rump: import librumpuser
Without pthread support, the fibril implementation is used instead.
This commit is contained in:
parent
5dec96dcef
commit
6d280e2195
|
|
@ -959,6 +959,9 @@
|
|||
./usr/lib/librumpnet.so.0.0 minix-base rump
|
||||
./usr/lib/librumpnet.so.0 minix-base rump
|
||||
./usr/lib/librumpnet.so minix-base rump
|
||||
./usr/lib/librumpuser.so.0.1 minix-base rump
|
||||
./usr/lib/librumpuser.so.0 minix-base rump
|
||||
./usr/lib/librumpuser.so minix-base rump
|
||||
./usr/lib/librumpvfs.so.0.0 minix-base rump
|
||||
./usr/lib/librumpvfs.so.0 minix-base rump
|
||||
./usr/lib/librumpvfs.so minix-base rump
|
||||
|
|
|
|||
|
|
@ -1724,6 +1724,8 @@
|
|||
./usr/include/rump/rumpkern_if_pub.h minix-comp rump
|
||||
./usr/include/rump/rumpnet_if_pub.h minix-comp rump
|
||||
./usr/include/rump/rumpuser.h minix-comp rump
|
||||
./usr/include/rump/rumpuser_component.h minix-comp rump
|
||||
./usr/include/rump/rumpuser_port.h minix-comp rump
|
||||
./usr/include/rump/rumpvfs_if_pub.h minix-comp rump
|
||||
./usr/include/rump/rumpvnode_if.h minix-comp rump
|
||||
./usr/include/saslc.h minix-comp crypto
|
||||
|
|
@ -2354,6 +2356,8 @@
|
|||
./usr/lib/librumpkern_z_pic.a minix-comp rump
|
||||
./usr/lib/librumpnet.a minix-comp rump
|
||||
./usr/lib/librumpnet_pic.a minix-comp rump
|
||||
./usr/lib/librumpuser.a minix-comp rump
|
||||
./usr/lib/librumpuser_pic.a minix-comp rump
|
||||
./usr/lib/librumpvfs.a minix-comp rump
|
||||
./usr/lib/librumpvfs_aio.a minix-comp rump
|
||||
./usr/lib/librumpvfs_aio_pic.a minix-comp rump
|
||||
|
|
|
|||
|
|
@ -189,7 +189,7 @@ SUBDIR+= libexecinfo # depends on libelf
|
|||
SUBDIR+= librefuse # depends on libpuffs
|
||||
#SUBDIR+= libisns # depends on libpthread
|
||||
.if (${MKRUMP} != "no")
|
||||
#SUBDIR+= librumpuser # depends on libpthread
|
||||
SUBDIR+= librumpuser # depends on libpthread
|
||||
#SUBDIR+= librumphijack # depends on librumpclient and libpthread
|
||||
.endif
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
RUMPTOP= ${.CURDIR}/../../sys/rump
|
||||
|
||||
#LIBDPLIBS+= rumpuser ${.CURDIR}/../librumpuser
|
||||
LIBDPLIBS+= rumpuser ${.CURDIR}/../librumpuser
|
||||
|
||||
WARNS= 3 # XXX: kernel isn't ready for -Wsign-compare
|
||||
|
||||
|
|
|
|||
61
lib/librumpuser/Makefile
Normal file
61
lib/librumpuser/Makefile
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
# $NetBSD: Makefile,v 1.23 2014/11/09 17:39:37 pooka Exp $
|
||||
#
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
WARNS?= 5
|
||||
|
||||
# rumpuser.h is in sys/rump for inclusion by kernel components
|
||||
.PATH: ${.CURDIR}/../../sys/rump/include/rump
|
||||
|
||||
.if defined(__MINIX)
|
||||
RUMPUSER_THREADS=fiber
|
||||
.else
|
||||
RUMPUSER_THREADS?=pthread
|
||||
.endif
|
||||
|
||||
LIB= rumpuser
|
||||
|
||||
.if ${RUMPUSER_THREADS} == "pthread"
|
||||
LIBDPLIBS+= pthread ${.CURDIR}/../libpthread
|
||||
.endif
|
||||
.for lib in ${RUMPUSER_EXTERNAL_DPLIBS}
|
||||
LIBDO.${lib}= _external
|
||||
LIBDPLIBS+= ${lib} lib
|
||||
.endfor
|
||||
CPPFLAGS+= -DLIBRUMPUSER
|
||||
#CPPFLAGS+= -D_DIAGNOSTIC
|
||||
|
||||
|
||||
.if ${RUMPUSER_THREADS} == "pthread"
|
||||
SRCS= rumpuser.c rumpuser_pth.c rumpuser_bio.c
|
||||
SRCS+= rumpuser_sp.c
|
||||
.elif ${RUMPUSER_THREADS} == "none"
|
||||
SRCS= rumpuser.c rumpuser_pth_dummy.c rumpuser_bio.c
|
||||
SRCS+= rumpuser_sp.c
|
||||
.elif ${RUMPUSER_THREADS} == "fiber"
|
||||
.if defined(RUMP_CURLWP)
|
||||
.if ${RUMP_CURLWP} != "hypercall"
|
||||
.error Unsupported curlwp scheme for thread model: ${RUMP_CURLWP}
|
||||
.endif
|
||||
.endif
|
||||
SRCS= rumpfiber.c rumpfiber_bio.c
|
||||
SRCS+= rumpfiber_sp.c
|
||||
.else
|
||||
.error Unsupported rumpuser threading type: ${RUMPUSER_THREADS}
|
||||
.endif
|
||||
|
||||
SRCS+= rumpuser_component.c rumpuser_random.c
|
||||
SRCS+= rumpuser_file.c rumpuser_mem.c
|
||||
|
||||
SRCS+= rumpuser_errtrans.c rumpuser_sigtrans.c
|
||||
|
||||
# optional
|
||||
SRCS+= rumpuser_dl.c rumpuser_daemonize.c
|
||||
|
||||
INCSDIR= /usr/include/rump
|
||||
INCS= rumpuser_component.h rumpuser_port.h
|
||||
|
||||
CPPFLAGS+= -D_REENTRANT
|
||||
|
||||
.include <bsd.lib.mk>
|
||||
347
lib/librumpuser/build-aux/compile
Executable file
347
lib/librumpuser/build-aux/compile
Executable file
|
|
@ -0,0 +1,347 @@
|
|||
#! /bin/sh
|
||||
# Wrapper for compilers which do not understand '-c -o'.
|
||||
|
||||
scriptversion=2012-10-14.11; # UTC
|
||||
|
||||
# Copyright (C) 1999-2013 Free Software Foundation, Inc.
|
||||
# Written by Tom Tromey <tromey@cygnus.com>.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# This file is maintained in Automake, please report
|
||||
# bugs to <bug-automake@gnu.org> or send patches to
|
||||
# <automake-patches@gnu.org>.
|
||||
|
||||
nl='
|
||||
'
|
||||
|
||||
# We need space, tab and new line, in precisely that order. Quoting is
|
||||
# there to prevent tools from complaining about whitespace usage.
|
||||
IFS=" "" $nl"
|
||||
|
||||
file_conv=
|
||||
|
||||
# func_file_conv build_file lazy
|
||||
# Convert a $build file to $host form and store it in $file
|
||||
# Currently only supports Windows hosts. If the determined conversion
|
||||
# type is listed in (the comma separated) LAZY, no conversion will
|
||||
# take place.
|
||||
func_file_conv ()
|
||||
{
|
||||
file=$1
|
||||
case $file in
|
||||
/ | /[!/]*) # absolute file, and not a UNC file
|
||||
if test -z "$file_conv"; then
|
||||
# lazily determine how to convert abs files
|
||||
case `uname -s` in
|
||||
MINGW*)
|
||||
file_conv=mingw
|
||||
;;
|
||||
CYGWIN*)
|
||||
file_conv=cygwin
|
||||
;;
|
||||
*)
|
||||
file_conv=wine
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
case $file_conv/,$2, in
|
||||
*,$file_conv,*)
|
||||
;;
|
||||
mingw/*)
|
||||
file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
|
||||
;;
|
||||
cygwin/*)
|
||||
file=`cygpath -m "$file" || echo "$file"`
|
||||
;;
|
||||
wine/*)
|
||||
file=`winepath -w "$file" || echo "$file"`
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# func_cl_dashL linkdir
|
||||
# Make cl look for libraries in LINKDIR
|
||||
func_cl_dashL ()
|
||||
{
|
||||
func_file_conv "$1"
|
||||
if test -z "$lib_path"; then
|
||||
lib_path=$file
|
||||
else
|
||||
lib_path="$lib_path;$file"
|
||||
fi
|
||||
linker_opts="$linker_opts -LIBPATH:$file"
|
||||
}
|
||||
|
||||
# func_cl_dashl library
|
||||
# Do a library search-path lookup for cl
|
||||
func_cl_dashl ()
|
||||
{
|
||||
lib=$1
|
||||
found=no
|
||||
save_IFS=$IFS
|
||||
IFS=';'
|
||||
for dir in $lib_path $LIB
|
||||
do
|
||||
IFS=$save_IFS
|
||||
if $shared && test -f "$dir/$lib.dll.lib"; then
|
||||
found=yes
|
||||
lib=$dir/$lib.dll.lib
|
||||
break
|
||||
fi
|
||||
if test -f "$dir/$lib.lib"; then
|
||||
found=yes
|
||||
lib=$dir/$lib.lib
|
||||
break
|
||||
fi
|
||||
if test -f "$dir/lib$lib.a"; then
|
||||
found=yes
|
||||
lib=$dir/lib$lib.a
|
||||
break
|
||||
fi
|
||||
done
|
||||
IFS=$save_IFS
|
||||
|
||||
if test "$found" != yes; then
|
||||
lib=$lib.lib
|
||||
fi
|
||||
}
|
||||
|
||||
# func_cl_wrapper cl arg...
|
||||
# Adjust compile command to suit cl
|
||||
func_cl_wrapper ()
|
||||
{
|
||||
# Assume a capable shell
|
||||
lib_path=
|
||||
shared=:
|
||||
linker_opts=
|
||||
for arg
|
||||
do
|
||||
if test -n "$eat"; then
|
||||
eat=
|
||||
else
|
||||
case $1 in
|
||||
-o)
|
||||
# configure might choose to run compile as 'compile cc -o foo foo.c'.
|
||||
eat=1
|
||||
case $2 in
|
||||
*.o | *.[oO][bB][jJ])
|
||||
func_file_conv "$2"
|
||||
set x "$@" -Fo"$file"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
func_file_conv "$2"
|
||||
set x "$@" -Fe"$file"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
-I)
|
||||
eat=1
|
||||
func_file_conv "$2" mingw
|
||||
set x "$@" -I"$file"
|
||||
shift
|
||||
;;
|
||||
-I*)
|
||||
func_file_conv "${1#-I}" mingw
|
||||
set x "$@" -I"$file"
|
||||
shift
|
||||
;;
|
||||
-l)
|
||||
eat=1
|
||||
func_cl_dashl "$2"
|
||||
set x "$@" "$lib"
|
||||
shift
|
||||
;;
|
||||
-l*)
|
||||
func_cl_dashl "${1#-l}"
|
||||
set x "$@" "$lib"
|
||||
shift
|
||||
;;
|
||||
-L)
|
||||
eat=1
|
||||
func_cl_dashL "$2"
|
||||
;;
|
||||
-L*)
|
||||
func_cl_dashL "${1#-L}"
|
||||
;;
|
||||
-static)
|
||||
shared=false
|
||||
;;
|
||||
-Wl,*)
|
||||
arg=${1#-Wl,}
|
||||
save_ifs="$IFS"; IFS=','
|
||||
for flag in $arg; do
|
||||
IFS="$save_ifs"
|
||||
linker_opts="$linker_opts $flag"
|
||||
done
|
||||
IFS="$save_ifs"
|
||||
;;
|
||||
-Xlinker)
|
||||
eat=1
|
||||
linker_opts="$linker_opts $2"
|
||||
;;
|
||||
-*)
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
*.cc | *.CC | *.cxx | *.CXX | *.[cC]++)
|
||||
func_file_conv "$1"
|
||||
set x "$@" -Tp"$file"
|
||||
shift
|
||||
;;
|
||||
*.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO])
|
||||
func_file_conv "$1" mingw
|
||||
set x "$@" "$file"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
shift
|
||||
done
|
||||
if test -n "$linker_opts"; then
|
||||
linker_opts="-link$linker_opts"
|
||||
fi
|
||||
exec "$@" $linker_opts
|
||||
exit 1
|
||||
}
|
||||
|
||||
eat=
|
||||
|
||||
case $1 in
|
||||
'')
|
||||
echo "$0: No command. Try '$0 --help' for more information." 1>&2
|
||||
exit 1;
|
||||
;;
|
||||
-h | --h*)
|
||||
cat <<\EOF
|
||||
Usage: compile [--help] [--version] PROGRAM [ARGS]
|
||||
|
||||
Wrapper for compilers which do not understand '-c -o'.
|
||||
Remove '-o dest.o' from ARGS, run PROGRAM with the remaining
|
||||
arguments, and rename the output as expected.
|
||||
|
||||
If you are trying to build a whole package this is not the
|
||||
right script to run: please start by reading the file 'INSTALL'.
|
||||
|
||||
Report bugs to <bug-automake@gnu.org>.
|
||||
EOF
|
||||
exit $?
|
||||
;;
|
||||
-v | --v*)
|
||||
echo "compile $scriptversion"
|
||||
exit $?
|
||||
;;
|
||||
cl | *[/\\]cl | cl.exe | *[/\\]cl.exe )
|
||||
func_cl_wrapper "$@" # Doesn't return...
|
||||
;;
|
||||
esac
|
||||
|
||||
ofile=
|
||||
cfile=
|
||||
|
||||
for arg
|
||||
do
|
||||
if test -n "$eat"; then
|
||||
eat=
|
||||
else
|
||||
case $1 in
|
||||
-o)
|
||||
# configure might choose to run compile as 'compile cc -o foo foo.c'.
|
||||
# So we strip '-o arg' only if arg is an object.
|
||||
eat=1
|
||||
case $2 in
|
||||
*.o | *.obj)
|
||||
ofile=$2
|
||||
;;
|
||||
*)
|
||||
set x "$@" -o "$2"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*.c)
|
||||
cfile=$1
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
shift
|
||||
done
|
||||
|
||||
if test -z "$ofile" || test -z "$cfile"; then
|
||||
# If no '-o' option was seen then we might have been invoked from a
|
||||
# pattern rule where we don't need one. That is ok -- this is a
|
||||
# normal compilation that the losing compiler can handle. If no
|
||||
# '.c' file was seen then we are probably linking. That is also
|
||||
# ok.
|
||||
exec "$@"
|
||||
fi
|
||||
|
||||
# Name of file we expect compiler to create.
|
||||
cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'`
|
||||
|
||||
# Create the lock directory.
|
||||
# Note: use '[/\\:.-]' here to ensure that we don't use the same name
|
||||
# that we are using for the .o file. Also, base the name on the expected
|
||||
# object file name, since that is what matters with a parallel build.
|
||||
lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d
|
||||
while true; do
|
||||
if mkdir "$lockdir" >/dev/null 2>&1; then
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
# FIXME: race condition here if user kills between mkdir and trap.
|
||||
trap "rmdir '$lockdir'; exit 1" 1 2 15
|
||||
|
||||
# Run the compile.
|
||||
"$@"
|
||||
ret=$?
|
||||
|
||||
if test -f "$cofile"; then
|
||||
test "$cofile" = "$ofile" || mv "$cofile" "$ofile"
|
||||
elif test -f "${cofile}bj"; then
|
||||
test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile"
|
||||
fi
|
||||
|
||||
rmdir "$lockdir"
|
||||
exit $ret
|
||||
|
||||
# Local Variables:
|
||||
# mode: shell-script
|
||||
# sh-indentation: 2
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
||||
1558
lib/librumpuser/build-aux/config.guess
vendored
Executable file
1558
lib/librumpuser/build-aux/config.guess
vendored
Executable file
File diff suppressed because it is too large
Load Diff
1791
lib/librumpuser/build-aux/config.sub
vendored
Executable file
1791
lib/librumpuser/build-aux/config.sub
vendored
Executable file
File diff suppressed because it is too large
Load Diff
791
lib/librumpuser/build-aux/depcomp
Executable file
791
lib/librumpuser/build-aux/depcomp
Executable file
|
|
@ -0,0 +1,791 @@
|
|||
#! /bin/sh
|
||||
# depcomp - compile a program generating dependencies as side-effects
|
||||
|
||||
scriptversion=2013-05-30.07; # UTC
|
||||
|
||||
# Copyright (C) 1999-2013 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
|
||||
|
||||
case $1 in
|
||||
'')
|
||||
echo "$0: No command. Try '$0 --help' for more information." 1>&2
|
||||
exit 1;
|
||||
;;
|
||||
-h | --h*)
|
||||
cat <<\EOF
|
||||
Usage: depcomp [--help] [--version] PROGRAM [ARGS]
|
||||
|
||||
Run PROGRAMS ARGS to compile a file, generating dependencies
|
||||
as side-effects.
|
||||
|
||||
Environment variables:
|
||||
depmode Dependency tracking mode.
|
||||
source Source file read by 'PROGRAMS ARGS'.
|
||||
object Object file output by 'PROGRAMS ARGS'.
|
||||
DEPDIR directory where to store dependencies.
|
||||
depfile Dependency file to output.
|
||||
tmpdepfile Temporary file to use when outputting dependencies.
|
||||
libtool Whether libtool is used (yes/no).
|
||||
|
||||
Report bugs to <bug-automake@gnu.org>.
|
||||
EOF
|
||||
exit $?
|
||||
;;
|
||||
-v | --v*)
|
||||
echo "depcomp $scriptversion"
|
||||
exit $?
|
||||
;;
|
||||
esac
|
||||
|
||||
# Get the directory component of the given path, and save it in the
|
||||
# global variables '$dir'. Note that this directory component will
|
||||
# be either empty or ending with a '/' character. This is deliberate.
|
||||
set_dir_from ()
|
||||
{
|
||||
case $1 in
|
||||
*/*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;;
|
||||
*) dir=;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Get the suffix-stripped basename of the given path, and save it the
|
||||
# global variable '$base'.
|
||||
set_base_from ()
|
||||
{
|
||||
base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'`
|
||||
}
|
||||
|
||||
# If no dependency file was actually created by the compiler invocation,
|
||||
# we still have to create a dummy depfile, to avoid errors with the
|
||||
# Makefile "include basename.Plo" scheme.
|
||||
make_dummy_depfile ()
|
||||
{
|
||||
echo "#dummy" > "$depfile"
|
||||
}
|
||||
|
||||
# Factor out some common post-processing of the generated depfile.
|
||||
# Requires the auxiliary global variable '$tmpdepfile' to be set.
|
||||
aix_post_process_depfile ()
|
||||
{
|
||||
# If the compiler actually managed to produce a dependency file,
|
||||
# post-process it.
|
||||
if test -f "$tmpdepfile"; then
|
||||
# Each line is of the form 'foo.o: dependency.h'.
|
||||
# Do two passes, one to just change these to
|
||||
# $object: dependency.h
|
||||
# and one to simply output
|
||||
# dependency.h:
|
||||
# which is needed to avoid the deleted-header problem.
|
||||
{ sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile"
|
||||
sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile"
|
||||
} > "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
else
|
||||
make_dummy_depfile
|
||||
fi
|
||||
}
|
||||
|
||||
# A tabulation character.
|
||||
tab=' '
|
||||
# A newline character.
|
||||
nl='
|
||||
'
|
||||
# Character ranges might be problematic outside the C locale.
|
||||
# These definitions help.
|
||||
upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ
|
||||
lower=abcdefghijklmnopqrstuvwxyz
|
||||
digits=0123456789
|
||||
alpha=${upper}${lower}
|
||||
|
||||
if test -z "$depmode" || test -z "$source" || test -z "$object"; then
|
||||
echo "depcomp: Variables source, object and depmode must be set" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
|
||||
depfile=${depfile-`echo "$object" |
|
||||
sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
|
||||
tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
|
||||
|
||||
rm -f "$tmpdepfile"
|
||||
|
||||
# Avoid interferences from the environment.
|
||||
gccflag= dashmflag=
|
||||
|
||||
# Some modes work just like other modes, but use different flags. We
|
||||
# parameterize here, but still list the modes in the big case below,
|
||||
# to make depend.m4 easier to write. Note that we *cannot* use a case
|
||||
# here, because this file can only contain one case statement.
|
||||
if test "$depmode" = hp; then
|
||||
# HP compiler uses -M and no extra arg.
|
||||
gccflag=-M
|
||||
depmode=gcc
|
||||
fi
|
||||
|
||||
if test "$depmode" = dashXmstdout; then
|
||||
# This is just like dashmstdout with a different argument.
|
||||
dashmflag=-xM
|
||||
depmode=dashmstdout
|
||||
fi
|
||||
|
||||
cygpath_u="cygpath -u -f -"
|
||||
if test "$depmode" = msvcmsys; then
|
||||
# This is just like msvisualcpp but w/o cygpath translation.
|
||||
# Just convert the backslash-escaped backslashes to single forward
|
||||
# slashes to satisfy depend.m4
|
||||
cygpath_u='sed s,\\\\,/,g'
|
||||
depmode=msvisualcpp
|
||||
fi
|
||||
|
||||
if test "$depmode" = msvc7msys; then
|
||||
# This is just like msvc7 but w/o cygpath translation.
|
||||
# Just convert the backslash-escaped backslashes to single forward
|
||||
# slashes to satisfy depend.m4
|
||||
cygpath_u='sed s,\\\\,/,g'
|
||||
depmode=msvc7
|
||||
fi
|
||||
|
||||
if test "$depmode" = xlc; then
|
||||
# IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information.
|
||||
gccflag=-qmakedep=gcc,-MF
|
||||
depmode=gcc
|
||||
fi
|
||||
|
||||
case "$depmode" in
|
||||
gcc3)
|
||||
## gcc 3 implements dependency tracking that does exactly what
|
||||
## we want. Yay! Note: for some reason libtool 1.4 doesn't like
|
||||
## it if -MD -MP comes after the -MF stuff. Hmm.
|
||||
## Unfortunately, FreeBSD c89 acceptance of flags depends upon
|
||||
## the command line argument order; so add the flags where they
|
||||
## appear in depend2.am. Note that the slowdown incurred here
|
||||
## affects only configure: in makefiles, %FASTDEP% shortcuts this.
|
||||
for arg
|
||||
do
|
||||
case $arg in
|
||||
-c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
|
||||
*) set fnord "$@" "$arg" ;;
|
||||
esac
|
||||
shift # fnord
|
||||
shift # $arg
|
||||
done
|
||||
"$@"
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
mv "$tmpdepfile" "$depfile"
|
||||
;;
|
||||
|
||||
gcc)
|
||||
## Note that this doesn't just cater to obsosete pre-3.x GCC compilers.
|
||||
## but also to in-use compilers like IMB xlc/xlC and the HP C compiler.
|
||||
## (see the conditional assignment to $gccflag above).
|
||||
## There are various ways to get dependency output from gcc. Here's
|
||||
## why we pick this rather obscure method:
|
||||
## - Don't want to use -MD because we'd like the dependencies to end
|
||||
## up in a subdir. Having to rename by hand is ugly.
|
||||
## (We might end up doing this anyway to support other compilers.)
|
||||
## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
|
||||
## -MM, not -M (despite what the docs say). Also, it might not be
|
||||
## supported by the other compilers which use the 'gcc' depmode.
|
||||
## - Using -M directly means running the compiler twice (even worse
|
||||
## than renaming).
|
||||
if test -z "$gccflag"; then
|
||||
gccflag=-MD,
|
||||
fi
|
||||
"$@" -Wp,"$gccflag$tmpdepfile"
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
# The second -e expression handles DOS-style file names with drive
|
||||
# letters.
|
||||
sed -e 's/^[^:]*: / /' \
|
||||
-e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
|
||||
## This next piece of magic avoids the "deleted header file" problem.
|
||||
## The problem is that when a header file which appears in a .P file
|
||||
## is deleted, the dependency causes make to die (because there is
|
||||
## typically no way to rebuild the header). We avoid this by adding
|
||||
## dummy dependencies for each header file. Too bad gcc doesn't do
|
||||
## this for us directly.
|
||||
## Some versions of gcc put a space before the ':'. On the theory
|
||||
## that the space means something, we add a space to the output as
|
||||
## well. hp depmode also adds that space, but also prefixes the VPATH
|
||||
## to the object. Take care to not repeat it in the output.
|
||||
## Some versions of the HPUX 10.20 sed can't process this invocation
|
||||
## correctly. Breaking it into two sed invocations is a workaround.
|
||||
tr ' ' "$nl" < "$tmpdepfile" \
|
||||
| sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \
|
||||
| sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
hp)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
sgi)
|
||||
if test "$libtool" = yes; then
|
||||
"$@" "-Wp,-MDupdate,$tmpdepfile"
|
||||
else
|
||||
"$@" -MDupdate "$tmpdepfile"
|
||||
fi
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
|
||||
if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
|
||||
echo "$object : \\" > "$depfile"
|
||||
# Clip off the initial element (the dependent). Don't try to be
|
||||
# clever and replace this with sed code, as IRIX sed won't handle
|
||||
# lines with more than a fixed number of characters (4096 in
|
||||
# IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
|
||||
# the IRIX cc adds comments like '#:fec' to the end of the
|
||||
# dependency line.
|
||||
tr ' ' "$nl" < "$tmpdepfile" \
|
||||
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \
|
||||
| tr "$nl" ' ' >> "$depfile"
|
||||
echo >> "$depfile"
|
||||
# The second pass generates a dummy entry for each header file.
|
||||
tr ' ' "$nl" < "$tmpdepfile" \
|
||||
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
|
||||
>> "$depfile"
|
||||
else
|
||||
make_dummy_depfile
|
||||
fi
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
xlc)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
aix)
|
||||
# The C for AIX Compiler uses -M and outputs the dependencies
|
||||
# in a .u file. In older versions, this file always lives in the
|
||||
# current directory. Also, the AIX compiler puts '$object:' at the
|
||||
# start of each line; $object doesn't have directory information.
|
||||
# Version 6 uses the directory in both cases.
|
||||
set_dir_from "$object"
|
||||
set_base_from "$object"
|
||||
if test "$libtool" = yes; then
|
||||
tmpdepfile1=$dir$base.u
|
||||
tmpdepfile2=$base.u
|
||||
tmpdepfile3=$dir.libs/$base.u
|
||||
"$@" -Wc,-M
|
||||
else
|
||||
tmpdepfile1=$dir$base.u
|
||||
tmpdepfile2=$dir$base.u
|
||||
tmpdepfile3=$dir$base.u
|
||||
"$@" -M
|
||||
fi
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||
exit $stat
|
||||
fi
|
||||
|
||||
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||
do
|
||||
test -f "$tmpdepfile" && break
|
||||
done
|
||||
aix_post_process_depfile
|
||||
;;
|
||||
|
||||
tcc)
|
||||
# tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26
|
||||
# FIXME: That version still under development at the moment of writing.
|
||||
# Make that this statement remains true also for stable, released
|
||||
# versions.
|
||||
# It will wrap lines (doesn't matter whether long or short) with a
|
||||
# trailing '\', as in:
|
||||
#
|
||||
# foo.o : \
|
||||
# foo.c \
|
||||
# foo.h \
|
||||
#
|
||||
# It will put a trailing '\' even on the last line, and will use leading
|
||||
# spaces rather than leading tabs (at least since its commit 0394caf7
|
||||
# "Emit spaces for -MD").
|
||||
"$@" -MD -MF "$tmpdepfile"
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
# Each non-empty line is of the form 'foo.o : \' or ' dep.h \'.
|
||||
# We have to change lines of the first kind to '$object: \'.
|
||||
sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile"
|
||||
# And for each line of the second kind, we have to emit a 'dep.h:'
|
||||
# dummy dependency, to avoid the deleted-header problem.
|
||||
sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
## The order of this option in the case statement is important, since the
|
||||
## shell code in configure will try each of these formats in the order
|
||||
## listed in this file. A plain '-MD' option would be understood by many
|
||||
## compilers, so we must ensure this comes after the gcc and icc options.
|
||||
pgcc)
|
||||
# Portland's C compiler understands '-MD'.
|
||||
# Will always output deps to 'file.d' where file is the root name of the
|
||||
# source file under compilation, even if file resides in a subdirectory.
|
||||
# The object file name does not affect the name of the '.d' file.
|
||||
# pgcc 10.2 will output
|
||||
# foo.o: sub/foo.c sub/foo.h
|
||||
# and will wrap long lines using '\' :
|
||||
# foo.o: sub/foo.c ... \
|
||||
# sub/foo.h ... \
|
||||
# ...
|
||||
set_dir_from "$object"
|
||||
# Use the source, not the object, to determine the base name, since
|
||||
# that's sadly what pgcc will do too.
|
||||
set_base_from "$source"
|
||||
tmpdepfile=$base.d
|
||||
|
||||
# For projects that build the same source file twice into different object
|
||||
# files, the pgcc approach of using the *source* file root name can cause
|
||||
# problems in parallel builds. Use a locking strategy to avoid stomping on
|
||||
# the same $tmpdepfile.
|
||||
lockdir=$base.d-lock
|
||||
trap "
|
||||
echo '$0: caught signal, cleaning up...' >&2
|
||||
rmdir '$lockdir'
|
||||
exit 1
|
||||
" 1 2 13 15
|
||||
numtries=100
|
||||
i=$numtries
|
||||
while test $i -gt 0; do
|
||||
# mkdir is a portable test-and-set.
|
||||
if mkdir "$lockdir" 2>/dev/null; then
|
||||
# This process acquired the lock.
|
||||
"$@" -MD
|
||||
stat=$?
|
||||
# Release the lock.
|
||||
rmdir "$lockdir"
|
||||
break
|
||||
else
|
||||
# If the lock is being held by a different process, wait
|
||||
# until the winning process is done or we timeout.
|
||||
while test -d "$lockdir" && test $i -gt 0; do
|
||||
sleep 1
|
||||
i=`expr $i - 1`
|
||||
done
|
||||
fi
|
||||
i=`expr $i - 1`
|
||||
done
|
||||
trap - 1 2 13 15
|
||||
if test $i -le 0; then
|
||||
echo "$0: failed to acquire lock after $numtries attempts" >&2
|
||||
echo "$0: check lockdir '$lockdir'" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
# Each line is of the form `foo.o: dependent.h',
|
||||
# or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
|
||||
# Do two passes, one to just change these to
|
||||
# `$object: dependent.h' and one to simply `dependent.h:'.
|
||||
sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
|
||||
# Some versions of the HPUX 10.20 sed can't process this invocation
|
||||
# correctly. Breaking it into two sed invocations is a workaround.
|
||||
sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \
|
||||
| sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
hp2)
|
||||
# The "hp" stanza above does not work with aCC (C++) and HP's ia64
|
||||
# compilers, which have integrated preprocessors. The correct option
|
||||
# to use with these is +Maked; it writes dependencies to a file named
|
||||
# 'foo.d', which lands next to the object file, wherever that
|
||||
# happens to be.
|
||||
# Much of this is similar to the tru64 case; see comments there.
|
||||
set_dir_from "$object"
|
||||
set_base_from "$object"
|
||||
if test "$libtool" = yes; then
|
||||
tmpdepfile1=$dir$base.d
|
||||
tmpdepfile2=$dir.libs/$base.d
|
||||
"$@" -Wc,+Maked
|
||||
else
|
||||
tmpdepfile1=$dir$base.d
|
||||
tmpdepfile2=$dir$base.d
|
||||
"$@" +Maked
|
||||
fi
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile1" "$tmpdepfile2"
|
||||
exit $stat
|
||||
fi
|
||||
|
||||
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
|
||||
do
|
||||
test -f "$tmpdepfile" && break
|
||||
done
|
||||
if test -f "$tmpdepfile"; then
|
||||
sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile"
|
||||
# Add 'dependent.h:' lines.
|
||||
sed -ne '2,${
|
||||
s/^ *//
|
||||
s/ \\*$//
|
||||
s/$/:/
|
||||
p
|
||||
}' "$tmpdepfile" >> "$depfile"
|
||||
else
|
||||
make_dummy_depfile
|
||||
fi
|
||||
rm -f "$tmpdepfile" "$tmpdepfile2"
|
||||
;;
|
||||
|
||||
tru64)
|
||||
# The Tru64 compiler uses -MD to generate dependencies as a side
|
||||
# effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'.
|
||||
# At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
|
||||
# dependencies in 'foo.d' instead, so we check for that too.
|
||||
# Subdirectories are respected.
|
||||
set_dir_from "$object"
|
||||
set_base_from "$object"
|
||||
|
||||
if test "$libtool" = yes; then
|
||||
# Libtool generates 2 separate objects for the 2 libraries. These
|
||||
# two compilations output dependencies in $dir.libs/$base.o.d and
|
||||
# in $dir$base.o.d. We have to check for both files, because
|
||||
# one of the two compilations can be disabled. We should prefer
|
||||
# $dir$base.o.d over $dir.libs/$base.o.d because the latter is
|
||||
# automatically cleaned when .libs/ is deleted, while ignoring
|
||||
# the former would cause a distcleancheck panic.
|
||||
tmpdepfile1=$dir$base.o.d # libtool 1.5
|
||||
tmpdepfile2=$dir.libs/$base.o.d # Likewise.
|
||||
tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504
|
||||
"$@" -Wc,-MD
|
||||
else
|
||||
tmpdepfile1=$dir$base.d
|
||||
tmpdepfile2=$dir$base.d
|
||||
tmpdepfile3=$dir$base.d
|
||||
"$@" -MD
|
||||
fi
|
||||
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||
exit $stat
|
||||
fi
|
||||
|
||||
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||
do
|
||||
test -f "$tmpdepfile" && break
|
||||
done
|
||||
# Same post-processing that is required for AIX mode.
|
||||
aix_post_process_depfile
|
||||
;;
|
||||
|
||||
msvc7)
|
||||
if test "$libtool" = yes; then
|
||||
showIncludes=-Wc,-showIncludes
|
||||
else
|
||||
showIncludes=-showIncludes
|
||||
fi
|
||||
"$@" $showIncludes > "$tmpdepfile"
|
||||
stat=$?
|
||||
grep -v '^Note: including file: ' "$tmpdepfile"
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
# The first sed program below extracts the file names and escapes
|
||||
# backslashes for cygpath. The second sed program outputs the file
|
||||
# name when reading, but also accumulates all include files in the
|
||||
# hold buffer in order to output them again at the end. This only
|
||||
# works with sed implementations that can handle large buffers.
|
||||
sed < "$tmpdepfile" -n '
|
||||
/^Note: including file: *\(.*\)/ {
|
||||
s//\1/
|
||||
s/\\/\\\\/g
|
||||
p
|
||||
}' | $cygpath_u | sort -u | sed -n '
|
||||
s/ /\\ /g
|
||||
s/\(.*\)/'"$tab"'\1 \\/p
|
||||
s/.\(.*\) \\/\1:/
|
||||
H
|
||||
$ {
|
||||
s/.*/'"$tab"'/
|
||||
G
|
||||
p
|
||||
}' >> "$depfile"
|
||||
echo >> "$depfile" # make sure the fragment doesn't end with a backslash
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
msvc7msys)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
#nosideeffect)
|
||||
# This comment above is used by automake to tell side-effect
|
||||
# dependency tracking mechanisms from slower ones.
|
||||
|
||||
dashmstdout)
|
||||
# Important note: in order to support this mode, a compiler *must*
|
||||
# always write the preprocessed file to stdout, regardless of -o.
|
||||
"$@" || exit $?
|
||||
|
||||
# Remove the call to Libtool.
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
|
||||
# Remove '-o $object'.
|
||||
IFS=" "
|
||||
for arg
|
||||
do
|
||||
case $arg in
|
||||
-o)
|
||||
shift
|
||||
;;
|
||||
$object)
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"
|
||||
shift # fnord
|
||||
shift # $arg
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
test -z "$dashmflag" && dashmflag=-M
|
||||
# Require at least two characters before searching for ':'
|
||||
# in the target name. This is to cope with DOS-style filenames:
|
||||
# a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise.
|
||||
"$@" $dashmflag |
|
||||
sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile"
|
||||
rm -f "$depfile"
|
||||
cat < "$tmpdepfile" > "$depfile"
|
||||
# Some versions of the HPUX 10.20 sed can't process this sed invocation
|
||||
# correctly. Breaking it into two sed invocations is a workaround.
|
||||
tr ' ' "$nl" < "$tmpdepfile" \
|
||||
| sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
|
||||
| sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
dashXmstdout)
|
||||
# This case only exists to satisfy depend.m4. It is never actually
|
||||
# run, as this mode is specially recognized in the preamble.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
makedepend)
|
||||
"$@" || exit $?
|
||||
# Remove any Libtool call
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
# X makedepend
|
||||
shift
|
||||
cleared=no eat=no
|
||||
for arg
|
||||
do
|
||||
case $cleared in
|
||||
no)
|
||||
set ""; shift
|
||||
cleared=yes ;;
|
||||
esac
|
||||
if test $eat = yes; then
|
||||
eat=no
|
||||
continue
|
||||
fi
|
||||
case "$arg" in
|
||||
-D*|-I*)
|
||||
set fnord "$@" "$arg"; shift ;;
|
||||
# Strip any option that makedepend may not understand. Remove
|
||||
# the object too, otherwise makedepend will parse it as a source file.
|
||||
-arch)
|
||||
eat=yes ;;
|
||||
-*|$object)
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"; shift ;;
|
||||
esac
|
||||
done
|
||||
obj_suffix=`echo "$object" | sed 's/^.*\././'`
|
||||
touch "$tmpdepfile"
|
||||
${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
|
||||
rm -f "$depfile"
|
||||
# makedepend may prepend the VPATH from the source file name to the object.
|
||||
# No need to regex-escape $object, excess matching of '.' is harmless.
|
||||
sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile"
|
||||
# Some versions of the HPUX 10.20 sed can't process the last invocation
|
||||
# correctly. Breaking it into two sed invocations is a workaround.
|
||||
sed '1,2d' "$tmpdepfile" \
|
||||
| tr ' ' "$nl" \
|
||||
| sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
|
||||
| sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile" "$tmpdepfile".bak
|
||||
;;
|
||||
|
||||
cpp)
|
||||
# Important note: in order to support this mode, a compiler *must*
|
||||
# always write the preprocessed file to stdout.
|
||||
"$@" || exit $?
|
||||
|
||||
# Remove the call to Libtool.
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
|
||||
# Remove '-o $object'.
|
||||
IFS=" "
|
||||
for arg
|
||||
do
|
||||
case $arg in
|
||||
-o)
|
||||
shift
|
||||
;;
|
||||
$object)
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"
|
||||
shift # fnord
|
||||
shift # $arg
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
"$@" -E \
|
||||
| sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
|
||||
-e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
|
||||
| sed '$ s: \\$::' > "$tmpdepfile"
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
cat < "$tmpdepfile" >> "$depfile"
|
||||
sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
msvisualcpp)
|
||||
# Important note: in order to support this mode, a compiler *must*
|
||||
# always write the preprocessed file to stdout.
|
||||
"$@" || exit $?
|
||||
|
||||
# Remove the call to Libtool.
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
|
||||
IFS=" "
|
||||
for arg
|
||||
do
|
||||
case "$arg" in
|
||||
-o)
|
||||
shift
|
||||
;;
|
||||
$object)
|
||||
shift
|
||||
;;
|
||||
"-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
|
||||
set fnord "$@"
|
||||
shift
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"
|
||||
shift
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
"$@" -E 2>/dev/null |
|
||||
sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile"
|
||||
echo "$tab" >> "$depfile"
|
||||
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
msvcmsys)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
none)
|
||||
exec "$@"
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Unknown depmode $depmode" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
|
||||
# Local Variables:
|
||||
# mode: shell-script
|
||||
# sh-indentation: 2
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
||||
527
lib/librumpuser/build-aux/install-sh
Executable file
527
lib/librumpuser/build-aux/install-sh
Executable file
|
|
@ -0,0 +1,527 @@
|
|||
#!/bin/sh
|
||||
# install - install a program, script, or datafile
|
||||
|
||||
scriptversion=2011-11-20.07; # UTC
|
||||
|
||||
# This originates from X11R5 (mit/util/scripts/install.sh), which was
|
||||
# later released in X11R6 (xc/config/util/install.sh) with the
|
||||
# following copyright and license.
|
||||
#
|
||||
# Copyright (C) 1994 X Consortium
|
||||
#
|
||||
# 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
|
||||
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
|
||||
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
# Except as contained in this notice, the name of the X Consortium shall not
|
||||
# be used in advertising or otherwise to promote the sale, use or other deal-
|
||||
# ings in this Software without prior written authorization from the X Consor-
|
||||
# tium.
|
||||
#
|
||||
#
|
||||
# FSF changes to this file are in the public domain.
|
||||
#
|
||||
# Calling this script install-sh is preferred over install.sh, to prevent
|
||||
# 'make' implicit rules from creating a file called install from it
|
||||
# when there is no Makefile.
|
||||
#
|
||||
# This script is compatible with the BSD install script, but was written
|
||||
# from scratch.
|
||||
|
||||
nl='
|
||||
'
|
||||
IFS=" "" $nl"
|
||||
|
||||
# set DOITPROG to echo to test this script
|
||||
|
||||
# Don't use :- since 4.3BSD and earlier shells don't like it.
|
||||
doit=${DOITPROG-}
|
||||
if test -z "$doit"; then
|
||||
doit_exec=exec
|
||||
else
|
||||
doit_exec=$doit
|
||||
fi
|
||||
|
||||
# Put in absolute file names if you don't have them in your path;
|
||||
# or use environment vars.
|
||||
|
||||
chgrpprog=${CHGRPPROG-chgrp}
|
||||
chmodprog=${CHMODPROG-chmod}
|
||||
chownprog=${CHOWNPROG-chown}
|
||||
cmpprog=${CMPPROG-cmp}
|
||||
cpprog=${CPPROG-cp}
|
||||
mkdirprog=${MKDIRPROG-mkdir}
|
||||
mvprog=${MVPROG-mv}
|
||||
rmprog=${RMPROG-rm}
|
||||
stripprog=${STRIPPROG-strip}
|
||||
|
||||
posix_glob='?'
|
||||
initialize_posix_glob='
|
||||
test "$posix_glob" != "?" || {
|
||||
if (set -f) 2>/dev/null; then
|
||||
posix_glob=
|
||||
else
|
||||
posix_glob=:
|
||||
fi
|
||||
}
|
||||
'
|
||||
|
||||
posix_mkdir=
|
||||
|
||||
# Desired mode of installed file.
|
||||
mode=0755
|
||||
|
||||
chgrpcmd=
|
||||
chmodcmd=$chmodprog
|
||||
chowncmd=
|
||||
mvcmd=$mvprog
|
||||
rmcmd="$rmprog -f"
|
||||
stripcmd=
|
||||
|
||||
src=
|
||||
dst=
|
||||
dir_arg=
|
||||
dst_arg=
|
||||
|
||||
copy_on_change=false
|
||||
no_target_directory=
|
||||
|
||||
usage="\
|
||||
Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
|
||||
or: $0 [OPTION]... SRCFILES... DIRECTORY
|
||||
or: $0 [OPTION]... -t DIRECTORY SRCFILES...
|
||||
or: $0 [OPTION]... -d DIRECTORIES...
|
||||
|
||||
In the 1st form, copy SRCFILE to DSTFILE.
|
||||
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
|
||||
In the 4th, create DIRECTORIES.
|
||||
|
||||
Options:
|
||||
--help display this help and exit.
|
||||
--version display version info and exit.
|
||||
|
||||
-c (ignored)
|
||||
-C install only if different (preserve the last data modification time)
|
||||
-d create directories instead of installing files.
|
||||
-g GROUP $chgrpprog installed files to GROUP.
|
||||
-m MODE $chmodprog installed files to MODE.
|
||||
-o USER $chownprog installed files to USER.
|
||||
-s $stripprog installed files.
|
||||
-t DIRECTORY install into DIRECTORY.
|
||||
-T report an error if DSTFILE is a directory.
|
||||
|
||||
Environment variables override the default commands:
|
||||
CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
|
||||
RMPROG STRIPPROG
|
||||
"
|
||||
|
||||
while test $# -ne 0; do
|
||||
case $1 in
|
||||
-c) ;;
|
||||
|
||||
-C) copy_on_change=true;;
|
||||
|
||||
-d) dir_arg=true;;
|
||||
|
||||
-g) chgrpcmd="$chgrpprog $2"
|
||||
shift;;
|
||||
|
||||
--help) echo "$usage"; exit $?;;
|
||||
|
||||
-m) mode=$2
|
||||
case $mode in
|
||||
*' '* | *' '* | *'
|
||||
'* | *'*'* | *'?'* | *'['*)
|
||||
echo "$0: invalid mode: $mode" >&2
|
||||
exit 1;;
|
||||
esac
|
||||
shift;;
|
||||
|
||||
-o) chowncmd="$chownprog $2"
|
||||
shift;;
|
||||
|
||||
-s) stripcmd=$stripprog;;
|
||||
|
||||
-t) dst_arg=$2
|
||||
# Protect names problematic for 'test' and other utilities.
|
||||
case $dst_arg in
|
||||
-* | [=\(\)!]) dst_arg=./$dst_arg;;
|
||||
esac
|
||||
shift;;
|
||||
|
||||
-T) no_target_directory=true;;
|
||||
|
||||
--version) echo "$0 $scriptversion"; exit $?;;
|
||||
|
||||
--) shift
|
||||
break;;
|
||||
|
||||
-*) echo "$0: invalid option: $1" >&2
|
||||
exit 1;;
|
||||
|
||||
*) break;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
|
||||
# When -d is used, all remaining arguments are directories to create.
|
||||
# When -t is used, the destination is already specified.
|
||||
# Otherwise, the last argument is the destination. Remove it from $@.
|
||||
for arg
|
||||
do
|
||||
if test -n "$dst_arg"; then
|
||||
# $@ is not empty: it contains at least $arg.
|
||||
set fnord "$@" "$dst_arg"
|
||||
shift # fnord
|
||||
fi
|
||||
shift # arg
|
||||
dst_arg=$arg
|
||||
# Protect names problematic for 'test' and other utilities.
|
||||
case $dst_arg in
|
||||
-* | [=\(\)!]) dst_arg=./$dst_arg;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
|
||||
if test $# -eq 0; then
|
||||
if test -z "$dir_arg"; then
|
||||
echo "$0: no input file specified." >&2
|
||||
exit 1
|
||||
fi
|
||||
# It's OK to call 'install-sh -d' without argument.
|
||||
# This can happen when creating conditional directories.
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if test -z "$dir_arg"; then
|
||||
do_exit='(exit $ret); exit $ret'
|
||||
trap "ret=129; $do_exit" 1
|
||||
trap "ret=130; $do_exit" 2
|
||||
trap "ret=141; $do_exit" 13
|
||||
trap "ret=143; $do_exit" 15
|
||||
|
||||
# Set umask so as not to create temps with too-generous modes.
|
||||
# However, 'strip' requires both read and write access to temps.
|
||||
case $mode in
|
||||
# Optimize common cases.
|
||||
*644) cp_umask=133;;
|
||||
*755) cp_umask=22;;
|
||||
|
||||
*[0-7])
|
||||
if test -z "$stripcmd"; then
|
||||
u_plus_rw=
|
||||
else
|
||||
u_plus_rw='% 200'
|
||||
fi
|
||||
cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
|
||||
*)
|
||||
if test -z "$stripcmd"; then
|
||||
u_plus_rw=
|
||||
else
|
||||
u_plus_rw=,u+rw
|
||||
fi
|
||||
cp_umask=$mode$u_plus_rw;;
|
||||
esac
|
||||
fi
|
||||
|
||||
for src
|
||||
do
|
||||
# Protect names problematic for 'test' and other utilities.
|
||||
case $src in
|
||||
-* | [=\(\)!]) src=./$src;;
|
||||
esac
|
||||
|
||||
if test -n "$dir_arg"; then
|
||||
dst=$src
|
||||
dstdir=$dst
|
||||
test -d "$dstdir"
|
||||
dstdir_status=$?
|
||||
else
|
||||
|
||||
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command
|
||||
# might cause directories to be created, which would be especially bad
|
||||
# if $src (and thus $dsttmp) contains '*'.
|
||||
if test ! -f "$src" && test ! -d "$src"; then
|
||||
echo "$0: $src does not exist." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if test -z "$dst_arg"; then
|
||||
echo "$0: no destination specified." >&2
|
||||
exit 1
|
||||
fi
|
||||
dst=$dst_arg
|
||||
|
||||
# If destination is a directory, append the input filename; won't work
|
||||
# if double slashes aren't ignored.
|
||||
if test -d "$dst"; then
|
||||
if test -n "$no_target_directory"; then
|
||||
echo "$0: $dst_arg: Is a directory" >&2
|
||||
exit 1
|
||||
fi
|
||||
dstdir=$dst
|
||||
dst=$dstdir/`basename "$src"`
|
||||
dstdir_status=0
|
||||
else
|
||||
# Prefer dirname, but fall back on a substitute if dirname fails.
|
||||
dstdir=`
|
||||
(dirname "$dst") 2>/dev/null ||
|
||||
expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
|
||||
X"$dst" : 'X\(//\)[^/]' \| \
|
||||
X"$dst" : 'X\(//\)$' \| \
|
||||
X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
|
||||
echo X"$dst" |
|
||||
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
/^X\(\/\/\)[^/].*/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
/^X\(\/\/\)$/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
/^X\(\/\).*/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
s/.*/./; q'
|
||||
`
|
||||
|
||||
test -d "$dstdir"
|
||||
dstdir_status=$?
|
||||
fi
|
||||
fi
|
||||
|
||||
obsolete_mkdir_used=false
|
||||
|
||||
if test $dstdir_status != 0; then
|
||||
case $posix_mkdir in
|
||||
'')
|
||||
# Create intermediate dirs using mode 755 as modified by the umask.
|
||||
# This is like FreeBSD 'install' as of 1997-10-28.
|
||||
umask=`umask`
|
||||
case $stripcmd.$umask in
|
||||
# Optimize common cases.
|
||||
*[2367][2367]) mkdir_umask=$umask;;
|
||||
.*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
|
||||
|
||||
*[0-7])
|
||||
mkdir_umask=`expr $umask + 22 \
|
||||
- $umask % 100 % 40 + $umask % 20 \
|
||||
- $umask % 10 % 4 + $umask % 2
|
||||
`;;
|
||||
*) mkdir_umask=$umask,go-w;;
|
||||
esac
|
||||
|
||||
# With -d, create the new directory with the user-specified mode.
|
||||
# Otherwise, rely on $mkdir_umask.
|
||||
if test -n "$dir_arg"; then
|
||||
mkdir_mode=-m$mode
|
||||
else
|
||||
mkdir_mode=
|
||||
fi
|
||||
|
||||
posix_mkdir=false
|
||||
case $umask in
|
||||
*[123567][0-7][0-7])
|
||||
# POSIX mkdir -p sets u+wx bits regardless of umask, which
|
||||
# is incompatible with FreeBSD 'install' when (umask & 300) != 0.
|
||||
;;
|
||||
*)
|
||||
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
|
||||
trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
|
||||
|
||||
if (umask $mkdir_umask &&
|
||||
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
|
||||
then
|
||||
if test -z "$dir_arg" || {
|
||||
# Check for POSIX incompatibilities with -m.
|
||||
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
|
||||
# other-writable bit of parent directory when it shouldn't.
|
||||
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
|
||||
ls_ld_tmpdir=`ls -ld "$tmpdir"`
|
||||
case $ls_ld_tmpdir in
|
||||
d????-?r-*) different_mode=700;;
|
||||
d????-?--*) different_mode=755;;
|
||||
*) false;;
|
||||
esac &&
|
||||
$mkdirprog -m$different_mode -p -- "$tmpdir" && {
|
||||
ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
|
||||
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
|
||||
}
|
||||
}
|
||||
then posix_mkdir=:
|
||||
fi
|
||||
rmdir "$tmpdir/d" "$tmpdir"
|
||||
else
|
||||
# Remove any dirs left behind by ancient mkdir implementations.
|
||||
rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
|
||||
fi
|
||||
trap '' 0;;
|
||||
esac;;
|
||||
esac
|
||||
|
||||
if
|
||||
$posix_mkdir && (
|
||||
umask $mkdir_umask &&
|
||||
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
|
||||
)
|
||||
then :
|
||||
else
|
||||
|
||||
# The umask is ridiculous, or mkdir does not conform to POSIX,
|
||||
# or it failed possibly due to a race condition. Create the
|
||||
# directory the slow way, step by step, checking for races as we go.
|
||||
|
||||
case $dstdir in
|
||||
/*) prefix='/';;
|
||||
[-=\(\)!]*) prefix='./';;
|
||||
*) prefix='';;
|
||||
esac
|
||||
|
||||
eval "$initialize_posix_glob"
|
||||
|
||||
oIFS=$IFS
|
||||
IFS=/
|
||||
$posix_glob set -f
|
||||
set fnord $dstdir
|
||||
shift
|
||||
$posix_glob set +f
|
||||
IFS=$oIFS
|
||||
|
||||
prefixes=
|
||||
|
||||
for d
|
||||
do
|
||||
test X"$d" = X && continue
|
||||
|
||||
prefix=$prefix$d
|
||||
if test -d "$prefix"; then
|
||||
prefixes=
|
||||
else
|
||||
if $posix_mkdir; then
|
||||
(umask=$mkdir_umask &&
|
||||
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
|
||||
# Don't fail if two instances are running concurrently.
|
||||
test -d "$prefix" || exit 1
|
||||
else
|
||||
case $prefix in
|
||||
*\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
|
||||
*) qprefix=$prefix;;
|
||||
esac
|
||||
prefixes="$prefixes '$qprefix'"
|
||||
fi
|
||||
fi
|
||||
prefix=$prefix/
|
||||
done
|
||||
|
||||
if test -n "$prefixes"; then
|
||||
# Don't fail if two instances are running concurrently.
|
||||
(umask $mkdir_umask &&
|
||||
eval "\$doit_exec \$mkdirprog $prefixes") ||
|
||||
test -d "$dstdir" || exit 1
|
||||
obsolete_mkdir_used=true
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if test -n "$dir_arg"; then
|
||||
{ test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
|
||||
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
|
||||
{ test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
|
||||
test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
|
||||
else
|
||||
|
||||
# Make a couple of temp file names in the proper directory.
|
||||
dsttmp=$dstdir/_inst.$$_
|
||||
rmtmp=$dstdir/_rm.$$_
|
||||
|
||||
# Trap to clean up those temp files at exit.
|
||||
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
|
||||
|
||||
# Copy the file name to the temp name.
|
||||
(umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
|
||||
|
||||
# and set any options; do chmod last to preserve setuid bits.
|
||||
#
|
||||
# If any of these fail, we abort the whole thing. If we want to
|
||||
# ignore errors from any of these, just make sure not to ignore
|
||||
# errors from the above "$doit $cpprog $src $dsttmp" command.
|
||||
#
|
||||
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
|
||||
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
|
||||
{ test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
|
||||
{ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
|
||||
|
||||
# If -C, don't bother to copy if it wouldn't change the file.
|
||||
if $copy_on_change &&
|
||||
old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
|
||||
new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
|
||||
|
||||
eval "$initialize_posix_glob" &&
|
||||
$posix_glob set -f &&
|
||||
set X $old && old=:$2:$4:$5:$6 &&
|
||||
set X $new && new=:$2:$4:$5:$6 &&
|
||||
$posix_glob set +f &&
|
||||
|
||||
test "$old" = "$new" &&
|
||||
$cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
|
||||
then
|
||||
rm -f "$dsttmp"
|
||||
else
|
||||
# Rename the file to the real destination.
|
||||
$doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
|
||||
|
||||
# The rename failed, perhaps because mv can't rename something else
|
||||
# to itself, or perhaps because mv is so ancient that it does not
|
||||
# support -f.
|
||||
{
|
||||
# Now remove or move aside any old file at destination location.
|
||||
# We try this two ways since rm can't unlink itself on some
|
||||
# systems and the destination file might be busy for other
|
||||
# reasons. In this case, the final cleanup might fail but the new
|
||||
# file should still install successfully.
|
||||
{
|
||||
test ! -f "$dst" ||
|
||||
$doit $rmcmd -f "$dst" 2>/dev/null ||
|
||||
{ $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
|
||||
{ $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
|
||||
} ||
|
||||
{ echo "$0: cannot unlink or rename $dst" >&2
|
||||
(exit 1); exit 1
|
||||
}
|
||||
} &&
|
||||
|
||||
# Now rename the file to the real destination.
|
||||
$doit $mvcmd "$dsttmp" "$dst"
|
||||
}
|
||||
fi || exit 1
|
||||
|
||||
trap '' 0
|
||||
fi
|
||||
done
|
||||
|
||||
# Local variables:
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
||||
215
lib/librumpuser/build-aux/missing
Executable file
215
lib/librumpuser/build-aux/missing
Executable file
|
|
@ -0,0 +1,215 @@
|
|||
#! /bin/sh
|
||||
# Common wrapper for a few potentially missing GNU programs.
|
||||
|
||||
scriptversion=2013-10-28.13; # UTC
|
||||
|
||||
# Copyright (C) 1996-2013 Free Software Foundation, Inc.
|
||||
# Originally written by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
if test $# -eq 0; then
|
||||
echo 1>&2 "Try '$0 --help' for more information"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
case $1 in
|
||||
|
||||
--is-lightweight)
|
||||
# Used by our autoconf macros to check whether the available missing
|
||||
# script is modern enough.
|
||||
exit 0
|
||||
;;
|
||||
|
||||
--run)
|
||||
# Back-compat with the calling convention used by older automake.
|
||||
shift
|
||||
;;
|
||||
|
||||
-h|--h|--he|--hel|--help)
|
||||
echo "\
|
||||
$0 [OPTION]... PROGRAM [ARGUMENT]...
|
||||
|
||||
Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due
|
||||
to PROGRAM being missing or too old.
|
||||
|
||||
Options:
|
||||
-h, --help display this help and exit
|
||||
-v, --version output version information and exit
|
||||
|
||||
Supported PROGRAM values:
|
||||
aclocal autoconf autoheader autom4te automake makeinfo
|
||||
bison yacc flex lex help2man
|
||||
|
||||
Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and
|
||||
'g' are ignored when checking the name.
|
||||
|
||||
Send bug reports to <bug-automake@gnu.org>."
|
||||
exit $?
|
||||
;;
|
||||
|
||||
-v|--v|--ve|--ver|--vers|--versi|--versio|--version)
|
||||
echo "missing $scriptversion (GNU Automake)"
|
||||
exit $?
|
||||
;;
|
||||
|
||||
-*)
|
||||
echo 1>&2 "$0: unknown '$1' option"
|
||||
echo 1>&2 "Try '$0 --help' for more information"
|
||||
exit 1
|
||||
;;
|
||||
|
||||
esac
|
||||
|
||||
# Run the given program, remember its exit status.
|
||||
"$@"; st=$?
|
||||
|
||||
# If it succeeded, we are done.
|
||||
test $st -eq 0 && exit 0
|
||||
|
||||
# Also exit now if we it failed (or wasn't found), and '--version' was
|
||||
# passed; such an option is passed most likely to detect whether the
|
||||
# program is present and works.
|
||||
case $2 in --version|--help) exit $st;; esac
|
||||
|
||||
# Exit code 63 means version mismatch. This often happens when the user
|
||||
# tries to use an ancient version of a tool on a file that requires a
|
||||
# minimum version.
|
||||
if test $st -eq 63; then
|
||||
msg="probably too old"
|
||||
elif test $st -eq 127; then
|
||||
# Program was missing.
|
||||
msg="missing on your system"
|
||||
else
|
||||
# Program was found and executed, but failed. Give up.
|
||||
exit $st
|
||||
fi
|
||||
|
||||
perl_URL=http://www.perl.org/
|
||||
flex_URL=http://flex.sourceforge.net/
|
||||
gnu_software_URL=http://www.gnu.org/software
|
||||
|
||||
program_details ()
|
||||
{
|
||||
case $1 in
|
||||
aclocal|automake)
|
||||
echo "The '$1' program is part of the GNU Automake package:"
|
||||
echo "<$gnu_software_URL/automake>"
|
||||
echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:"
|
||||
echo "<$gnu_software_URL/autoconf>"
|
||||
echo "<$gnu_software_URL/m4/>"
|
||||
echo "<$perl_URL>"
|
||||
;;
|
||||
autoconf|autom4te|autoheader)
|
||||
echo "The '$1' program is part of the GNU Autoconf package:"
|
||||
echo "<$gnu_software_URL/autoconf/>"
|
||||
echo "It also requires GNU m4 and Perl in order to run:"
|
||||
echo "<$gnu_software_URL/m4/>"
|
||||
echo "<$perl_URL>"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
give_advice ()
|
||||
{
|
||||
# Normalize program name to check for.
|
||||
normalized_program=`echo "$1" | sed '
|
||||
s/^gnu-//; t
|
||||
s/^gnu//; t
|
||||
s/^g//; t'`
|
||||
|
||||
printf '%s\n' "'$1' is $msg."
|
||||
|
||||
configure_deps="'configure.ac' or m4 files included by 'configure.ac'"
|
||||
case $normalized_program in
|
||||
autoconf*)
|
||||
echo "You should only need it if you modified 'configure.ac',"
|
||||
echo "or m4 files included by it."
|
||||
program_details 'autoconf'
|
||||
;;
|
||||
autoheader*)
|
||||
echo "You should only need it if you modified 'acconfig.h' or"
|
||||
echo "$configure_deps."
|
||||
program_details 'autoheader'
|
||||
;;
|
||||
automake*)
|
||||
echo "You should only need it if you modified 'Makefile.am' or"
|
||||
echo "$configure_deps."
|
||||
program_details 'automake'
|
||||
;;
|
||||
aclocal*)
|
||||
echo "You should only need it if you modified 'acinclude.m4' or"
|
||||
echo "$configure_deps."
|
||||
program_details 'aclocal'
|
||||
;;
|
||||
autom4te*)
|
||||
echo "You might have modified some maintainer files that require"
|
||||
echo "the 'autom4te' program to be rebuilt."
|
||||
program_details 'autom4te'
|
||||
;;
|
||||
bison*|yacc*)
|
||||
echo "You should only need it if you modified a '.y' file."
|
||||
echo "You may want to install the GNU Bison package:"
|
||||
echo "<$gnu_software_URL/bison/>"
|
||||
;;
|
||||
lex*|flex*)
|
||||
echo "You should only need it if you modified a '.l' file."
|
||||
echo "You may want to install the Fast Lexical Analyzer package:"
|
||||
echo "<$flex_URL>"
|
||||
;;
|
||||
help2man*)
|
||||
echo "You should only need it if you modified a dependency" \
|
||||
"of a man page."
|
||||
echo "You may want to install the GNU Help2man package:"
|
||||
echo "<$gnu_software_URL/help2man/>"
|
||||
;;
|
||||
makeinfo*)
|
||||
echo "You should only need it if you modified a '.texi' file, or"
|
||||
echo "any other file indirectly affecting the aspect of the manual."
|
||||
echo "You might want to install the Texinfo package:"
|
||||
echo "<$gnu_software_URL/texinfo/>"
|
||||
echo "The spurious makeinfo call might also be the consequence of"
|
||||
echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might"
|
||||
echo "want to install GNU make:"
|
||||
echo "<$gnu_software_URL/make/>"
|
||||
;;
|
||||
*)
|
||||
echo "You might have modified some files without having the proper"
|
||||
echo "tools for further handling them. Check the 'README' file, it"
|
||||
echo "often tells you about the needed prerequisites for installing"
|
||||
echo "this package. You may also peek at any GNU archive site, in"
|
||||
echo "case some other package contains this missing '$1' program."
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
give_advice "$1" | sed -e '1s/^/WARNING: /' \
|
||||
-e '2,$s/^/ /' >&2
|
||||
|
||||
# Propagate the correct exit status (expected to be 127 for a program
|
||||
# not found, 63 for a program that failed due to version mismatch).
|
||||
exit $st
|
||||
|
||||
# Local variables:
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
||||
5230
lib/librumpuser/configure
vendored
Executable file
5230
lib/librumpuser/configure
vendored
Executable file
File diff suppressed because it is too large
Load Diff
109
lib/librumpuser/configure.ac
Normal file
109
lib/librumpuser/configure.ac
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
#
|
||||
# Rump kernel POSIX hypervisor autoconf support.
|
||||
#
|
||||
# NOTE! regen by doing the following
|
||||
# 1) autoreconf -iv
|
||||
# 2) edit rumpuser_port.h (search for RUMPUSER_CONFIG for instructions)
|
||||
# 3) rm -rf autom4te.cache
|
||||
# 4) commit to NetBSD, pullup to repo.rumpkernel.org
|
||||
#
|
||||
|
||||
AC_PREREQ([2.66])
|
||||
AC_INIT([rumpuser-posix], [999], [http://rumpkernel.org/])
|
||||
|
||||
AC_CONFIG_HEADERS([rumpuser_config.h])
|
||||
AC_CONFIG_AUX_DIR([build-aux])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
|
||||
AC_LANG([C])
|
||||
|
||||
AC_SYS_LARGEFILE
|
||||
|
||||
AC_CHECK_HEADERS([sys/param.h sys/sysctl.h sys/disk.h \
|
||||
sys/disklabel.h sys/dkio.h sys/atomic.h paths.h])
|
||||
|
||||
AC_CANONICAL_TARGET
|
||||
|
||||
AC_CHECK_TYPES([clockid_t, register_t])
|
||||
|
||||
AC_CHECK_FUNCS([kqueue chflags strsuftoll setprogname getprogname \
|
||||
getenv_r posix_memalign memalign aligned_alloc \
|
||||
arc4random_buf getsubopt fsync_range __quotactl utimensat])
|
||||
|
||||
AC_TRY_LINK_FUNC([clock_nanosleep],,
|
||||
AC_CHECK_LIB([rt], [clock_nanosleep])
|
||||
)
|
||||
AC_CHECK_LIB([rt], [clock_gettime],
|
||||
AC_DEFINE([HAVE_CLOCK_GETTIME], 1, [clock_gettime]),
|
||||
AC_TRY_LINK_FUNC([clock_gettime],
|
||||
AC_DEFINE([HAVE_CLOCK_GETTIME], 1, [clock_gettime])))
|
||||
AC_CHECK_LIB([rt], [clock_nanosleep],
|
||||
AC_DEFINE([HAVE_CLOCK_NANOSLEEP], 1, [clock_nanosleep]),
|
||||
AC_TRY_LINK_FUNC([clock_nanosleep],
|
||||
AC_DEFINE([HAVE_CLOCK_NANOSLEEP], 1, [clock_nanosleep])))
|
||||
AC_CHECK_LIB([dl], [dlinfo],
|
||||
AC_DEFINE([HAVE_DLINFO], 1, [dlinfo]),
|
||||
AC_TRY_LINK_FUNC([dlinfo], AC_DEFINE([HAVE_DLINFO], 1, [dlinfo])))
|
||||
|
||||
AC_CHECK_MEMBERS([struct sockaddr_in.sin_len],,,[#include <netinet/in.h>])
|
||||
|
||||
dnl
|
||||
dnl pthread_setname() sillyness is a bit longer; we need the signature
|
||||
dnl
|
||||
SAVE_CFLAGS="${CFLAGS}"
|
||||
CFLAGS="${SAVE_CFLAGS} -Werror"
|
||||
|
||||
dnl check sys/cdefs.h creatively to process only with cc, not cpp
|
||||
dnl (sys/cdefs.h in at least in musl contains a #warning)
|
||||
AC_CHECK_HEADERS([sys/cdefs.h], [], [], [#include <sys/cdefs.h>])
|
||||
|
||||
SAVE_LIBS="${LIBS}"
|
||||
LIBS="${LIBS} -lpthread"
|
||||
AC_MSG_CHECKING([for two-argument pthread_setname_np()])
|
||||
AC_COMPILE_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[[#define _GNU_SOURCE
|
||||
#include <pthread.h>]],
|
||||
[[pthread_t pt;]
|
||||
[pthread_setname_np(pt, "x");return 0;]])
|
||||
],[
|
||||
AC_MSG_RESULT([yes])
|
||||
AC_DEFINE(HAVE_PTHREAD_SETNAME2, [1],
|
||||
[Define to 1 if you have 2-arg pthread_setname_np()])
|
||||
],[
|
||||
AC_MSG_RESULT([no])
|
||||
])
|
||||
AC_MSG_CHECKING([for three-argument pthread_setname_np()])
|
||||
AC_COMPILE_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[[#define _GNU_SOURCE
|
||||
#include <pthread.h>]],
|
||||
[[pthread_t pt;]
|
||||
[pthread_setname_np(pt, "X", (void *)0);return 0;]])
|
||||
],[
|
||||
AC_MSG_RESULT([yes])
|
||||
AC_DEFINE(HAVE_PTHREAD_SETNAME3, [1],
|
||||
[Define to 1 if you have 3-arg pthread_setname_np()])
|
||||
],[
|
||||
AC_MSG_RESULT([no])
|
||||
])
|
||||
LIBS="${SAVELIBS}"
|
||||
|
||||
AC_MSG_CHECKING([for ioctl cmd being int])
|
||||
AC_COMPILE_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[[#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
int ioctl(int fd, int, ...);]],
|
||||
[[]
|
||||
[return 0;]])
|
||||
],[
|
||||
AC_MSG_RESULT([yes])
|
||||
AC_DEFINE(HAVE_IOCTL_CMD_INT, [1],
|
||||
[Define to 1 if ioctl()'s cmd arg is int])
|
||||
],[
|
||||
AC_MSG_RESULT([no])
|
||||
])
|
||||
CFLAGS="${SAVE_CFLAGS}"
|
||||
|
||||
AC_OUTPUT
|
||||
1035
lib/librumpuser/rumpfiber.c
Normal file
1035
lib/librumpuser/rumpfiber.c
Normal file
File diff suppressed because it is too large
Load Diff
69
lib/librumpuser/rumpfiber.h
Normal file
69
lib/librumpuser/rumpfiber.h
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
/* $NetBSD: rumpfiber.h,v 1.4 2015/02/15 00:54:32 justin Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2014 Justin Cormack. 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 <sys/queue.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <ucontext.h>
|
||||
#include <unistd.h>
|
||||
|
||||
struct thread {
|
||||
char *name;
|
||||
void *lwp;
|
||||
void *cookie;
|
||||
int64_t wakeup_time;
|
||||
TAILQ_ENTRY(thread) thread_list;
|
||||
ucontext_t ctx;
|
||||
int flags;
|
||||
int threrrno;
|
||||
};
|
||||
|
||||
#define RUNNABLE_FLAG 0x00000001
|
||||
#define THREAD_MUSTJOIN 0x00000002
|
||||
#define THREAD_JOINED 0x00000004
|
||||
#define THREAD_EXTSTACK 0x00000008
|
||||
#define THREAD_TIMEDOUT 0x00000010
|
||||
|
||||
#define STACKSIZE 65536
|
||||
|
||||
/* used by experimental _lwp code */
|
||||
void schedule(void);
|
||||
void wake(struct thread *thread);
|
||||
void block(struct thread *thread);
|
||||
struct thread *init_mainthread(void *);
|
||||
void exit_thread(void) __attribute__((noreturn));
|
||||
void set_sched_hook(void (*f)(void *, void *));
|
||||
int abssleep_real(uint64_t millisecs);
|
||||
struct thread* create_thread(const char *name, void *cookie,
|
||||
void (*f)(void *), void *data,
|
||||
void *stack, size_t stack_size);
|
||||
int is_runnable(struct thread *);
|
||||
void set_runnable(struct thread *);
|
||||
void clear_runnable(struct thread *);
|
||||
|
||||
68
lib/librumpuser/rumpfiber_bio.c
Normal file
68
lib/librumpuser/rumpfiber_bio.c
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
/* $NetBSD: rumpfiber_bio.c,v 1.5 2014/11/04 19:05:17 pooka Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2014 Antti Kantee. 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "rumpuser_port.h"
|
||||
|
||||
#if !defined(lint)
|
||||
__RCSID("$NetBSD: rumpfiber_bio.c,v 1.5 2014/11/04 19:05:17 pooka Exp $");
|
||||
#endif /* !lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <rump/rumpuser.h>
|
||||
|
||||
#include "rumpuser_int.h"
|
||||
|
||||
void
|
||||
rumpuser_bio(int fd, int op, void *data, size_t dlen, int64_t doff,
|
||||
rump_biodone_fn biodone, void *bioarg)
|
||||
{
|
||||
ssize_t rv;
|
||||
int error = 0;
|
||||
|
||||
if (op & RUMPUSER_BIO_READ) {
|
||||
if ((rv = pread(fd, data, dlen, doff)) == -1)
|
||||
error = rumpuser__errtrans(errno);
|
||||
} else {
|
||||
if ((rv = pwrite(fd, data, dlen, doff)) == -1)
|
||||
error = rumpuser__errtrans(errno);
|
||||
if (error == 0 && (op & RUMPUSER_BIO_SYNC)) {
|
||||
#ifdef HAVE_FSYNC_RANGE
|
||||
fsync_range(fd, FDATASYNC, doff, dlen);
|
||||
#else
|
||||
fsync(fd);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if (rv == -1)
|
||||
rv = 0;
|
||||
biodone(bioarg, (size_t)rv, error);
|
||||
}
|
||||
105
lib/librumpuser/rumpfiber_sp.c
Normal file
105
lib/librumpuser/rumpfiber_sp.c
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
/* $NetBSD: rumpfiber_sp.c,v 1.4 2015/02/15 00:54:32 justin Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2014 Justin Cormack. 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
*/
|
||||
|
||||
/* stubs for sp functions as not supported for fibers yet */
|
||||
|
||||
#include "rumpuser_port.h"
|
||||
|
||||
#if !defined(lint)
|
||||
__RCSID("$NetBSD: rumpfiber_sp.c,v 1.4 2015/02/15 00:54:32 justin Exp $");
|
||||
#endif /* !lint */
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <rump/rumpuser.h>
|
||||
|
||||
#include "rumpfiber.h"
|
||||
|
||||
/*ARGSUSED*/
|
||||
int
|
||||
rumpuser_sp_init(const char *url,
|
||||
const char *ostype, const char *osrelease, const char *machine)
|
||||
{
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
void
|
||||
rumpuser_sp_fini(void *arg)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
int
|
||||
rumpuser_sp_raise(void *arg, int signo)
|
||||
{
|
||||
|
||||
abort();
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
int
|
||||
rumpuser_sp_copyin(void *arg, const void *raddr, void *laddr, size_t len)
|
||||
{
|
||||
|
||||
abort();
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
int
|
||||
rumpuser_sp_copyinstr(void *arg, const void *raddr, void *laddr, size_t *len)
|
||||
{
|
||||
|
||||
abort();
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
int
|
||||
rumpuser_sp_copyout(void *arg, const void *laddr, void *raddr, size_t dlen)
|
||||
{
|
||||
|
||||
abort();
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
int
|
||||
rumpuser_sp_copyoutstr(void *arg, const void *laddr, void *raddr, size_t *dlen)
|
||||
{
|
||||
|
||||
abort();
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
int
|
||||
rumpuser_sp_anonmmap(void *arg, size_t howmuch, void **addr)
|
||||
{
|
||||
|
||||
abort();
|
||||
}
|
||||
270
lib/librumpuser/rumpuser.c
Normal file
270
lib/librumpuser/rumpuser.c
Normal file
|
|
@ -0,0 +1,270 @@
|
|||
/* $NetBSD: rumpuser.c,v 1.67 2015/08/16 11:05:06 pooka Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007-2010 Antti Kantee. 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "rumpuser_port.h"
|
||||
|
||||
#if !defined(lint)
|
||||
__RCSID("$NetBSD: rumpuser.c,v 1.67 2015/08/16 11:05:06 pooka Exp $");
|
||||
#endif /* !lint */
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <netdb.h>
|
||||
#include <signal.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <rump/rumpuser.h>
|
||||
|
||||
#include "rumpuser_int.h"
|
||||
|
||||
struct rumpuser_hyperup rumpuser__hyp;
|
||||
|
||||
int
|
||||
rumpuser_init(int version, const struct rumpuser_hyperup *hyp)
|
||||
{
|
||||
int rv;
|
||||
|
||||
if (version != RUMPUSER_VERSION) {
|
||||
fprintf(stderr, "rumpuser mismatch, kern: %d, hypervisor %d\n",
|
||||
version, RUMPUSER_VERSION);
|
||||
abort();
|
||||
}
|
||||
|
||||
rv = rumpuser__random_init();
|
||||
if (rv != 0) {
|
||||
ET(rv);
|
||||
}
|
||||
|
||||
rumpuser__thrinit();
|
||||
rumpuser__hyp = *hyp;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
rumpuser_clock_gettime(int enum_rumpclock, int64_t *sec, long *nsec)
|
||||
{
|
||||
enum rumpclock rclk = enum_rumpclock;
|
||||
struct timespec ts;
|
||||
clockid_t clk;
|
||||
int rv;
|
||||
|
||||
switch (rclk) {
|
||||
case RUMPUSER_CLOCK_RELWALL:
|
||||
clk = CLOCK_REALTIME;
|
||||
break;
|
||||
case RUMPUSER_CLOCK_ABSMONO:
|
||||
#ifdef HAVE_CLOCK_NANOSLEEP
|
||||
clk = CLOCK_MONOTONIC;
|
||||
#else
|
||||
clk = CLOCK_REALTIME;
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
|
||||
if (clock_gettime(clk, &ts) == -1) {
|
||||
rv = errno;
|
||||
} else {
|
||||
*sec = ts.tv_sec;
|
||||
*nsec = ts.tv_nsec;
|
||||
rv = 0;
|
||||
}
|
||||
|
||||
ET(rv);
|
||||
}
|
||||
|
||||
int
|
||||
rumpuser_clock_sleep(int enum_rumpclock, int64_t sec, long nsec)
|
||||
{
|
||||
enum rumpclock rclk = enum_rumpclock;
|
||||
struct timespec rqt, rmt;
|
||||
int nlocks;
|
||||
int rv;
|
||||
|
||||
rumpkern_unsched(&nlocks, NULL);
|
||||
|
||||
/*LINTED*/
|
||||
rqt.tv_sec = sec;
|
||||
/*LINTED*/
|
||||
rqt.tv_nsec = nsec;
|
||||
|
||||
switch (rclk) {
|
||||
case RUMPUSER_CLOCK_RELWALL:
|
||||
do {
|
||||
rv = nanosleep(&rqt, &rmt);
|
||||
rqt = rmt;
|
||||
} while (rv == -1 && errno == EINTR);
|
||||
if (rv == -1) {
|
||||
rv = errno;
|
||||
}
|
||||
break;
|
||||
case RUMPUSER_CLOCK_ABSMONO:
|
||||
do {
|
||||
#ifdef HAVE_CLOCK_NANOSLEEP
|
||||
rv = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME,
|
||||
&rqt, NULL);
|
||||
#else
|
||||
/* le/la/der/die/das sigh. timevalspec tailspin */
|
||||
struct timespec ts, tsr;
|
||||
if ((rv = clock_gettime(CLOCK_REALTIME, &ts)) == -1)
|
||||
continue;
|
||||
if (ts.tv_sec == rqt.tv_sec ?
|
||||
ts.tv_nsec > rqt.tv_nsec : ts.tv_sec > rqt.tv_sec) {
|
||||
rv = 0;
|
||||
} else {
|
||||
tsr.tv_sec = rqt.tv_sec - ts.tv_sec;
|
||||
tsr.tv_nsec = rqt.tv_nsec - ts.tv_nsec;
|
||||
if (tsr.tv_nsec < 0) {
|
||||
tsr.tv_sec--;
|
||||
tsr.tv_nsec += 1000*1000*1000;
|
||||
}
|
||||
rv = nanosleep(&tsr, NULL);
|
||||
if (rv == -1)
|
||||
rv = errno;
|
||||
}
|
||||
#endif
|
||||
} while (rv == EINTR);
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
|
||||
rumpkern_sched(nlocks, NULL);
|
||||
|
||||
ET(rv);
|
||||
}
|
||||
|
||||
static int
|
||||
gethostncpu(void)
|
||||
{
|
||||
int ncpu = 1; /* unknown, really */
|
||||
|
||||
#ifdef _SC_NPROCESSORS_ONLN
|
||||
ncpu = sysconf(_SC_NPROCESSORS_ONLN);
|
||||
#endif
|
||||
|
||||
return ncpu;
|
||||
}
|
||||
|
||||
int
|
||||
rumpuser_getparam(const char *name, void *buf, size_t blen)
|
||||
{
|
||||
int rv;
|
||||
|
||||
if (strcmp(name, RUMPUSER_PARAM_NCPU) == 0) {
|
||||
int ncpu;
|
||||
|
||||
if (getenv_r("RUMP_NCPU", buf, blen) == -1) {
|
||||
sprintf(buf, "2"); /* default */
|
||||
} else if (strcmp(buf, "host") == 0) {
|
||||
ncpu = gethostncpu();
|
||||
snprintf(buf, blen, "%d", ncpu);
|
||||
}
|
||||
rv = 0;
|
||||
} else if (strcmp(name, RUMPUSER_PARAM_HOSTNAME) == 0) {
|
||||
char tmp[MAXHOSTNAMELEN];
|
||||
|
||||
if (gethostname(tmp, sizeof(tmp)) == -1) {
|
||||
snprintf(buf, blen, "rump-%05d", (int)getpid());
|
||||
} else {
|
||||
snprintf(buf, blen, "rump-%05d.%s",
|
||||
(int)getpid(), tmp);
|
||||
}
|
||||
rv = 0;
|
||||
} else if (*name == '_') {
|
||||
rv = EINVAL;
|
||||
} else {
|
||||
if (getenv_r(name, buf, blen) == -1)
|
||||
rv = errno;
|
||||
else
|
||||
rv = 0;
|
||||
}
|
||||
|
||||
ET(rv);
|
||||
}
|
||||
|
||||
void
|
||||
rumpuser_putchar(int c)
|
||||
{
|
||||
|
||||
putchar(c);
|
||||
}
|
||||
|
||||
__dead void
|
||||
rumpuser_exit(int rv)
|
||||
{
|
||||
|
||||
printf("halted\n");
|
||||
if (rv == RUMPUSER_PANIC)
|
||||
abort();
|
||||
else
|
||||
exit(rv);
|
||||
}
|
||||
|
||||
void
|
||||
rumpuser_seterrno(int error)
|
||||
{
|
||||
|
||||
errno = error;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is meant for safe debugging prints from the kernel.
|
||||
*/
|
||||
void
|
||||
rumpuser_dprintf(const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
vfprintf(stderr, format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
int
|
||||
rumpuser_kill(int64_t pid, int rumpsig)
|
||||
{
|
||||
int sig;
|
||||
|
||||
sig = rumpuser__sig_rump2host(rumpsig);
|
||||
if (sig > 0)
|
||||
raise(sig);
|
||||
return 0;
|
||||
}
|
||||
189
lib/librumpuser/rumpuser_bio.c
Normal file
189
lib/librumpuser/rumpuser_bio.c
Normal file
|
|
@ -0,0 +1,189 @@
|
|||
/* $NetBSD: rumpuser_bio.c,v 1.10 2014/11/04 19:05:17 pooka Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2013 Antti Kantee. 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "rumpuser_port.h"
|
||||
|
||||
#if !defined(lint)
|
||||
__RCSID("$NetBSD: rumpuser_bio.c,v 1.10 2014/11/04 19:05:17 pooka Exp $");
|
||||
#endif /* !lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <rump/rumpuser.h>
|
||||
|
||||
#include "rumpuser_int.h"
|
||||
|
||||
struct rumpuser_bio {
|
||||
int bio_fd;
|
||||
int bio_op;
|
||||
void *bio_data;
|
||||
size_t bio_dlen;
|
||||
off_t bio_off;
|
||||
|
||||
rump_biodone_fn bio_done;
|
||||
void *bio_donearg;
|
||||
};
|
||||
|
||||
#define N_BIOS 128
|
||||
static pthread_mutex_t biomtx = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_cond_t biocv = PTHREAD_COND_INITIALIZER;
|
||||
static int bio_head, bio_tail;
|
||||
static struct rumpuser_bio bios[N_BIOS];
|
||||
|
||||
static void
|
||||
dobio(struct rumpuser_bio *biop)
|
||||
{
|
||||
ssize_t rv;
|
||||
int error, dummy;
|
||||
|
||||
assert(biop->bio_donearg != NULL);
|
||||
if (biop->bio_op & RUMPUSER_BIO_READ) {
|
||||
error = 0;
|
||||
rv = pread(biop->bio_fd, biop->bio_data,
|
||||
biop->bio_dlen, biop->bio_off);
|
||||
if (rv < 0) {
|
||||
rv = 0;
|
||||
error = rumpuser__errtrans(errno);
|
||||
}
|
||||
} else {
|
||||
error = 0;
|
||||
rv = pwrite(biop->bio_fd, biop->bio_data,
|
||||
biop->bio_dlen, biop->bio_off);
|
||||
if (rv < 0) {
|
||||
rv = 0;
|
||||
error = rumpuser__errtrans(errno);
|
||||
} else if (biop->bio_op & RUMPUSER_BIO_SYNC) {
|
||||
#ifdef HAVE_FSYNC_RANGE
|
||||
fsync_range(biop->bio_fd, FDATASYNC,
|
||||
biop->bio_off, biop->bio_dlen);
|
||||
#else
|
||||
fsync(biop->bio_fd);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
rumpkern_sched(0, NULL);
|
||||
biop->bio_done(biop->bio_donearg, (size_t)rv, error);
|
||||
rumpkern_unsched(&dummy, NULL);
|
||||
|
||||
/* paranoia */
|
||||
biop->bio_donearg = NULL;
|
||||
}
|
||||
|
||||
static void *
|
||||
biothread(void *arg)
|
||||
{
|
||||
struct rumpuser_bio *biop;
|
||||
int rv;
|
||||
|
||||
rumpuser__hyp.hyp_schedule();
|
||||
rv = rumpuser__hyp.hyp_lwproc_newlwp(0);
|
||||
assert(rv == 0);
|
||||
rumpuser__hyp.hyp_unschedule();
|
||||
NOFAIL_ERRNO(pthread_mutex_lock(&biomtx));
|
||||
for (;;) {
|
||||
while (bio_head == bio_tail)
|
||||
NOFAIL_ERRNO(pthread_cond_wait(&biocv, &biomtx));
|
||||
|
||||
biop = &bios[bio_tail];
|
||||
pthread_mutex_unlock(&biomtx);
|
||||
|
||||
dobio(biop);
|
||||
|
||||
NOFAIL_ERRNO(pthread_mutex_lock(&biomtx));
|
||||
bio_tail = (bio_tail+1) % N_BIOS;
|
||||
pthread_cond_signal(&biocv);
|
||||
}
|
||||
|
||||
/* unreachable */
|
||||
abort();
|
||||
}
|
||||
|
||||
void
|
||||
rumpuser_bio(int fd, int op, void *data, size_t dlen, int64_t doff,
|
||||
rump_biodone_fn biodone, void *bioarg)
|
||||
{
|
||||
struct rumpuser_bio bio;
|
||||
static int inited = 0;
|
||||
static int usethread = 1;
|
||||
int nlocks;
|
||||
|
||||
rumpkern_unsched(&nlocks, NULL);
|
||||
|
||||
if (!inited) {
|
||||
pthread_mutex_lock(&biomtx);
|
||||
if (!inited) {
|
||||
char buf[16];
|
||||
pthread_t pt;
|
||||
|
||||
/*
|
||||
* duplicates policy of rump kernel. maybe a bit
|
||||
* questionable, but since the setting is not
|
||||
* used in normal circumstances, let's not care
|
||||
*/
|
||||
if (getenv_r("RUMP_THREADS", buf, sizeof(buf)) == 0)
|
||||
usethread = *buf != '0';
|
||||
|
||||
if (usethread)
|
||||
pthread_create(&pt, NULL, biothread, NULL);
|
||||
inited = 1;
|
||||
}
|
||||
pthread_mutex_unlock(&biomtx);
|
||||
assert(inited);
|
||||
}
|
||||
|
||||
bio.bio_fd = fd;
|
||||
bio.bio_op = op;
|
||||
bio.bio_data = data;
|
||||
bio.bio_dlen = dlen;
|
||||
bio.bio_off = (off_t)doff;
|
||||
bio.bio_done = biodone;
|
||||
bio.bio_donearg = bioarg;
|
||||
|
||||
if (!usethread) {
|
||||
dobio(&bio);
|
||||
} else {
|
||||
pthread_mutex_lock(&biomtx);
|
||||
while ((bio_head+1) % N_BIOS == bio_tail)
|
||||
pthread_cond_wait(&biocv, &biomtx);
|
||||
|
||||
bios[bio_head] = bio;
|
||||
bio_head = (bio_head+1) % N_BIOS;
|
||||
|
||||
pthread_cond_signal(&biocv);
|
||||
pthread_mutex_unlock(&biomtx);
|
||||
}
|
||||
|
||||
rumpkern_sched(nlocks, NULL);
|
||||
}
|
||||
108
lib/librumpuser/rumpuser_component.c
Normal file
108
lib/librumpuser/rumpuser_component.c
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
/* $NetBSD: rumpuser_component.c,v 1.6 2013/05/07 15:18:35 pooka Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2013 Antti Kantee. 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "rumpuser_port.h"
|
||||
|
||||
#if !defined(lint)
|
||||
__RCSID("$NetBSD: rumpuser_component.c,v 1.6 2013/05/07 15:18:35 pooka Exp $");
|
||||
#endif /* !lint */
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
* These interfaces affect the shlib major/minor; they can be called from
|
||||
* any program when applicable. The rest of the interfaces provided
|
||||
* by rumpuser are part of the rump kernel/hypervisor contract and
|
||||
* are versioned by RUMPUSER_VERSION.
|
||||
*/
|
||||
|
||||
#include <rump/rumpuser_component.h>
|
||||
|
||||
#include "rumpuser_int.h"
|
||||
|
||||
void *
|
||||
rumpuser_component_unschedule(void)
|
||||
{
|
||||
int nlocks;
|
||||
|
||||
rumpkern_unsched(&nlocks, NULL);
|
||||
return (void *)(intptr_t)nlocks;
|
||||
}
|
||||
|
||||
void
|
||||
rumpuser_component_schedule(void *cookie)
|
||||
{
|
||||
int nlocks = (int)(intptr_t)cookie;
|
||||
|
||||
rumpkern_sched(nlocks, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
rumpuser_component_kthread(void)
|
||||
{
|
||||
|
||||
rumpuser__hyp.hyp_schedule();
|
||||
rumpuser__hyp.hyp_lwproc_newlwp(0);
|
||||
rumpuser__hyp.hyp_unschedule();
|
||||
}
|
||||
|
||||
struct lwp *
|
||||
rumpuser_component_curlwp(void)
|
||||
{
|
||||
struct lwp *l;
|
||||
|
||||
rumpuser__hyp.hyp_schedule();
|
||||
l = rumpuser__hyp.hyp_lwproc_curlwp();
|
||||
rumpuser__hyp.hyp_unschedule();
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
void
|
||||
rumpuser_component_switchlwp(struct lwp *l)
|
||||
{
|
||||
|
||||
rumpuser__hyp.hyp_schedule();
|
||||
rumpuser__hyp.hyp_lwproc_switch(l);
|
||||
rumpuser__hyp.hyp_unschedule();
|
||||
}
|
||||
|
||||
void
|
||||
rumpuser_component_kthread_release(void)
|
||||
{
|
||||
|
||||
rumpuser__hyp.hyp_schedule();
|
||||
rumpuser__hyp.hyp_lwproc_release();
|
||||
rumpuser__hyp.hyp_unschedule();
|
||||
}
|
||||
|
||||
int
|
||||
rumpuser_component_errtrans(int hosterr)
|
||||
{
|
||||
|
||||
return rumpuser__errtrans(hosterr);
|
||||
}
|
||||
40
lib/librumpuser/rumpuser_component.h
Normal file
40
lib/librumpuser/rumpuser_component.h
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/* $NetBSD: rumpuser_component.h,v 1.3 2013/04/30 12:39:20 pooka Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2013 Antti Kantee. 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
*/
|
||||
|
||||
#ifndef _RUMP_RUMPUSER_COMPONENT_H_
|
||||
#define _RUMP_RUMPUSER_COMPONENT_H_
|
||||
|
||||
void * rumpuser_component_unschedule(void);
|
||||
void rumpuser_component_schedule(void *);
|
||||
int rumpuser_component_errtrans(int);
|
||||
|
||||
void rumpuser_component_kthread(void);
|
||||
struct lwp *rumpuser_component_curlwp(void);
|
||||
void rumpuser_component_switchlwp(struct lwp *);
|
||||
void rumpuser_component_kthread_release(void);
|
||||
|
||||
#endif /* _RUMP_RUMPUSER_COMPONENT_H_ */
|
||||
156
lib/librumpuser/rumpuser_config.h.in
Normal file
156
lib/librumpuser/rumpuser_config.h.in
Normal file
|
|
@ -0,0 +1,156 @@
|
|||
/* rumpuser_config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* Define to 1 if you have the `aligned_alloc' function. */
|
||||
#undef HAVE_ALIGNED_ALLOC
|
||||
|
||||
/* Define to 1 if you have the `arc4random_buf' function. */
|
||||
#undef HAVE_ARC4RANDOM_BUF
|
||||
|
||||
/* Define to 1 if you have the `chflags' function. */
|
||||
#undef HAVE_CHFLAGS
|
||||
|
||||
/* Define to 1 if the system has the type `clockid_t'. */
|
||||
#undef HAVE_CLOCKID_T
|
||||
|
||||
/* clock_gettime */
|
||||
#undef HAVE_CLOCK_GETTIME
|
||||
|
||||
/* clock_nanosleep */
|
||||
#undef HAVE_CLOCK_NANOSLEEP
|
||||
|
||||
/* dlinfo */
|
||||
#undef HAVE_DLINFO
|
||||
|
||||
/* Define to 1 if you have the `fsync_range' function. */
|
||||
#undef HAVE_FSYNC_RANGE
|
||||
|
||||
/* Define to 1 if you have the `getenv_r' function. */
|
||||
#undef HAVE_GETENV_R
|
||||
|
||||
/* Define to 1 if you have the `getprogname' function. */
|
||||
#undef HAVE_GETPROGNAME
|
||||
|
||||
/* Define to 1 if you have the `getsubopt' function. */
|
||||
#undef HAVE_GETSUBOPT
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#undef HAVE_INTTYPES_H
|
||||
|
||||
/* Define to 1 if ioctl()'s cmd arg is int */
|
||||
#undef HAVE_IOCTL_CMD_INT
|
||||
|
||||
/* Define to 1 if you have the `kqueue' function. */
|
||||
#undef HAVE_KQUEUE
|
||||
|
||||
/* Define to 1 if you have the `rt' library (-lrt). */
|
||||
#undef HAVE_LIBRT
|
||||
|
||||
/* Define to 1 if you have the `memalign' function. */
|
||||
#undef HAVE_MEMALIGN
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#undef HAVE_MEMORY_H
|
||||
|
||||
/* Define to 1 if you have the <paths.h> header file. */
|
||||
#undef HAVE_PATHS_H
|
||||
|
||||
/* Define to 1 if you have the `posix_memalign' function. */
|
||||
#undef HAVE_POSIX_MEMALIGN
|
||||
|
||||
/* Define to 1 if you have 2-arg pthread_setname_np() */
|
||||
#undef HAVE_PTHREAD_SETNAME2
|
||||
|
||||
/* Define to 1 if you have 3-arg pthread_setname_np() */
|
||||
#undef HAVE_PTHREAD_SETNAME3
|
||||
|
||||
/* Define to 1 if the system has the type `register_t'. */
|
||||
#undef HAVE_REGISTER_T
|
||||
|
||||
/* Define to 1 if you have the `setprogname' function. */
|
||||
#undef HAVE_SETPROGNAME
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#undef HAVE_STDINT_H
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#undef HAVE_STDLIB_H
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#undef HAVE_STRINGS_H
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#undef HAVE_STRING_H
|
||||
|
||||
/* Define to 1 if you have the `strsuftoll' function. */
|
||||
#undef HAVE_STRSUFTOLL
|
||||
|
||||
/* Define to 1 if `sin_len' is a member of `struct sockaddr_in'. */
|
||||
#undef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
|
||||
|
||||
/* Define to 1 if you have the <sys/atomic.h> header file. */
|
||||
#undef HAVE_SYS_ATOMIC_H
|
||||
|
||||
/* Define to 1 if you have the <sys/cdefs.h> header file. */
|
||||
#undef HAVE_SYS_CDEFS_H
|
||||
|
||||
/* Define to 1 if you have the <sys/disklabel.h> header file. */
|
||||
#undef HAVE_SYS_DISKLABEL_H
|
||||
|
||||
/* Define to 1 if you have the <sys/disk.h> header file. */
|
||||
#undef HAVE_SYS_DISK_H
|
||||
|
||||
/* Define to 1 if you have the <sys/dkio.h> header file. */
|
||||
#undef HAVE_SYS_DKIO_H
|
||||
|
||||
/* Define to 1 if you have the <sys/param.h> header file. */
|
||||
#undef HAVE_SYS_PARAM_H
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#undef HAVE_SYS_STAT_H
|
||||
|
||||
/* Define to 1 if you have the <sys/sysctl.h> header file. */
|
||||
#undef HAVE_SYS_SYSCTL_H
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#undef HAVE_SYS_TYPES_H
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#undef HAVE_UNISTD_H
|
||||
|
||||
/* Define to 1 if you have the `utimensat' function. */
|
||||
#undef HAVE_UTIMENSAT
|
||||
|
||||
/* Define to 1 if you have the `__quotactl' function. */
|
||||
#undef HAVE___QUOTACTL
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#undef PACKAGE_BUGREPORT
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#undef PACKAGE_NAME
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#undef PACKAGE_STRING
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#undef PACKAGE_TARNAME
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
#undef PACKAGE_URL
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#undef PACKAGE_VERSION
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#undef STDC_HEADERS
|
||||
|
||||
/* Enable large inode numbers on Mac OS X 10.5. */
|
||||
#ifndef _DARWIN_USE_64_BIT_INODE
|
||||
# define _DARWIN_USE_64_BIT_INODE 1
|
||||
#endif
|
||||
|
||||
/* Number of bits in a file offset, on hosts where this is settable. */
|
||||
#undef _FILE_OFFSET_BITS
|
||||
|
||||
/* Define for large files, on AIX-style hosts. */
|
||||
#undef _LARGE_FILES
|
||||
147
lib/librumpuser/rumpuser_daemonize.c
Normal file
147
lib/librumpuser/rumpuser_daemonize.c
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
/* $NetBSD: rumpuser_daemonize.c,v 1.7 2014/11/04 19:05:17 pooka Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2010 Antti Kantee. 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "rumpuser_port.h"
|
||||
|
||||
#if !defined(lint)
|
||||
__RCSID("$NetBSD: rumpuser_daemonize.c,v 1.7 2014/11/04 19:05:17 pooka Exp $");
|
||||
#endif /* !lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "rumpuser_int.h"
|
||||
|
||||
#if defined(HAVE_PATHS_H)
|
||||
#include <paths.h>
|
||||
#else
|
||||
#define _PATH_DEVNULL "/dev/null"
|
||||
#endif
|
||||
|
||||
static int isdaemonizing;
|
||||
static int daemonpipe[2];
|
||||
|
||||
#include <rump/rumpuser.h>
|
||||
|
||||
int
|
||||
rumpuser_daemonize_begin(void)
|
||||
{
|
||||
ssize_t n;
|
||||
int error;
|
||||
int rv;
|
||||
|
||||
if (isdaemonizing) {
|
||||
rv = EINPROGRESS;
|
||||
goto out;
|
||||
}
|
||||
isdaemonizing = 1;
|
||||
|
||||
/*
|
||||
* For daemons we need to fork. However, since we can't fork
|
||||
* after rump_init (which creates threads), do it now. Add
|
||||
* a little pipe trickery to make sure we don't exit until the
|
||||
* service is fully inited (i.e. interlocked daemonization).
|
||||
* Actually, use sucketpair since that allows to easily steer
|
||||
* clear of the dreaded sigpipe.
|
||||
*
|
||||
* Note: We do *NOT* host chdir("/"). It's up to the caller to
|
||||
* take care of that or not.
|
||||
*/
|
||||
if (socketpair(PF_LOCAL, SOCK_STREAM, 0, daemonpipe) == -1) {
|
||||
rv = errno;
|
||||
goto out;
|
||||
}
|
||||
|
||||
switch (fork()) {
|
||||
case 0:
|
||||
if (setsid() == -1) {
|
||||
rumpuser_daemonize_done(errno);
|
||||
}
|
||||
rv = 0;
|
||||
break;
|
||||
case -1:
|
||||
rv = errno;
|
||||
break;
|
||||
default:
|
||||
close(daemonpipe[1]);
|
||||
n = recv(daemonpipe[0], &error, sizeof(error), MSG_NOSIGNAL);
|
||||
if (n == -1)
|
||||
error = errno;
|
||||
else if (n != sizeof(error))
|
||||
error = ESRCH;
|
||||
_exit(error);
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
out:
|
||||
ET(rv);
|
||||
}
|
||||
|
||||
int
|
||||
rumpuser_daemonize_done(int error)
|
||||
{
|
||||
ssize_t n;
|
||||
int fd, rv = 0;
|
||||
|
||||
if (!isdaemonizing) {
|
||||
rv = ENOENT;
|
||||
goto outout;
|
||||
}
|
||||
|
||||
if (error == 0) {
|
||||
fd = open(_PATH_DEVNULL, O_RDWR);
|
||||
if (fd == -1) {
|
||||
error = errno;
|
||||
goto out;
|
||||
}
|
||||
dup2(fd, STDIN_FILENO);
|
||||
dup2(fd, STDOUT_FILENO);
|
||||
dup2(fd, STDERR_FILENO);
|
||||
if (fd > STDERR_FILENO)
|
||||
close(fd);
|
||||
}
|
||||
|
||||
out:
|
||||
n = send(daemonpipe[1], &error, sizeof(error), MSG_NOSIGNAL);
|
||||
if (n != sizeof(error)) {
|
||||
rv = EPIPE;
|
||||
} else if (n == -1) {
|
||||
rv = errno;
|
||||
} else {
|
||||
close(daemonpipe[0]);
|
||||
close(daemonpipe[1]);
|
||||
}
|
||||
|
||||
outout:
|
||||
ET(rv);
|
||||
}
|
||||
487
lib/librumpuser/rumpuser_dl.c
Normal file
487
lib/librumpuser/rumpuser_dl.c
Normal file
|
|
@ -0,0 +1,487 @@
|
|||
/* $NetBSD: rumpuser_dl.c,v 1.30 2014/11/04 19:05:17 pooka Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2009 Antti Kantee. 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Load all module link sets and feed symbol table to the kernel.
|
||||
* Called during rump bootstrap.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Solaris libelf.h doesn't support _FILE_OFFSET_BITS=64. Luckily,
|
||||
* for this module it doesn't matter.
|
||||
*/
|
||||
#if defined(__sun__)
|
||||
#define RUMPUSER_NO_FILE_OFFSET_BITS
|
||||
#endif
|
||||
#include "rumpuser_port.h"
|
||||
|
||||
#if !defined(lint)
|
||||
__RCSID("$NetBSD: rumpuser_dl.c,v 1.30 2014/11/04 19:05:17 pooka Exp $");
|
||||
#endif /* !lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <rump/rumpuser.h>
|
||||
|
||||
#if defined(__ELF__) && defined(HAVE_DLINFO)
|
||||
#include <elf.h>
|
||||
#include <link.h>
|
||||
|
||||
static size_t symtabsize = 0, strtabsize = 0;
|
||||
static size_t symtaboff = 0, strtaboff = 0;
|
||||
static uint8_t *symtab = NULL;
|
||||
static char *strtab = NULL;
|
||||
static unsigned char eident;
|
||||
|
||||
/* nb5 compat */
|
||||
#ifndef Elf_Symindx
|
||||
#define Elf_Symindx uint32_t
|
||||
#endif
|
||||
|
||||
static void *
|
||||
reservespace(void *store, size_t *storesize,
|
||||
size_t storeoff, size_t required)
|
||||
{
|
||||
size_t chunk, newsize;
|
||||
|
||||
assert(storeoff <= *storesize);
|
||||
chunk = *storesize - storeoff;
|
||||
|
||||
if (chunk >= required)
|
||||
return store;
|
||||
|
||||
newsize = *storesize + ((size_t)required - chunk);
|
||||
store = realloc(store, newsize);
|
||||
if (store == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
*((uint8_t *)store + storeoff) = '\0';
|
||||
*storesize = newsize;
|
||||
|
||||
return store;
|
||||
}
|
||||
|
||||
/*
|
||||
* Macros to make handling elf32/64 in the code a little saner.
|
||||
*/
|
||||
|
||||
#define DYNn_GETMEMBER(base, n, thevar, result) \
|
||||
do { \
|
||||
if (eident == ELFCLASS32) { \
|
||||
const Elf32_Dyn *dyn = base; \
|
||||
/*LINTED*/ \
|
||||
result = dyn[n].thevar; \
|
||||
} else { \
|
||||
const Elf64_Dyn *dyn = base; \
|
||||
/*LINTED*/ \
|
||||
result = dyn[n].thevar; \
|
||||
} \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define SYMn_GETMEMBER(base, n, thevar, result) \
|
||||
do { \
|
||||
if (eident == ELFCLASS32) { \
|
||||
const Elf32_Sym *sym = base; \
|
||||
/*LINTED*/ \
|
||||
result = sym[n].thevar; \
|
||||
} else { \
|
||||
const Elf64_Sym *sym = base; \
|
||||
/*LINTED*/ \
|
||||
result = sym[n].thevar; \
|
||||
} \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define SYMn_SETMEMBER(base, n, thevar, value) \
|
||||
do { \
|
||||
if (eident == ELFCLASS32) { \
|
||||
Elf32_Sym *sym = base; \
|
||||
/*LINTED*/ \
|
||||
sym[n].thevar = value; \
|
||||
} else { \
|
||||
Elf64_Sym *sym = base; \
|
||||
/*LINTED*/ \
|
||||
sym[n].thevar = value; \
|
||||
} \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define SYM_GETSIZE() ((eident==ELFCLASS32)?sizeof(Elf32_Sym):sizeof(Elf64_Sym))
|
||||
|
||||
/*
|
||||
* On NetBSD, the dynamic section pointer values seem to be relative to
|
||||
* the address the dso is mapped at. On glibc, they seem to contain
|
||||
* the absolute address. I couldn't find anything definite from a quick
|
||||
* read of the standard and therefore I will not go and figure beyond ifdef.
|
||||
* On Solaris and DragonFly / FreeBSD, the main object works differently
|
||||
* ... uuuuh.
|
||||
*/
|
||||
#if defined(__GLIBC__) && !defined(__mips__)
|
||||
#define adjptr(_map_, _ptr_) ((void *)(_ptr_))
|
||||
#elif defined(__sun__) || defined(__DragonFly__) || defined(__FreeBSD__)
|
||||
#define adjptr(_map_, _ptr_) \
|
||||
(ismainobj ? (void *)(_ptr_) : (void *)(_map_->l_addr + (_ptr_)))
|
||||
#else
|
||||
/* NetBSD and some others, e.g. Linux + musl */
|
||||
#define adjptr(_map_, _ptr_) ((void *)(_map_->l_addr + (_ptr_)))
|
||||
#endif
|
||||
|
||||
static int
|
||||
getsymbols(struct link_map *map, int ismainobj)
|
||||
{
|
||||
char *str_base;
|
||||
void *syms_base = NULL; /* XXXgcc */
|
||||
size_t curstrsize;
|
||||
const void *ed_base;
|
||||
uint64_t ed_tag;
|
||||
size_t cursymcount;
|
||||
unsigned i;
|
||||
|
||||
if (map->l_addr) {
|
||||
if (memcmp((void *)map->l_addr, ELFMAG, SELFMAG) != 0)
|
||||
return ENOEXEC;
|
||||
eident = *(unsigned char *)(map->l_addr + EI_CLASS);
|
||||
if (eident != ELFCLASS32 && eident != ELFCLASS64)
|
||||
return ENOEXEC;
|
||||
}
|
||||
|
||||
/*
|
||||
* ok, we probably have only the main object. instead of going
|
||||
* to disk and reading the ehdr, just try to guess the size.
|
||||
*/
|
||||
if (eident == 0) {
|
||||
if (/*CONSTCOND*/sizeof(void *) == 4)
|
||||
eident = ELFCLASS32;
|
||||
else
|
||||
eident = ELFCLASS64;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find symtab and strtab and their sizes.
|
||||
*/
|
||||
str_base = NULL;
|
||||
curstrsize = 0;
|
||||
cursymcount = 0;
|
||||
ed_base = map->l_ld;
|
||||
DYNn_GETMEMBER(ed_base, 0, d_tag, ed_tag);
|
||||
for (i = 0; ed_tag != DT_NULL;) {
|
||||
uintptr_t edptr;
|
||||
size_t edval;
|
||||
Elf_Symindx *hashtab;
|
||||
|
||||
switch (ed_tag) {
|
||||
case DT_SYMTAB:
|
||||
DYNn_GETMEMBER(ed_base, i, d_un.d_ptr, edptr);
|
||||
syms_base = adjptr(map, edptr);
|
||||
break;
|
||||
case DT_STRTAB:
|
||||
DYNn_GETMEMBER(ed_base, i, d_un.d_ptr, edptr);
|
||||
str_base = adjptr(map, edptr);
|
||||
break;
|
||||
case DT_STRSZ:
|
||||
DYNn_GETMEMBER(ed_base, i, d_un.d_val, edval);
|
||||
curstrsize = edval;
|
||||
break;
|
||||
case DT_HASH:
|
||||
DYNn_GETMEMBER(ed_base, i, d_un.d_ptr, edptr);
|
||||
hashtab = (Elf_Symindx *)adjptr(map, edptr);
|
||||
cursymcount = hashtab[1];
|
||||
break;
|
||||
#ifdef DT_GNU_HASH
|
||||
/*
|
||||
* DT_GNU_HASH is a bit more complicated than DT_HASH
|
||||
* in this regard since apparently there is no field
|
||||
* telling us the total symbol count. Instead, we look
|
||||
* for the last valid hash bucket and add its chain lenght
|
||||
* to the bucket's base index.
|
||||
*/
|
||||
case DT_GNU_HASH: {
|
||||
Elf32_Word nbuck, symndx, maskwords, maxchain = 0;
|
||||
Elf32_Word *gnuhash, *buckets, *ptr;
|
||||
int bi;
|
||||
|
||||
DYNn_GETMEMBER(ed_base, i, d_un.d_ptr, edptr);
|
||||
gnuhash = (Elf32_Word *)adjptr(map, edptr);
|
||||
|
||||
nbuck = gnuhash[0];
|
||||
symndx = gnuhash[1];
|
||||
maskwords = gnuhash[2];
|
||||
|
||||
/*
|
||||
* First, find the last valid bucket and grab its index
|
||||
*/
|
||||
if (eident == ELFCLASS64)
|
||||
maskwords *= 2; /* sizeof(*buckets) == 4 */
|
||||
buckets = gnuhash + 4 + maskwords;
|
||||
for (bi = nbuck-1; bi >= 0; bi--) {
|
||||
if (buckets[bi] != 0) {
|
||||
maxchain = buckets[bi];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (maxchain == 0 || maxchain < symndx)
|
||||
break;
|
||||
|
||||
/*
|
||||
* Then, traverse the last chain and count symbols.
|
||||
*/
|
||||
|
||||
cursymcount = maxchain;
|
||||
ptr = buckets + nbuck + (maxchain - symndx);
|
||||
do {
|
||||
cursymcount++;
|
||||
} while ((*ptr++ & 1) == 0);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case DT_SYMENT:
|
||||
DYNn_GETMEMBER(ed_base, i, d_un.d_val, edval);
|
||||
assert(edval == SYM_GETSIZE());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
DYNn_GETMEMBER(ed_base, i, d_tag, ed_tag);
|
||||
}
|
||||
|
||||
if (str_base == NULL || syms_base == NULL ||
|
||||
curstrsize == 0 || cursymcount == 0) {
|
||||
fprintf(stderr, "could not find strtab, symtab or their sizes "
|
||||
"in %s\n", map->l_name);
|
||||
return ENOEXEC;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure we have enough space for the contents of the symbol
|
||||
* and string tables we are currently processing. The total used
|
||||
* space will be smaller due to undefined symbols we are not
|
||||
* interested in.
|
||||
*/
|
||||
symtab = reservespace(symtab, &symtabsize,
|
||||
symtaboff, cursymcount * SYM_GETSIZE());
|
||||
strtab = reservespace(strtab, &strtabsize, strtaboff, curstrsize);
|
||||
if (symtab == NULL || strtab == NULL) {
|
||||
fprintf(stderr, "failed to reserve memory");
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
/* iterate over all symbols in current symtab */
|
||||
for (i = 0; i < cursymcount; i++) {
|
||||
const char *cursymname;
|
||||
int shndx, name;
|
||||
uintptr_t value;
|
||||
void *csym;
|
||||
|
||||
SYMn_GETMEMBER(syms_base, i, st_shndx, shndx);
|
||||
SYMn_GETMEMBER(syms_base, i, st_value, value);
|
||||
if (shndx == SHN_UNDEF || value == 0)
|
||||
continue;
|
||||
|
||||
/* get symbol name */
|
||||
SYMn_GETMEMBER(syms_base, i, st_name, name);
|
||||
cursymname = name + str_base;
|
||||
|
||||
/*
|
||||
* Only accept symbols which are decidedly in
|
||||
* the rump kernel namespace.
|
||||
* XXX: quirks, but they wouldn't matter here
|
||||
*/
|
||||
if (strncmp(cursymname, "rump", 4) != 0 &&
|
||||
strncmp(cursymname, "RUMP", 4) != 0 &&
|
||||
strncmp(cursymname, "__", 2) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
memcpy(symtab + symtaboff,
|
||||
(const uint8_t *)syms_base + i*SYM_GETSIZE(),SYM_GETSIZE());
|
||||
|
||||
/*
|
||||
* set name to point at new strtab, offset symbol value
|
||||
* with lib base address.
|
||||
*/
|
||||
csym = symtab + symtaboff;
|
||||
SYMn_SETMEMBER(csym, 0, st_name, strtaboff);
|
||||
SYMn_GETMEMBER(csym, 0, st_value, value);
|
||||
SYMn_SETMEMBER(csym, 0, st_value,(intptr_t)(value+map->l_addr));
|
||||
symtaboff += SYM_GETSIZE();
|
||||
|
||||
strcpy(strtab + strtaboff, cursymname);
|
||||
strtaboff += strlen(cursymname)+1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
process_object(void *handle,
|
||||
rump_modinit_fn domodinit, rump_compload_fn docompload)
|
||||
{
|
||||
const struct modinfo *const *mi_start, *const *mi_end;
|
||||
struct rump_component *const *rc, *const *rc_end;
|
||||
|
||||
mi_start = dlsym(handle, "__start_link_set_modules");
|
||||
mi_end = dlsym(handle, "__stop_link_set_modules");
|
||||
if (mi_start && mi_end)
|
||||
domodinit(mi_start, (size_t)(mi_end-mi_start));
|
||||
|
||||
rc = dlsym(handle, "__start_link_set_rump_components");
|
||||
rc_end = dlsym(handle, "__stop_link_set_rump_components");
|
||||
if (rc && rc_end) {
|
||||
for (; rc < rc_end; rc++)
|
||||
docompload(*rc);
|
||||
assert(rc == rc_end);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the linkmap from the dynlinker. Try to load kernel modules
|
||||
* from all objects in the linkmap.
|
||||
*/
|
||||
void
|
||||
rumpuser_dl_bootstrap(rump_modinit_fn domodinit,
|
||||
rump_symload_fn symload, rump_compload_fn compload)
|
||||
{
|
||||
struct link_map *map, *origmap, *mainmap;
|
||||
void *mainhandle;
|
||||
int error;
|
||||
|
||||
mainhandle = dlopen(NULL, RTLD_NOW);
|
||||
/* Will be null if statically linked so just return */
|
||||
if (mainhandle == NULL)
|
||||
return;
|
||||
if (dlinfo(mainhandle, RTLD_DI_LINKMAP, &mainmap) == -1) {
|
||||
fprintf(stderr, "warning: rumpuser module bootstrap "
|
||||
"failed: %s\n", dlerror());
|
||||
return;
|
||||
}
|
||||
origmap = mainmap;
|
||||
|
||||
/*
|
||||
* Use a heuristic to determine if we are static linked.
|
||||
* A dynamically linked binary should always have at least
|
||||
* two objects: itself and ld.so.
|
||||
*
|
||||
* In a statically linked binary with glibc the linkmap
|
||||
* contains some "info" that leads to a segfault. Since we
|
||||
* can't really do anything useful in here without ld.so, just
|
||||
* simply bail and let the symbol references in librump do the
|
||||
* right things.
|
||||
*/
|
||||
if (origmap->l_next == NULL && origmap->l_prev == NULL) {
|
||||
dlclose(mainhandle);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Process last->first because that's the most probable
|
||||
* order for dependencies
|
||||
*/
|
||||
for (; origmap->l_next; origmap = origmap->l_next)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Build symbol table to hand to the rump kernel. Do this by
|
||||
* iterating over all rump libraries and collecting symbol
|
||||
* addresses and relocation info.
|
||||
*/
|
||||
error = 0;
|
||||
for (map = origmap; map && !error; map = map->l_prev) {
|
||||
if (strstr(map->l_name, "librump") != NULL || map == mainmap)
|
||||
error = getsymbols(map, map == mainmap);
|
||||
}
|
||||
|
||||
if (error == 0) {
|
||||
void *trimmedsym, *trimmedstr;
|
||||
|
||||
/*
|
||||
* Allocate optimum-sized memory for storing tables
|
||||
* and feed to kernel. If memory allocation fails,
|
||||
* just give the ones with extra context (although
|
||||
* I'm pretty sure we'll die moments later due to
|
||||
* memory running out).
|
||||
*/
|
||||
if ((trimmedsym = malloc(symtaboff)) != NULL) {
|
||||
memcpy(trimmedsym, symtab, symtaboff);
|
||||
} else {
|
||||
trimmedsym = symtab;
|
||||
symtab = NULL;
|
||||
}
|
||||
if ((trimmedstr = malloc(strtaboff)) != NULL) {
|
||||
memcpy(trimmedstr, strtab, strtaboff);
|
||||
} else {
|
||||
trimmedstr = strtab;
|
||||
strtab = NULL;
|
||||
}
|
||||
symload(trimmedsym, symtaboff, trimmedstr, strtaboff);
|
||||
}
|
||||
free(symtab);
|
||||
free(strtab);
|
||||
|
||||
/*
|
||||
* Next, load modules and components.
|
||||
*
|
||||
* Simply loop through all objects, ones unrelated to rump kernels
|
||||
* will not contain link_set_rump_components (well, not including
|
||||
* "sabotage", but that needs to be solved at another level anyway).
|
||||
*/
|
||||
for (map = origmap; map; map = map->l_prev) {
|
||||
void *handle;
|
||||
|
||||
if (map == mainmap) {
|
||||
handle = mainhandle;
|
||||
} else {
|
||||
handle = dlopen(map->l_name, RTLD_LAZY);
|
||||
if (handle == NULL)
|
||||
continue;
|
||||
}
|
||||
process_object(handle, domodinit, compload);
|
||||
if (map != mainmap)
|
||||
dlclose(handle);
|
||||
}
|
||||
}
|
||||
#else
|
||||
/*
|
||||
* no dynamic linking supported
|
||||
*/
|
||||
void
|
||||
rumpuser_dl_bootstrap(rump_modinit_fn domodinit,
|
||||
rump_symload_fn symload, rump_compload_fn compload)
|
||||
{
|
||||
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
321
lib/librumpuser/rumpuser_errtrans.c
Normal file
321
lib/librumpuser/rumpuser_errtrans.c
Normal file
|
|
@ -0,0 +1,321 @@
|
|||
/* $NetBSD: rumpuser_errtrans.c,v 1.1 2013/04/30 12:39:20 pooka Exp $ */
|
||||
|
||||
/*
|
||||
* pseudo-automatically generated. PLEASE DO EDIT (e.g. in case there
|
||||
* are errnos which are defined to be the same value)
|
||||
*
|
||||
* awk '/^#define/{printf "#ifdef %s\n\tcase %-15s: return %s;\n#endif\n", \
|
||||
* $2, $2, $3}' < errno.h
|
||||
*
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
/*
|
||||
* Translate host errno to rump kernel errno
|
||||
*/
|
||||
int rumpuser__errtrans(int); /* a naughty decouple */
|
||||
int
|
||||
rumpuser__errtrans(int hosterr)
|
||||
{
|
||||
|
||||
/* just in case the vompiler is being silly */
|
||||
if (hosterr == 0)
|
||||
return 0;
|
||||
|
||||
switch (hosterr) {
|
||||
#ifdef EPERM
|
||||
case EPERM : return 1;
|
||||
#endif
|
||||
#ifdef ENOENT
|
||||
case ENOENT : return 2;
|
||||
#endif
|
||||
#ifdef ESRCH
|
||||
case ESRCH : return 3;
|
||||
#endif
|
||||
#ifdef EINTR
|
||||
case EINTR : return 4;
|
||||
#endif
|
||||
#ifdef EIO
|
||||
case EIO : return 5;
|
||||
#endif
|
||||
#ifdef ENXIO
|
||||
case ENXIO : return 6;
|
||||
#endif
|
||||
#ifdef E2BIG
|
||||
case E2BIG : return 7;
|
||||
#endif
|
||||
#ifdef ENOEXEC
|
||||
case ENOEXEC : return 8;
|
||||
#endif
|
||||
#ifdef EBADF
|
||||
case EBADF : return 9;
|
||||
#endif
|
||||
#ifdef ECHILD
|
||||
case ECHILD : return 10;
|
||||
#endif
|
||||
#ifdef EDEADLK
|
||||
case EDEADLK : return 11;
|
||||
#endif
|
||||
#ifdef ENOMEM
|
||||
case ENOMEM : return 12;
|
||||
#endif
|
||||
#ifdef EACCES
|
||||
case EACCES : return 13;
|
||||
#endif
|
||||
#ifdef EFAULT
|
||||
case EFAULT : return 14;
|
||||
#endif
|
||||
#ifdef ENOTBLK
|
||||
case ENOTBLK : return 15;
|
||||
#endif
|
||||
#ifdef EBUSY
|
||||
case EBUSY : return 16;
|
||||
#endif
|
||||
#ifdef EEXIST
|
||||
case EEXIST : return 17;
|
||||
#endif
|
||||
#ifdef EXDEV
|
||||
case EXDEV : return 18;
|
||||
#endif
|
||||
#ifdef ENODEV
|
||||
case ENODEV : return 19;
|
||||
#endif
|
||||
#ifdef ENOTDIR
|
||||
case ENOTDIR : return 20;
|
||||
#endif
|
||||
#ifdef EISDIR
|
||||
case EISDIR : return 21;
|
||||
#endif
|
||||
#ifdef EINVAL
|
||||
case EINVAL : return 22;
|
||||
#endif
|
||||
#ifdef ENFILE
|
||||
case ENFILE : return 23;
|
||||
#endif
|
||||
#ifdef EMFILE
|
||||
case EMFILE : return 24;
|
||||
#endif
|
||||
#ifdef ENOTTY
|
||||
case ENOTTY : return 25;
|
||||
#endif
|
||||
#ifdef ETXTBSY
|
||||
case ETXTBSY : return 26;
|
||||
#endif
|
||||
#ifdef EFBIG
|
||||
case EFBIG : return 27;
|
||||
#endif
|
||||
#ifdef ENOSPC
|
||||
case ENOSPC : return 28;
|
||||
#endif
|
||||
#ifdef ESPIPE
|
||||
case ESPIPE : return 29;
|
||||
#endif
|
||||
#ifdef EROFS
|
||||
case EROFS : return 30;
|
||||
#endif
|
||||
#ifdef EMLINK
|
||||
case EMLINK : return 31;
|
||||
#endif
|
||||
#ifdef EPIPE
|
||||
case EPIPE : return 32;
|
||||
#endif
|
||||
#ifdef EDOM
|
||||
case EDOM : return 33;
|
||||
#endif
|
||||
#ifdef ERANGE
|
||||
case ERANGE : return 34;
|
||||
#endif
|
||||
#ifdef EAGAIN
|
||||
case EAGAIN : return 35;
|
||||
#endif
|
||||
#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
|
||||
case EWOULDBLOCK : return 35;
|
||||
#endif
|
||||
#ifdef EINPROGRESS
|
||||
case EINPROGRESS : return 36;
|
||||
#endif
|
||||
#ifdef EALREADY
|
||||
case EALREADY : return 37;
|
||||
#endif
|
||||
#ifdef ENOTSOCK
|
||||
case ENOTSOCK : return 38;
|
||||
#endif
|
||||
#ifdef EDESTADDRREQ
|
||||
case EDESTADDRREQ : return 39;
|
||||
#endif
|
||||
#ifdef EMSGSIZE
|
||||
case EMSGSIZE : return 40;
|
||||
#endif
|
||||
#ifdef EPROTOTYPE
|
||||
case EPROTOTYPE : return 41;
|
||||
#endif
|
||||
#ifdef ENOPROTOOPT
|
||||
case ENOPROTOOPT : return 42;
|
||||
#endif
|
||||
#ifdef EPROTONOSUPPORT
|
||||
case EPROTONOSUPPORT: return 43;
|
||||
#endif
|
||||
#ifdef ESOCKTNOSUPPORT
|
||||
case ESOCKTNOSUPPORT: return 44;
|
||||
#endif
|
||||
#ifdef EOPNOTSUPP
|
||||
case EOPNOTSUPP : return 45;
|
||||
#endif
|
||||
#ifdef EPFNOSUPPORT
|
||||
case EPFNOSUPPORT : return 46;
|
||||
#endif
|
||||
#ifdef EAFNOSUPPORT
|
||||
case EAFNOSUPPORT : return 47;
|
||||
#endif
|
||||
#ifdef EADDRINUSE
|
||||
case EADDRINUSE : return 48;
|
||||
#endif
|
||||
#ifdef EADDRNOTAVAIL
|
||||
case EADDRNOTAVAIL : return 49;
|
||||
#endif
|
||||
#ifdef ENETDOWN
|
||||
case ENETDOWN : return 50;
|
||||
#endif
|
||||
#ifdef ENETUNREACH
|
||||
case ENETUNREACH : return 51;
|
||||
#endif
|
||||
#ifdef ENETRESET
|
||||
case ENETRESET : return 52;
|
||||
#endif
|
||||
#ifdef ECONNABORTED
|
||||
case ECONNABORTED : return 53;
|
||||
#endif
|
||||
#ifdef ECONNRESET
|
||||
case ECONNRESET : return 54;
|
||||
#endif
|
||||
#ifdef ENOBUFS
|
||||
case ENOBUFS : return 55;
|
||||
#endif
|
||||
#ifdef EISCONN
|
||||
case EISCONN : return 56;
|
||||
#endif
|
||||
#ifdef ENOTCONN
|
||||
case ENOTCONN : return 57;
|
||||
#endif
|
||||
#ifdef ESHUTDOWN
|
||||
case ESHUTDOWN : return 58;
|
||||
#endif
|
||||
#ifdef ETOOMANYREFS
|
||||
case ETOOMANYREFS : return 59;
|
||||
#endif
|
||||
#ifdef ETIMEDOUT
|
||||
case ETIMEDOUT : return 60;
|
||||
#endif
|
||||
#ifdef ECONNREFUSED
|
||||
case ECONNREFUSED : return 61;
|
||||
#endif
|
||||
#ifdef ELOOP
|
||||
case ELOOP : return 62;
|
||||
#endif
|
||||
#ifdef ENAMETOOLONG
|
||||
case ENAMETOOLONG : return 63;
|
||||
#endif
|
||||
#ifdef EHOSTDOWN
|
||||
case EHOSTDOWN : return 64;
|
||||
#endif
|
||||
#ifdef EHOSTUNREACH
|
||||
case EHOSTUNREACH : return 65;
|
||||
#endif
|
||||
#ifdef ENOTEMPTY
|
||||
case ENOTEMPTY : return 66;
|
||||
#endif
|
||||
#ifdef EPROCLIM
|
||||
case EPROCLIM : return 67;
|
||||
#endif
|
||||
#ifdef EUSERS
|
||||
case EUSERS : return 68;
|
||||
#endif
|
||||
#ifdef EDQUOT
|
||||
case EDQUOT : return 69;
|
||||
#endif
|
||||
#ifdef ESTALE
|
||||
case ESTALE : return 70;
|
||||
#endif
|
||||
#ifdef EREMOTE
|
||||
case EREMOTE : return 71;
|
||||
#endif
|
||||
#ifdef EBADRPC
|
||||
case EBADRPC : return 72;
|
||||
#endif
|
||||
#ifdef ERPCMISMATCH
|
||||
case ERPCMISMATCH : return 73;
|
||||
#endif
|
||||
#ifdef EPROGUNAVAIL
|
||||
case EPROGUNAVAIL : return 74;
|
||||
#endif
|
||||
#ifdef EPROGMISMATCH
|
||||
case EPROGMISMATCH : return 75;
|
||||
#endif
|
||||
#ifdef EPROCUNAVAIL
|
||||
case EPROCUNAVAIL : return 76;
|
||||
#endif
|
||||
#ifdef ENOLCK
|
||||
case ENOLCK : return 77;
|
||||
#endif
|
||||
#ifdef ENOSYS
|
||||
case ENOSYS : return 78;
|
||||
#endif
|
||||
#ifdef EFTYPE
|
||||
case EFTYPE : return 79;
|
||||
#endif
|
||||
#ifdef EAUTH
|
||||
case EAUTH : return 80;
|
||||
#endif
|
||||
#ifdef ENEEDAUTH
|
||||
case ENEEDAUTH : return 81;
|
||||
#endif
|
||||
#ifdef EIDRM
|
||||
case EIDRM : return 82;
|
||||
#endif
|
||||
#ifdef ENOMSG
|
||||
case ENOMSG : return 83;
|
||||
#endif
|
||||
#ifdef EOVERFLOW
|
||||
case EOVERFLOW : return 84;
|
||||
#endif
|
||||
#ifdef EILSEQ
|
||||
case EILSEQ : return 85;
|
||||
#endif
|
||||
#if defined(ENOTSUP) && (!defined(EOPNOTSUPP) || ENOTSUP != EOPNOTSUPP)
|
||||
case ENOTSUP : return 86;
|
||||
#endif
|
||||
#ifdef ECANCELED
|
||||
case ECANCELED : return 87;
|
||||
#endif
|
||||
#ifdef EBADMSG
|
||||
case EBADMSG : return 88;
|
||||
#endif
|
||||
#ifdef ENODATA
|
||||
case ENODATA : return 89;
|
||||
#endif
|
||||
#ifdef ENOSR
|
||||
case ENOSR : return 90;
|
||||
#endif
|
||||
#ifdef ENOSTR
|
||||
case ENOSTR : return 91;
|
||||
#endif
|
||||
#ifdef ETIME
|
||||
case ETIME : return 92;
|
||||
#endif
|
||||
#ifdef ENOATTR
|
||||
case ENOATTR : return 93;
|
||||
#endif
|
||||
#ifdef EMULTIHOP
|
||||
case EMULTIHOP : return 94;
|
||||
#endif
|
||||
#ifdef ENOLINK
|
||||
case ENOLINK : return 95;
|
||||
#endif
|
||||
#ifdef EPROTO
|
||||
case EPROTO : return 96;
|
||||
#endif
|
||||
|
||||
default : return 22; /* EINVAL */
|
||||
}
|
||||
}
|
||||
342
lib/librumpuser/rumpuser_file.c
Normal file
342
lib/librumpuser/rumpuser_file.c
Normal file
|
|
@ -0,0 +1,342 @@
|
|||
/* $NetBSD: rumpuser_file.c,v 1.4 2014/11/04 21:08:12 pooka Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007-2010 Antti Kantee. 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
*/
|
||||
|
||||
/* NOTE this code will move to a new driver in the next hypercall revision */
|
||||
|
||||
#include "rumpuser_port.h"
|
||||
|
||||
#if !defined(lint)
|
||||
__RCSID("$NetBSD: rumpuser_file.c,v 1.4 2014/11/04 21:08:12 pooka Exp $");
|
||||
#endif /* !lint */
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#if defined(HAVE_SYS_DISK_H)
|
||||
#include <sys/disk.h>
|
||||
#endif
|
||||
#if defined(HAVE_SYS_DISKLABEL_H)
|
||||
#include <sys/disklabel.h>
|
||||
#endif
|
||||
#if defined(HAVE_SYS_DKIO_H)
|
||||
#include <sys/dkio.h>
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_SYS_SYSCTL_H)
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <netdb.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <rump/rumpuser.h>
|
||||
|
||||
#include "rumpuser_int.h"
|
||||
|
||||
int
|
||||
rumpuser_getfileinfo(const char *path, uint64_t *sizep, int *ftp)
|
||||
{
|
||||
struct stat sb;
|
||||
uint64_t size = 0;
|
||||
int needsdev = 0, rv = 0, ft = 0;
|
||||
int fd = -1;
|
||||
|
||||
if (stat(path, &sb) == -1) {
|
||||
rv = errno;
|
||||
goto out;
|
||||
}
|
||||
|
||||
switch (sb.st_mode & S_IFMT) {
|
||||
case S_IFDIR:
|
||||
ft = RUMPUSER_FT_DIR;
|
||||
break;
|
||||
case S_IFREG:
|
||||
ft = RUMPUSER_FT_REG;
|
||||
break;
|
||||
case S_IFBLK:
|
||||
ft = RUMPUSER_FT_BLK;
|
||||
needsdev = 1;
|
||||
break;
|
||||
case S_IFCHR:
|
||||
ft = RUMPUSER_FT_CHR;
|
||||
needsdev = 1;
|
||||
break;
|
||||
default:
|
||||
ft = RUMPUSER_FT_OTHER;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!needsdev) {
|
||||
size = sb.st_size;
|
||||
} else if (sizep) {
|
||||
/*
|
||||
* Welcome to the jungle. Of course querying the kernel
|
||||
* for a device partition size is supposed to be far from
|
||||
* trivial. On NetBSD we use ioctl. On $other platform
|
||||
* we have a problem. We try "the lseek trick" and just
|
||||
* fail if that fails. Platform specific code can later
|
||||
* be written here if appropriate.
|
||||
*
|
||||
* On NetBSD we hope and pray that for block devices nobody
|
||||
* else is holding them open, because otherwise the kernel
|
||||
* will not permit us to open it. Thankfully, this is
|
||||
* usually called only in bootstrap and then we can
|
||||
* forget about it.
|
||||
*/
|
||||
|
||||
fd = open(path, O_RDONLY);
|
||||
if (fd == -1) {
|
||||
rv = errno;
|
||||
goto out;
|
||||
}
|
||||
|
||||
#if (!defined(DIOCGDINFO) || !defined(DISKPART)) && !defined(DIOCGWEDGEINFO)
|
||||
{
|
||||
off_t off = lseek(fd, 0, SEEK_END);
|
||||
if (off != 0) {
|
||||
size = off;
|
||||
goto out;
|
||||
}
|
||||
fprintf(stderr, "error: device size query not implemented on "
|
||||
"this platform\n");
|
||||
rv = EOPNOTSUPP;
|
||||
goto out;
|
||||
}
|
||||
#else
|
||||
|
||||
#if defined(DIOCGDINFO) && defined(DISKPART)
|
||||
{
|
||||
struct disklabel lab;
|
||||
struct partition *parta;
|
||||
if (ioctl(fd, DIOCGDINFO, &lab) == 0) {
|
||||
parta = &lab.d_partitions[DISKPART(sb.st_rdev)];
|
||||
size = (uint64_t)lab.d_secsize * parta->p_size;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(DIOCGWEDGEINFO)
|
||||
{
|
||||
struct dkwedge_info dkw;
|
||||
if (ioctl(fd, DIOCGWEDGEINFO, &dkw) == 0) {
|
||||
/*
|
||||
* XXX: should use DIOCGDISKINFO to query
|
||||
* sector size, but that requires proplib,
|
||||
* so just don't bother for now. it's nice
|
||||
* that something as difficult as figuring out
|
||||
* a partition's size has been made so easy.
|
||||
*/
|
||||
size = dkw.dkw_size << DEV_BSHIFT;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
rv = errno;
|
||||
#endif
|
||||
}
|
||||
|
||||
out:
|
||||
if (rv == 0 && sizep)
|
||||
*sizep = size;
|
||||
if (rv == 0 && ftp)
|
||||
*ftp = ft;
|
||||
if (fd != -1)
|
||||
close(fd);
|
||||
|
||||
ET(rv);
|
||||
}
|
||||
|
||||
int
|
||||
rumpuser_open(const char *path, int ruflags, int *fdp)
|
||||
{
|
||||
int fd, flags, rv;
|
||||
|
||||
switch (ruflags & RUMPUSER_OPEN_ACCMODE) {
|
||||
case RUMPUSER_OPEN_RDONLY:
|
||||
flags = O_RDONLY;
|
||||
break;
|
||||
case RUMPUSER_OPEN_WRONLY:
|
||||
flags = O_WRONLY;
|
||||
break;
|
||||
case RUMPUSER_OPEN_RDWR:
|
||||
flags = O_RDWR;
|
||||
break;
|
||||
default:
|
||||
rv = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
#define TESTSET(_ru_, _h_) if (ruflags & _ru_) flags |= _h_;
|
||||
TESTSET(RUMPUSER_OPEN_CREATE, O_CREAT);
|
||||
TESTSET(RUMPUSER_OPEN_EXCL, O_EXCL);
|
||||
#undef TESTSET
|
||||
|
||||
KLOCK_WRAP(fd = open(path, flags, 0644));
|
||||
if (fd == -1) {
|
||||
rv = errno;
|
||||
} else {
|
||||
*fdp = fd;
|
||||
rv = 0;
|
||||
}
|
||||
|
||||
out:
|
||||
ET(rv);
|
||||
}
|
||||
|
||||
int
|
||||
rumpuser_close(int fd)
|
||||
{
|
||||
int nlocks;
|
||||
|
||||
rumpkern_unsched(&nlocks, NULL);
|
||||
fsync(fd);
|
||||
close(fd);
|
||||
rumpkern_sched(nlocks, NULL);
|
||||
|
||||
ET(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Assume "struct rumpuser_iovec" and "struct iovec" are the same.
|
||||
* If you encounter POSIX platforms where they aren't, add some
|
||||
* translation for iovlen > 1.
|
||||
*/
|
||||
int
|
||||
rumpuser_iovread(int fd, struct rumpuser_iovec *ruiov, size_t iovlen,
|
||||
int64_t roff, size_t *retp)
|
||||
{
|
||||
struct iovec *iov = (struct iovec *)ruiov;
|
||||
off_t off = (off_t)roff;
|
||||
ssize_t nn;
|
||||
int rv;
|
||||
|
||||
if (off == RUMPUSER_IOV_NOSEEK) {
|
||||
KLOCK_WRAP(nn = readv(fd, iov, iovlen));
|
||||
} else {
|
||||
int nlocks;
|
||||
|
||||
rumpkern_unsched(&nlocks, NULL);
|
||||
if (lseek(fd, off, SEEK_SET) == off) {
|
||||
nn = readv(fd, iov, iovlen);
|
||||
} else {
|
||||
nn = -1;
|
||||
}
|
||||
rumpkern_sched(nlocks, NULL);
|
||||
}
|
||||
|
||||
if (nn == -1) {
|
||||
rv = errno;
|
||||
} else {
|
||||
*retp = (size_t)nn;
|
||||
rv = 0;
|
||||
}
|
||||
|
||||
ET(rv);
|
||||
}
|
||||
|
||||
int
|
||||
rumpuser_iovwrite(int fd, const struct rumpuser_iovec *ruiov, size_t iovlen,
|
||||
int64_t roff, size_t *retp)
|
||||
{
|
||||
const struct iovec *iov = (const struct iovec *)ruiov;
|
||||
off_t off = (off_t)roff;
|
||||
ssize_t nn;
|
||||
int rv;
|
||||
|
||||
if (off == RUMPUSER_IOV_NOSEEK) {
|
||||
KLOCK_WRAP(nn = writev(fd, iov, iovlen));
|
||||
} else {
|
||||
int nlocks;
|
||||
|
||||
rumpkern_unsched(&nlocks, NULL);
|
||||
if (lseek(fd, off, SEEK_SET) == off) {
|
||||
nn = writev(fd, iov, iovlen);
|
||||
} else {
|
||||
nn = -1;
|
||||
}
|
||||
rumpkern_sched(nlocks, NULL);
|
||||
}
|
||||
|
||||
if (nn == -1) {
|
||||
rv = errno;
|
||||
} else {
|
||||
*retp = (size_t)nn;
|
||||
rv = 0;
|
||||
}
|
||||
|
||||
ET(rv);
|
||||
}
|
||||
|
||||
int
|
||||
rumpuser_syncfd(int fd, int flags, uint64_t start, uint64_t len)
|
||||
{
|
||||
int rv = 0;
|
||||
|
||||
/*
|
||||
* For now, assume fd is regular file and does not care
|
||||
* about read syncing
|
||||
*/
|
||||
if ((flags & RUMPUSER_SYNCFD_BOTH) == 0) {
|
||||
rv = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if ((flags & RUMPUSER_SYNCFD_WRITE) == 0) {
|
||||
rv = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
#if defined(HAVE_FSYNC_RANGE)
|
||||
{
|
||||
int fsflags = FDATASYNC;
|
||||
|
||||
if (fsflags & RUMPUSER_SYNCFD_SYNC)
|
||||
fsflags |= FDISKSYNC;
|
||||
if (fsync_range(fd, fsflags, start, len) == -1)
|
||||
rv = errno;
|
||||
}
|
||||
#else
|
||||
/* el-simplo */
|
||||
if (fsync(fd) == -1)
|
||||
rv = errno;
|
||||
#endif
|
||||
|
||||
out:
|
||||
ET(rv);
|
||||
}
|
||||
105
lib/librumpuser/rumpuser_int.h
Normal file
105
lib/librumpuser/rumpuser_int.h
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
/* $NetBSD: rumpuser_int.h,v 1.10 2014/07/22 22:41:58 justin Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2008 Antti Kantee. 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 <stdlib.h>
|
||||
|
||||
#include <rump/rumpuser.h>
|
||||
|
||||
#define seterror(value) do { if (error) *error = value;} while (/*CONSTCOND*/0)
|
||||
|
||||
extern struct rumpuser_hyperup rumpuser__hyp;
|
||||
|
||||
static inline void
|
||||
rumpkern_unsched(int *nlocks, void *interlock)
|
||||
{
|
||||
|
||||
rumpuser__hyp.hyp_backend_unschedule(0, nlocks, interlock);
|
||||
}
|
||||
|
||||
static inline void
|
||||
rumpkern_sched(int nlocks, void *interlock)
|
||||
{
|
||||
|
||||
rumpuser__hyp.hyp_backend_schedule(nlocks, interlock);
|
||||
}
|
||||
|
||||
#define KLOCK_WRAP(a) \
|
||||
do { \
|
||||
int nlocks; \
|
||||
rumpkern_unsched(&nlocks, NULL); \
|
||||
a; \
|
||||
rumpkern_sched(nlocks, NULL); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define DOCALL(rvtype, call) \
|
||||
{ \
|
||||
rvtype rv; \
|
||||
rv = call; \
|
||||
if (rv == -1) \
|
||||
seterror(errno); \
|
||||
else \
|
||||
seterror(0); \
|
||||
return rv; \
|
||||
}
|
||||
|
||||
#define DOCALL_KLOCK(rvtype, call) \
|
||||
{ \
|
||||
rvtype rv; \
|
||||
int nlocks; \
|
||||
rumpkern_unsched(&nlocks, NULL); \
|
||||
rv = call; \
|
||||
rumpkern_sched(nlocks, NULL); \
|
||||
if (rv == -1) \
|
||||
seterror(errno); \
|
||||
else \
|
||||
seterror(0); \
|
||||
return rv; \
|
||||
}
|
||||
|
||||
void rumpuser__thrinit(void);
|
||||
|
||||
#define NOFAIL(a) do {if (!(a)) abort();} while (/*CONSTCOND*/0)
|
||||
|
||||
#define NOFAIL_ERRNO(a) \
|
||||
do { \
|
||||
int fail_rv = (a); \
|
||||
if (fail_rv) { \
|
||||
printf("panic: rumpuser fatal failure %d (%s)\n", \
|
||||
fail_rv, strerror(fail_rv)); \
|
||||
abort(); \
|
||||
} \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
int rumpuser__sig_rump2host(int);
|
||||
int rumpuser__errtrans(int);
|
||||
#ifdef __NetBSD__
|
||||
#define ET(_v_) return (_v_);
|
||||
#else
|
||||
#define ET(_v_) return (_v_) ? rumpuser__errtrans(_v_) : 0;
|
||||
#endif
|
||||
|
||||
int rumpuser__random_init(void);
|
||||
111
lib/librumpuser/rumpuser_mem.c
Normal file
111
lib/librumpuser/rumpuser_mem.c
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
/* $NetBSD: rumpuser_mem.c,v 1.2 2014/08/24 14:37:31 pooka Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007-2010 Antti Kantee. 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "rumpuser_port.h"
|
||||
|
||||
#if !defined(lint)
|
||||
__RCSID("$NetBSD: rumpuser_mem.c,v 1.2 2014/08/24 14:37:31 pooka Exp $");
|
||||
#endif /* !lint */
|
||||
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <rump/rumpuser.h>
|
||||
|
||||
#include "rumpuser_int.h"
|
||||
|
||||
int
|
||||
rumpuser_malloc(size_t howmuch, int alignment, void **memp)
|
||||
{
|
||||
void *mem = NULL;
|
||||
int rv;
|
||||
|
||||
if (alignment == 0)
|
||||
alignment = sizeof(void *);
|
||||
|
||||
rv = posix_memalign(&mem, (size_t)alignment, howmuch);
|
||||
if (__predict_false(rv != 0)) {
|
||||
if (rv == EINVAL) {
|
||||
printf("rumpuser_malloc: invalid alignment %d\n",
|
||||
alignment);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
*memp = mem;
|
||||
ET(rv);
|
||||
}
|
||||
|
||||
/*ARGSUSED1*/
|
||||
void
|
||||
rumpuser_free(void *ptr, size_t size)
|
||||
{
|
||||
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
int
|
||||
rumpuser_anonmmap(void *prefaddr, size_t size, int alignbit,
|
||||
int exec, void **memp)
|
||||
{
|
||||
void *mem;
|
||||
int prot, rv;
|
||||
|
||||
#ifndef MAP_ALIGNED
|
||||
#define MAP_ALIGNED(a) 0
|
||||
if (alignbit)
|
||||
fprintf(stderr, "rumpuser_anonmmap: warning, requested "
|
||||
"alignment not supported by hypervisor\n");
|
||||
#endif
|
||||
|
||||
prot = PROT_READ|PROT_WRITE;
|
||||
if (exec)
|
||||
prot |= PROT_EXEC;
|
||||
mem = mmap(prefaddr, size, prot,
|
||||
MAP_PRIVATE | MAP_ANON | MAP_ALIGNED(alignbit), -1, 0);
|
||||
if (mem == MAP_FAILED) {
|
||||
rv = errno;
|
||||
} else {
|
||||
*memp = mem;
|
||||
rv = 0;
|
||||
}
|
||||
|
||||
ET(rv);
|
||||
}
|
||||
|
||||
void
|
||||
rumpuser_unmap(void *addr, size_t len)
|
||||
{
|
||||
|
||||
munmap(addr, len);
|
||||
}
|
||||
|
||||
329
lib/librumpuser/rumpuser_port.h
Normal file
329
lib/librumpuser/rumpuser_port.h
Normal file
|
|
@ -0,0 +1,329 @@
|
|||
/* $NetBSD: rumpuser_port.h,v 1.46 2015/09/21 21:50:16 pooka Exp $ */
|
||||
|
||||
#ifndef _LIB_LIBRUMPUSER_RUMPUSER_PORT_H_
|
||||
#define _LIB_LIBRUMPUSER_RUMPUSER_PORT_H_
|
||||
|
||||
/*
|
||||
* Define things found by autoconf. buildrump.sh defines RUMPUSER_CONFIG,
|
||||
* the NetBSD build does not run autoconf during build and supplies the
|
||||
* necessary values here. To update the NetBSD values, run ./configure
|
||||
* for an up-to-date NetBSD installation and insert rumpuser_config.h
|
||||
* in the space below, e.g. with ":r !sed -ne '/^\#/p' rumpuser_config.h"
|
||||
*/
|
||||
#if !defined(RUMPUSER_CONFIG)
|
||||
|
||||
#define HAVE_ARC4RANDOM_BUF 1
|
||||
#define HAVE_CHFLAGS 1
|
||||
#define HAVE_CLOCKID_T 1
|
||||
#define HAVE_CLOCK_GETTIME 1
|
||||
#define HAVE_CLOCK_NANOSLEEP 1
|
||||
#define HAVE_DLINFO 1
|
||||
#define HAVE_FSYNC_RANGE 1
|
||||
#define HAVE_GETENV_R 1
|
||||
#define HAVE_GETPROGNAME 1
|
||||
#define HAVE_GETSUBOPT 1
|
||||
#define HAVE_INTTYPES_H 1
|
||||
#define HAVE_KQUEUE 1
|
||||
#define HAVE_MEMORY_H 1
|
||||
#define HAVE_PATHS_H 1
|
||||
#define HAVE_POSIX_MEMALIGN 1
|
||||
#define HAVE_PTHREAD_SETNAME3 1
|
||||
#define HAVE_REGISTER_T 1
|
||||
#define HAVE_SETPROGNAME 1
|
||||
#define HAVE_STDINT_H 1
|
||||
#define HAVE_STDLIB_H 1
|
||||
#define HAVE_STRINGS_H 1
|
||||
#define HAVE_STRING_H 1
|
||||
#define HAVE_STRSUFTOLL 1
|
||||
#define HAVE_STRUCT_SOCKADDR_IN_SIN_LEN 1
|
||||
#define HAVE_SYS_ATOMIC_H 1
|
||||
#define HAVE_SYS_CDEFS_H 1
|
||||
#define HAVE_SYS_DISKLABEL_H 1
|
||||
#define HAVE_SYS_DISK_H 1
|
||||
#define HAVE_SYS_DKIO_H 1
|
||||
#define HAVE_SYS_PARAM_H 1
|
||||
#define HAVE_SYS_STAT_H 1
|
||||
#define HAVE_SYS_SYSCTL_H 1
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
#define HAVE_UNISTD_H 1
|
||||
#define HAVE___QUOTACTL 1
|
||||
#define HAVE_UTIMENSAT 1
|
||||
#define PACKAGE_BUGREPORT "http://rumpkernel.org/"
|
||||
#define PACKAGE_NAME "rumpuser-posix"
|
||||
#define PACKAGE_STRING "rumpuser-posix 999"
|
||||
#define PACKAGE_TARNAME "rumpuser-posix"
|
||||
#define PACKAGE_URL ""
|
||||
#define PACKAGE_VERSION "999"
|
||||
#define STDC_HEADERS 1
|
||||
#ifndef _DARWIN_USE_64_BIT_INODE
|
||||
# define _DARWIN_USE_64_BIT_INODE 1
|
||||
#endif
|
||||
|
||||
#else /* RUMPUSER_CONFIG */
|
||||
#include "rumpuser_config.h"
|
||||
#endif
|
||||
|
||||
#if defined(__linux__) || defined(__GNU__) || defined(__GLIBC__)
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_SYS_CDEFS_H)
|
||||
#include <sys/cdefs.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Some versions of FreeBSD (e.g. 9.2) contain C11 stuff without
|
||||
* any obvious way to expose the protos. Kludge around it.
|
||||
*/
|
||||
#ifdef __FreeBSD__
|
||||
#if __ISO_C_VISIBLE < 2011
|
||||
#undef __ISO_C_VISIBLE
|
||||
#define __ISO_C_VISIBLE 2011
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_SYS_PARAM_H)
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a,b) ((/*CONSTCOND*/(a)<(b))?(a):(b))
|
||||
#endif
|
||||
#ifndef MAX
|
||||
#define MAX(a,b) ((/*CONSTCOND*/(a)>(b))?(a):(b))
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_GETSUBOPT)
|
||||
static inline int
|
||||
getsubopt(char **optionp, char * const *tokens, char **valuep)
|
||||
{
|
||||
|
||||
/* TODO make a definition */
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_CLOCKID_T)
|
||||
typedef int clockid_t;
|
||||
#endif
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include <stdint.h>
|
||||
typedef uint16_t in_port_t;
|
||||
#include <sys/select.h>
|
||||
#define atomic_inc_uint(x) __sync_fetch_and_add(x, 1)
|
||||
#define atomic_dec_uint(x) __sync_fetch_and_sub(x, 1)
|
||||
#endif
|
||||
|
||||
/* sunny magic */
|
||||
#if defined(__sun__)
|
||||
# if defined(RUMPUSER_NO_FILE_OFFSET_BITS)
|
||||
# undef _FILE_OFFSET_BITS
|
||||
# define _FILE_OFFSET_BITS 32
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_CLOCK_GETTIME)
|
||||
#include <sys/time.h>
|
||||
#define CLOCK_REALTIME 0
|
||||
static inline int
|
||||
clock_gettime(clockid_t clk, struct timespec *ts)
|
||||
{
|
||||
struct timeval tv;
|
||||
|
||||
if (gettimeofday(&tv, 0) == 0) {
|
||||
ts->tv_sec = tv.tv_sec;
|
||||
ts->tv_nsec = tv.tv_usec * 1000;
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#include <libkern/OSAtomic.h>
|
||||
#define atomic_inc_uint(x) OSAtomicIncrement32((volatile int32_t *)(x))
|
||||
#define atomic_dec_uint(x) OSAtomicDecrement32((volatile int32_t *)(x))
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#if !defined(HAVE_GETENV_R)
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
static inline int
|
||||
getenv_r(const char *name, char *buf, size_t buflen)
|
||||
{
|
||||
char *tmp;
|
||||
|
||||
if ((tmp = getenv(name)) != NULL) {
|
||||
if (strlen(tmp) >= buflen) {
|
||||
errno = ERANGE;
|
||||
return -1;
|
||||
}
|
||||
strcpy(buf, tmp);
|
||||
return 0;
|
||||
} else {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_POSIX_MEMALIGN)
|
||||
#if !defined(HAVE_MEMALIGN)
|
||||
#error method for aligned memory allocation required
|
||||
#endif
|
||||
#include <sys/sysmacros.h>
|
||||
#include <stdlib.h>
|
||||
static inline int
|
||||
posix_memalign(void **ptr, size_t align, size_t size)
|
||||
{
|
||||
|
||||
*ptr = memalign(align, size);
|
||||
if (*ptr == NULL)
|
||||
return ENOMEM;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* For NetBSD, use COHERENCY_UNIT as the lock alignment size.
|
||||
* On other platforms, just guess it to be 64.
|
||||
*/
|
||||
#ifdef __NetBSD__
|
||||
#define RUMPUSER_LOCKALIGN COHERENCY_UNIT
|
||||
#else
|
||||
#define RUMPUSER_LOCKALIGN 64
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_ALIGNED_ALLOC)
|
||||
#include <stdlib.h>
|
||||
static inline void *
|
||||
aligned_alloc(size_t alignment, size_t size)
|
||||
{
|
||||
void *ptr;
|
||||
int rv;
|
||||
|
||||
rv = posix_memalign(&ptr, alignment, size);
|
||||
return rv ? NULL : ptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef __RCSID
|
||||
#define __RCSID(a)
|
||||
#endif
|
||||
|
||||
#ifndef INFTIM
|
||||
#define INFTIM (-1)
|
||||
#endif
|
||||
|
||||
#ifndef _DIAGASSERT
|
||||
#define _DIAGASSERT(_p_)
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_STRUCT_SOCKADDR_IN_SIN_LEN)
|
||||
#define SIN_SETLEN(a,b)
|
||||
#else
|
||||
#define SIN_SETLEN(_sin_, _len_) _sin_.sin_len = _len_
|
||||
#endif
|
||||
|
||||
#ifndef __predict_true
|
||||
#define __predict_true(a) a
|
||||
#define __predict_false(a) a
|
||||
#endif
|
||||
|
||||
#ifndef __dead
|
||||
#define __dead __attribute__((__noreturn__))
|
||||
#endif
|
||||
|
||||
#ifndef __printflike
|
||||
#ifdef __GNUC__
|
||||
#define __printflike(a,b) __attribute__((__format__ (__printf__,a,b)))
|
||||
#else
|
||||
#define __printflike(a,b)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef __noinline
|
||||
#ifdef __GNUC__
|
||||
#define __noinline __attribute__((__noinline__))
|
||||
#else
|
||||
#define __noinline
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef __arraycount
|
||||
#define __arraycount(_ar_) (sizeof(_ar_)/sizeof(_ar_[0]))
|
||||
#endif
|
||||
|
||||
#ifndef __UNCONST
|
||||
#define __UNCONST(_a_) ((void *)(unsigned long)(const void *)(_a_))
|
||||
#endif
|
||||
|
||||
#ifndef __CONCAT
|
||||
#define __CONCAT(x,y) x ## y
|
||||
#endif
|
||||
|
||||
#ifndef __STRING
|
||||
#define __STRING(x) #x
|
||||
#endif
|
||||
|
||||
#ifndef __NetBSD_Prereq__
|
||||
#define __NetBSD_Prereq__(a,b,c) 0
|
||||
#endif
|
||||
|
||||
#include <sys/socket.h>
|
||||
|
||||
#if !defined(__CMSG_ALIGN)
|
||||
#ifdef CMSG_ALIGN
|
||||
#define __CMSG_ALIGN(a) CMSG_ALIGN(a)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef PF_LOCAL
|
||||
#define PF_LOCAL PF_UNIX
|
||||
#endif
|
||||
#ifndef AF_LOCAL
|
||||
#define AF_LOCAL AF_UNIX
|
||||
#endif
|
||||
|
||||
/* pfft, but what are you going to do? */
|
||||
#ifndef MSG_NOSIGNAL
|
||||
#define MSG_NOSIGNAL 0
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_REGISTER_T) && !defined(RUMP_REGISTER_T)
|
||||
#define RUMP_REGISTER_T long
|
||||
typedef RUMP_REGISTER_T register_t;
|
||||
#endif
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
#ifndef TIMEVAL_TO_TIMESPEC
|
||||
#define TIMEVAL_TO_TIMESPEC(tv, ts) \
|
||||
do { \
|
||||
(ts)->tv_sec = (tv)->tv_sec; \
|
||||
(ts)->tv_nsec = (tv)->tv_usec * 1000; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_SETPROGNAME)
|
||||
#define setprogname(a)
|
||||
#endif
|
||||
|
||||
/* at least GNU Hurd does not specify various common hardcoded constants */
|
||||
#include <limits.h>
|
||||
#ifndef MAXPATHLEN
|
||||
#define MAXPATHLEN 4096
|
||||
#endif
|
||||
#ifndef PATH_MAX
|
||||
#define PATH_MAX MAXPATHLEN
|
||||
#endif
|
||||
#ifndef MAXHOSTNAMELEN
|
||||
#define MAXHOSTNAMELEN 256
|
||||
#endif
|
||||
|
||||
#endif /* _LIB_LIBRUMPUSER_RUMPUSER_PORT_H_ */
|
||||
747
lib/librumpuser/rumpuser_pth.c
Normal file
747
lib/librumpuser/rumpuser_pth.c
Normal file
|
|
@ -0,0 +1,747 @@
|
|||
/* $NetBSD: rumpuser_pth.c,v 1.45 2015/09/18 10:56:25 pooka Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007-2010 Antti Kantee. 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "rumpuser_port.h"
|
||||
|
||||
#if !defined(lint)
|
||||
__RCSID("$NetBSD: rumpuser_pth.c,v 1.45 2015/09/18 10:56:25 pooka Exp $");
|
||||
#endif /* !lint */
|
||||
|
||||
#include <sys/queue.h>
|
||||
|
||||
#if defined(HAVE_SYS_ATOMIC_H)
|
||||
#include <sys/atomic.h>
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <rump/rumpuser.h>
|
||||
|
||||
#include "rumpuser_int.h"
|
||||
|
||||
int
|
||||
rumpuser_thread_create(void *(*f)(void *), void *arg, const char *thrname,
|
||||
int joinable, int priority, int cpuidx, void **ptcookie)
|
||||
{
|
||||
pthread_t ptid;
|
||||
pthread_t *ptidp;
|
||||
pthread_attr_t pattr;
|
||||
int rv, i;
|
||||
|
||||
if ((rv = pthread_attr_init(&pattr)) != 0)
|
||||
return rv;
|
||||
|
||||
if (joinable) {
|
||||
NOFAIL(ptidp = malloc(sizeof(*ptidp)));
|
||||
pthread_attr_setdetachstate(&pattr, PTHREAD_CREATE_JOINABLE);
|
||||
} else {
|
||||
ptidp = &ptid;
|
||||
pthread_attr_setdetachstate(&pattr, PTHREAD_CREATE_DETACHED);
|
||||
}
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
const struct timespec ts = {0, 10*1000*1000};
|
||||
|
||||
rv = pthread_create(ptidp, &pattr, f, arg);
|
||||
if (rv != EAGAIN)
|
||||
break;
|
||||
nanosleep(&ts, NULL);
|
||||
}
|
||||
|
||||
#if defined(HAVE_PTHREAD_SETNAME3)
|
||||
if (rv == 0 && thrname) {
|
||||
pthread_setname_np(*ptidp, thrname, NULL);
|
||||
}
|
||||
#elif defined(HAVE_PTHREAD_SETNAME2)
|
||||
if (rv == 0 && thrname) {
|
||||
pthread_setname_np(*ptidp, thrname);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (joinable) {
|
||||
assert(ptcookie);
|
||||
*ptcookie = ptidp;
|
||||
}
|
||||
|
||||
pthread_attr_destroy(&pattr);
|
||||
|
||||
ET(rv);
|
||||
}
|
||||
|
||||
__dead void
|
||||
rumpuser_thread_exit(void)
|
||||
{
|
||||
|
||||
/*
|
||||
* FIXXXME: with glibc on ARM pthread_exit() aborts because
|
||||
* it fails to unwind the stack. In the typical case, only
|
||||
* the mountroothook thread will exit and even that's
|
||||
* conditional on vfs being present.
|
||||
*/
|
||||
#if (defined(__ARMEL__) || defined(__ARMEB__)) && defined(__GLIBC__)
|
||||
for (;;)
|
||||
pause();
|
||||
#endif
|
||||
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
||||
int
|
||||
rumpuser_thread_join(void *ptcookie)
|
||||
{
|
||||
pthread_t *pt = ptcookie;
|
||||
int rv;
|
||||
|
||||
KLOCK_WRAP((rv = pthread_join(*pt, NULL)));
|
||||
if (rv == 0)
|
||||
free(pt);
|
||||
|
||||
ET(rv);
|
||||
}
|
||||
|
||||
struct rumpuser_mtx {
|
||||
pthread_mutex_t pthmtx;
|
||||
struct lwp *owner;
|
||||
int flags;
|
||||
};
|
||||
|
||||
void
|
||||
rumpuser_mutex_init(struct rumpuser_mtx **mtxp, int flags)
|
||||
{
|
||||
struct rumpuser_mtx *mtx;
|
||||
pthread_mutexattr_t att;
|
||||
size_t allocsz;
|
||||
|
||||
allocsz = (sizeof(*mtx)+RUMPUSER_LOCKALIGN) & ~(RUMPUSER_LOCKALIGN-1);
|
||||
NOFAIL(mtx = aligned_alloc(RUMPUSER_LOCKALIGN, allocsz));
|
||||
|
||||
pthread_mutexattr_init(&att);
|
||||
pthread_mutexattr_settype(&att, PTHREAD_MUTEX_ERRORCHECK);
|
||||
NOFAIL_ERRNO(pthread_mutex_init(&mtx->pthmtx, &att));
|
||||
pthread_mutexattr_destroy(&att);
|
||||
|
||||
mtx->owner = NULL;
|
||||
assert(flags != 0);
|
||||
mtx->flags = flags;
|
||||
|
||||
*mtxp = mtx;
|
||||
}
|
||||
|
||||
static void
|
||||
mtxenter(struct rumpuser_mtx *mtx)
|
||||
{
|
||||
|
||||
if (!(mtx->flags & RUMPUSER_MTX_KMUTEX))
|
||||
return;
|
||||
|
||||
assert(mtx->owner == NULL);
|
||||
mtx->owner = rumpuser_curlwp();
|
||||
}
|
||||
|
||||
static void
|
||||
mtxexit(struct rumpuser_mtx *mtx)
|
||||
{
|
||||
|
||||
if (!(mtx->flags & RUMPUSER_MTX_KMUTEX))
|
||||
return;
|
||||
|
||||
assert(mtx->owner != NULL);
|
||||
mtx->owner = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
rumpuser_mutex_enter(struct rumpuser_mtx *mtx)
|
||||
{
|
||||
|
||||
if (mtx->flags & RUMPUSER_MTX_SPIN) {
|
||||
rumpuser_mutex_enter_nowrap(mtx);
|
||||
return;
|
||||
}
|
||||
|
||||
assert(mtx->flags & RUMPUSER_MTX_KMUTEX);
|
||||
if (pthread_mutex_trylock(&mtx->pthmtx) != 0)
|
||||
KLOCK_WRAP(NOFAIL_ERRNO(pthread_mutex_lock(&mtx->pthmtx)));
|
||||
mtxenter(mtx);
|
||||
}
|
||||
|
||||
void
|
||||
rumpuser_mutex_enter_nowrap(struct rumpuser_mtx *mtx)
|
||||
{
|
||||
|
||||
assert(mtx->flags & RUMPUSER_MTX_SPIN);
|
||||
NOFAIL_ERRNO(pthread_mutex_lock(&mtx->pthmtx));
|
||||
mtxenter(mtx);
|
||||
}
|
||||
|
||||
int
|
||||
rumpuser_mutex_tryenter(struct rumpuser_mtx *mtx)
|
||||
{
|
||||
int rv;
|
||||
|
||||
rv = pthread_mutex_trylock(&mtx->pthmtx);
|
||||
if (rv == 0) {
|
||||
mtxenter(mtx);
|
||||
}
|
||||
|
||||
ET(rv);
|
||||
}
|
||||
|
||||
void
|
||||
rumpuser_mutex_exit(struct rumpuser_mtx *mtx)
|
||||
{
|
||||
|
||||
mtxexit(mtx);
|
||||
NOFAIL_ERRNO(pthread_mutex_unlock(&mtx->pthmtx));
|
||||
}
|
||||
|
||||
void
|
||||
rumpuser_mutex_destroy(struct rumpuser_mtx *mtx)
|
||||
{
|
||||
|
||||
NOFAIL_ERRNO(pthread_mutex_destroy(&mtx->pthmtx));
|
||||
free(mtx);
|
||||
}
|
||||
|
||||
void
|
||||
rumpuser_mutex_owner(struct rumpuser_mtx *mtx, struct lwp **lp)
|
||||
{
|
||||
|
||||
if (__predict_false(!(mtx->flags & RUMPUSER_MTX_KMUTEX))) {
|
||||
printf("panic: rumpuser_mutex_held unsupported on non-kmtx\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
*lp = mtx->owner;
|
||||
}
|
||||
|
||||
/*
|
||||
* rwlocks. these are mostly simple, except that NetBSD wants to
|
||||
* support something called downgrade, which means we need to swap
|
||||
* our exclusive lock for a shared lock. to accommodate this,
|
||||
* we need to check *after* acquiring a lock in case someone was
|
||||
* downgrading it. if so, we couldn't actually have it and maybe
|
||||
* need to retry later.
|
||||
*/
|
||||
|
||||
struct rumpuser_rw {
|
||||
pthread_rwlock_t pthrw;
|
||||
#if !defined(__APPLE__) && !defined(__ANDROID__)
|
||||
char pad[64 - sizeof(pthread_rwlock_t)];
|
||||
pthread_spinlock_t spin;
|
||||
#endif
|
||||
unsigned int readers;
|
||||
struct lwp *writer;
|
||||
int downgrade; /* someone is downgrading (hopefully lock holder ;) */
|
||||
};
|
||||
|
||||
static int
|
||||
rw_amwriter(struct rumpuser_rw *rw)
|
||||
{
|
||||
|
||||
return rw->writer == rumpuser_curlwp() && rw->readers == (unsigned)-1;
|
||||
}
|
||||
|
||||
static int
|
||||
rw_nreaders(struct rumpuser_rw *rw)
|
||||
{
|
||||
unsigned nreaders = rw->readers;
|
||||
|
||||
return nreaders != (unsigned)-1 ? nreaders : 0;
|
||||
}
|
||||
|
||||
static int
|
||||
rw_setwriter(struct rumpuser_rw *rw, int retry)
|
||||
{
|
||||
|
||||
/*
|
||||
* Don't need the spinlock here, we already have an
|
||||
* exclusive lock and "downgrade" is stable until complete.
|
||||
*/
|
||||
if (rw->downgrade) {
|
||||
pthread_rwlock_unlock(&rw->pthrw);
|
||||
if (retry) {
|
||||
struct timespec ts;
|
||||
|
||||
/* portable yield, essentially */
|
||||
ts.tv_sec = 0;
|
||||
ts.tv_nsec = 1;
|
||||
KLOCK_WRAP(nanosleep(&ts, NULL));
|
||||
}
|
||||
return EBUSY;
|
||||
}
|
||||
assert(rw->readers == 0);
|
||||
rw->writer = rumpuser_curlwp();
|
||||
rw->readers = (unsigned)-1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
rw_clearwriter(struct rumpuser_rw *rw)
|
||||
{
|
||||
|
||||
assert(rw_amwriter(rw));
|
||||
rw->readers = 0;
|
||||
rw->writer = NULL;
|
||||
}
|
||||
|
||||
static inline void
|
||||
rw_readup(struct rumpuser_rw *rw)
|
||||
{
|
||||
|
||||
#if defined(__NetBSD__) || defined(__APPLE__) || defined(__ANDROID__)
|
||||
atomic_inc_uint(&rw->readers);
|
||||
#else
|
||||
pthread_spin_lock(&rw->spin);
|
||||
++rw->readers;
|
||||
pthread_spin_unlock(&rw->spin);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void
|
||||
rw_readdown(struct rumpuser_rw *rw)
|
||||
{
|
||||
|
||||
#if defined(__NetBSD__) || defined(__APPLE__) || defined(__ANDROID__)
|
||||
atomic_dec_uint(&rw->readers);
|
||||
#else
|
||||
pthread_spin_lock(&rw->spin);
|
||||
assert(rw->readers > 0);
|
||||
--rw->readers;
|
||||
pthread_spin_unlock(&rw->spin);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
rumpuser_rw_init(struct rumpuser_rw **rwp)
|
||||
{
|
||||
struct rumpuser_rw *rw;
|
||||
size_t allocsz;
|
||||
|
||||
allocsz = (sizeof(*rw)+RUMPUSER_LOCKALIGN) & ~(RUMPUSER_LOCKALIGN-1);
|
||||
|
||||
NOFAIL(rw = aligned_alloc(RUMPUSER_LOCKALIGN, allocsz));
|
||||
NOFAIL_ERRNO(pthread_rwlock_init(&rw->pthrw, NULL));
|
||||
#if !defined(__APPLE__) && !defined(__ANDROID__)
|
||||
NOFAIL_ERRNO(pthread_spin_init(&rw->spin, PTHREAD_PROCESS_PRIVATE));
|
||||
#endif
|
||||
rw->readers = 0;
|
||||
rw->writer = NULL;
|
||||
rw->downgrade = 0;
|
||||
|
||||
*rwp = rw;
|
||||
}
|
||||
|
||||
void
|
||||
rumpuser_rw_enter(int enum_rumprwlock, struct rumpuser_rw *rw)
|
||||
{
|
||||
enum rumprwlock lk = enum_rumprwlock;
|
||||
|
||||
switch (lk) {
|
||||
case RUMPUSER_RW_WRITER:
|
||||
do {
|
||||
if (pthread_rwlock_trywrlock(&rw->pthrw) != 0)
|
||||
KLOCK_WRAP(NOFAIL_ERRNO(
|
||||
pthread_rwlock_wrlock(&rw->pthrw)));
|
||||
} while (rw_setwriter(rw, 1) != 0);
|
||||
break;
|
||||
case RUMPUSER_RW_READER:
|
||||
if (pthread_rwlock_tryrdlock(&rw->pthrw) != 0)
|
||||
KLOCK_WRAP(NOFAIL_ERRNO(
|
||||
pthread_rwlock_rdlock(&rw->pthrw)));
|
||||
rw_readup(rw);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
rumpuser_rw_tryenter(int enum_rumprwlock, struct rumpuser_rw *rw)
|
||||
{
|
||||
enum rumprwlock lk = enum_rumprwlock;
|
||||
int rv;
|
||||
|
||||
switch (lk) {
|
||||
case RUMPUSER_RW_WRITER:
|
||||
rv = pthread_rwlock_trywrlock(&rw->pthrw);
|
||||
if (rv == 0)
|
||||
rv = rw_setwriter(rw, 0);
|
||||
break;
|
||||
case RUMPUSER_RW_READER:
|
||||
rv = pthread_rwlock_tryrdlock(&rw->pthrw);
|
||||
if (rv == 0)
|
||||
rw_readup(rw);
|
||||
break;
|
||||
default:
|
||||
rv = EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
ET(rv);
|
||||
}
|
||||
|
||||
int
|
||||
rumpuser_rw_tryupgrade(struct rumpuser_rw *rw)
|
||||
{
|
||||
|
||||
/*
|
||||
* Not supported by pthreads. Since the caller needs to
|
||||
* back off anyway to avoid deadlock, always failing
|
||||
* is correct.
|
||||
*/
|
||||
ET(EBUSY);
|
||||
}
|
||||
|
||||
/*
|
||||
* convert from exclusive to shared lock without allowing anyone to
|
||||
* obtain an exclusive lock in between. actually, might allow
|
||||
* someone to obtain the lock, we just don't allow that thread to
|
||||
* return from the hypercall with it.
|
||||
*/
|
||||
void
|
||||
rumpuser_rw_downgrade(struct rumpuser_rw *rw)
|
||||
{
|
||||
|
||||
assert(rw->downgrade == 0);
|
||||
rw->downgrade = 1;
|
||||
rumpuser_rw_exit(rw);
|
||||
/*
|
||||
* though the competition can't get out of the hypervisor, it
|
||||
* might have rescheduled itself after we released the lock.
|
||||
* so need a wrap here.
|
||||
*/
|
||||
KLOCK_WRAP(NOFAIL_ERRNO(pthread_rwlock_rdlock(&rw->pthrw)));
|
||||
rw->downgrade = 0;
|
||||
rw_readup(rw);
|
||||
}
|
||||
|
||||
void
|
||||
rumpuser_rw_exit(struct rumpuser_rw *rw)
|
||||
{
|
||||
|
||||
if (rw_nreaders(rw))
|
||||
rw_readdown(rw);
|
||||
else
|
||||
rw_clearwriter(rw);
|
||||
NOFAIL_ERRNO(pthread_rwlock_unlock(&rw->pthrw));
|
||||
}
|
||||
|
||||
void
|
||||
rumpuser_rw_destroy(struct rumpuser_rw *rw)
|
||||
{
|
||||
|
||||
NOFAIL_ERRNO(pthread_rwlock_destroy(&rw->pthrw));
|
||||
#if !defined(__APPLE__) && ! defined(__ANDROID__)
|
||||
NOFAIL_ERRNO(pthread_spin_destroy(&rw->spin));
|
||||
#endif
|
||||
free(rw);
|
||||
}
|
||||
|
||||
void
|
||||
rumpuser_rw_held(int enum_rumprwlock, struct rumpuser_rw *rw, int *rv)
|
||||
{
|
||||
enum rumprwlock lk = enum_rumprwlock;
|
||||
|
||||
switch (lk) {
|
||||
case RUMPUSER_RW_WRITER:
|
||||
*rv = rw_amwriter(rw);
|
||||
break;
|
||||
case RUMPUSER_RW_READER:
|
||||
*rv = rw_nreaders(rw);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* condvar
|
||||
*/
|
||||
|
||||
struct rumpuser_cv {
|
||||
pthread_cond_t pthcv;
|
||||
int nwaiters;
|
||||
};
|
||||
|
||||
void
|
||||
rumpuser_cv_init(struct rumpuser_cv **cv)
|
||||
{
|
||||
|
||||
NOFAIL(*cv = malloc(sizeof(struct rumpuser_cv)));
|
||||
NOFAIL_ERRNO(pthread_cond_init(&((*cv)->pthcv), NULL));
|
||||
(*cv)->nwaiters = 0;
|
||||
}
|
||||
|
||||
void
|
||||
rumpuser_cv_destroy(struct rumpuser_cv *cv)
|
||||
{
|
||||
|
||||
NOFAIL_ERRNO(pthread_cond_destroy(&cv->pthcv));
|
||||
free(cv);
|
||||
}
|
||||
|
||||
static void
|
||||
cv_unschedule(struct rumpuser_mtx *mtx, int *nlocks)
|
||||
{
|
||||
|
||||
rumpkern_unsched(nlocks, mtx);
|
||||
mtxexit(mtx);
|
||||
}
|
||||
|
||||
static void
|
||||
cv_reschedule(struct rumpuser_mtx *mtx, int nlocks)
|
||||
{
|
||||
|
||||
/*
|
||||
* If the cv interlock is a spin mutex, we must first release
|
||||
* the mutex that was reacquired by pthread_cond_wait(),
|
||||
* acquire the CPU context and only then relock the mutex.
|
||||
* This is to preserve resource allocation order so that
|
||||
* we don't deadlock. Non-spinning mutexes don't have this
|
||||
* problem since they don't use a hold-and-wait approach
|
||||
* to acquiring the mutex wrt the rump kernel CPU context.
|
||||
*
|
||||
* The more optimal solution would be to rework rumpkern_sched()
|
||||
* so that it's possible to tell the scheduler
|
||||
* "if you need to block, drop this lock first", but I'm not
|
||||
* going poking there without some numbers on how often this
|
||||
* path is taken for spin mutexes.
|
||||
*/
|
||||
if ((mtx->flags & (RUMPUSER_MTX_SPIN | RUMPUSER_MTX_KMUTEX)) ==
|
||||
(RUMPUSER_MTX_SPIN | RUMPUSER_MTX_KMUTEX)) {
|
||||
NOFAIL_ERRNO(pthread_mutex_unlock(&mtx->pthmtx));
|
||||
rumpkern_sched(nlocks, mtx);
|
||||
rumpuser_mutex_enter_nowrap(mtx);
|
||||
} else {
|
||||
mtxenter(mtx);
|
||||
rumpkern_sched(nlocks, mtx);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
rumpuser_cv_wait(struct rumpuser_cv *cv, struct rumpuser_mtx *mtx)
|
||||
{
|
||||
int nlocks;
|
||||
|
||||
cv->nwaiters++;
|
||||
cv_unschedule(mtx, &nlocks);
|
||||
NOFAIL_ERRNO(pthread_cond_wait(&cv->pthcv, &mtx->pthmtx));
|
||||
cv_reschedule(mtx, nlocks);
|
||||
cv->nwaiters--;
|
||||
}
|
||||
|
||||
void
|
||||
rumpuser_cv_wait_nowrap(struct rumpuser_cv *cv, struct rumpuser_mtx *mtx)
|
||||
{
|
||||
|
||||
cv->nwaiters++;
|
||||
mtxexit(mtx);
|
||||
NOFAIL_ERRNO(pthread_cond_wait(&cv->pthcv, &mtx->pthmtx));
|
||||
mtxenter(mtx);
|
||||
cv->nwaiters--;
|
||||
}
|
||||
|
||||
int
|
||||
rumpuser_cv_timedwait(struct rumpuser_cv *cv, struct rumpuser_mtx *mtx,
|
||||
int64_t sec, int64_t nsec)
|
||||
{
|
||||
struct timespec ts;
|
||||
int rv, nlocks;
|
||||
|
||||
/*
|
||||
* Get clock already here, just in case we will be put to sleep
|
||||
* after releasing the kernel context.
|
||||
*
|
||||
* The condition variables should use CLOCK_MONOTONIC, but since
|
||||
* that's not available everywhere, leave it for another day.
|
||||
*/
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
|
||||
cv->nwaiters++;
|
||||
cv_unschedule(mtx, &nlocks);
|
||||
|
||||
ts.tv_sec += sec;
|
||||
ts.tv_nsec += nsec;
|
||||
if (ts.tv_nsec >= 1000*1000*1000) {
|
||||
ts.tv_sec++;
|
||||
ts.tv_nsec -= 1000*1000*1000;
|
||||
}
|
||||
rv = pthread_cond_timedwait(&cv->pthcv, &mtx->pthmtx, &ts);
|
||||
|
||||
cv_reschedule(mtx, nlocks);
|
||||
cv->nwaiters--;
|
||||
|
||||
ET(rv);
|
||||
}
|
||||
|
||||
void
|
||||
rumpuser_cv_signal(struct rumpuser_cv *cv)
|
||||
{
|
||||
|
||||
NOFAIL_ERRNO(pthread_cond_signal(&cv->pthcv));
|
||||
}
|
||||
|
||||
void
|
||||
rumpuser_cv_broadcast(struct rumpuser_cv *cv)
|
||||
{
|
||||
|
||||
NOFAIL_ERRNO(pthread_cond_broadcast(&cv->pthcv));
|
||||
}
|
||||
|
||||
void
|
||||
rumpuser_cv_has_waiters(struct rumpuser_cv *cv, int *nwaiters)
|
||||
{
|
||||
|
||||
*nwaiters = cv->nwaiters;
|
||||
}
|
||||
|
||||
/*
|
||||
* curlwp
|
||||
*/
|
||||
|
||||
static pthread_key_t curlwpkey;
|
||||
|
||||
/*
|
||||
* the if0'd curlwp implementation is not used by this hypervisor,
|
||||
* but serves as test code to check that the intended usage works.
|
||||
*/
|
||||
#if 0
|
||||
struct rumpuser_lwp {
|
||||
struct lwp *l;
|
||||
LIST_ENTRY(rumpuser_lwp) l_entries;
|
||||
};
|
||||
static LIST_HEAD(, rumpuser_lwp) lwps = LIST_HEAD_INITIALIZER(lwps);
|
||||
static pthread_mutex_t lwplock = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
void
|
||||
rumpuser_curlwpop(enum rumplwpop op, struct lwp *l)
|
||||
{
|
||||
struct rumpuser_lwp *rl, *rliter;
|
||||
|
||||
switch (op) {
|
||||
case RUMPUSER_LWP_CREATE:
|
||||
rl = malloc(sizeof(*rl));
|
||||
rl->l = l;
|
||||
pthread_mutex_lock(&lwplock);
|
||||
LIST_FOREACH(rliter, &lwps, l_entries) {
|
||||
if (rliter->l == l) {
|
||||
fprintf(stderr, "LWP_CREATE: %p exists\n", l);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
LIST_INSERT_HEAD(&lwps, rl, l_entries);
|
||||
pthread_mutex_unlock(&lwplock);
|
||||
break;
|
||||
case RUMPUSER_LWP_DESTROY:
|
||||
pthread_mutex_lock(&lwplock);
|
||||
LIST_FOREACH(rl, &lwps, l_entries) {
|
||||
if (rl->l == l)
|
||||
break;
|
||||
}
|
||||
if (!rl) {
|
||||
fprintf(stderr, "LWP_DESTROY: %p does not exist\n", l);
|
||||
abort();
|
||||
}
|
||||
LIST_REMOVE(rl, l_entries);
|
||||
pthread_mutex_unlock(&lwplock);
|
||||
free(rl);
|
||||
break;
|
||||
case RUMPUSER_LWP_SET:
|
||||
assert(pthread_getspecific(curlwpkey) == NULL && l != NULL);
|
||||
|
||||
pthread_mutex_lock(&lwplock);
|
||||
LIST_FOREACH(rl, &lwps, l_entries) {
|
||||
if (rl->l == l)
|
||||
break;
|
||||
}
|
||||
if (!rl) {
|
||||
fprintf(stderr,
|
||||
"LWP_SET: %p does not exist\n", l);
|
||||
abort();
|
||||
}
|
||||
pthread_mutex_unlock(&lwplock);
|
||||
|
||||
pthread_setspecific(curlwpkey, rl);
|
||||
break;
|
||||
case RUMPUSER_LWP_CLEAR:
|
||||
assert(((struct rumpuser_lwp *)
|
||||
pthread_getspecific(curlwpkey))->l == l);
|
||||
pthread_setspecific(curlwpkey, NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct lwp *
|
||||
rumpuser_curlwp(void)
|
||||
{
|
||||
struct rumpuser_lwp *rl;
|
||||
|
||||
rl = pthread_getspecific(curlwpkey);
|
||||
return rl ? rl->l : NULL;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void
|
||||
rumpuser_curlwpop(int enum_rumplwpop, struct lwp *l)
|
||||
{
|
||||
enum rumplwpop op = enum_rumplwpop;
|
||||
|
||||
switch (op) {
|
||||
case RUMPUSER_LWP_CREATE:
|
||||
break;
|
||||
case RUMPUSER_LWP_DESTROY:
|
||||
break;
|
||||
case RUMPUSER_LWP_SET:
|
||||
assert(pthread_getspecific(curlwpkey) == NULL);
|
||||
pthread_setspecific(curlwpkey, l);
|
||||
break;
|
||||
case RUMPUSER_LWP_CLEAR:
|
||||
assert(pthread_getspecific(curlwpkey) == l);
|
||||
pthread_setspecific(curlwpkey, NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct lwp *
|
||||
rumpuser_curlwp(void)
|
||||
{
|
||||
|
||||
return pthread_getspecific(curlwpkey);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void
|
||||
rumpuser__thrinit(void)
|
||||
{
|
||||
pthread_key_create(&curlwpkey, NULL);
|
||||
}
|
||||
327
lib/librumpuser/rumpuser_pth_dummy.c
Normal file
327
lib/librumpuser/rumpuser_pth_dummy.c
Normal file
|
|
@ -0,0 +1,327 @@
|
|||
/* $NetBSD: rumpuser_pth_dummy.c,v 1.17 2014/06/17 06:43:21 alnsn Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2009 Antti Kantee. 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "rumpuser_port.h"
|
||||
|
||||
#if !defined(lint)
|
||||
__RCSID("$NetBSD: rumpuser_pth_dummy.c,v 1.17 2014/06/17 06:43:21 alnsn Exp $");
|
||||
#endif /* !lint */
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <rump/rumpuser.h>
|
||||
|
||||
#include "rumpuser_int.h"
|
||||
|
||||
static struct lwp *curlwp;
|
||||
|
||||
struct rumpuser_cv {};
|
||||
|
||||
struct rumpuser_mtx {
|
||||
int v;
|
||||
struct lwp *o;
|
||||
};
|
||||
|
||||
struct rumpuser_rw {
|
||||
int v;
|
||||
};
|
||||
|
||||
void
|
||||
rumpuser__thrinit(void)
|
||||
{
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
int
|
||||
rumpuser_thread_create(void *(*f)(void *), void *arg, const char *thrname,
|
||||
int joinable, int pri, int cpuidx, void **tptr)
|
||||
{
|
||||
|
||||
fprintf(stderr, "rumpuser: threads not available\n");
|
||||
abort();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
rumpuser_thread_exit(void)
|
||||
{
|
||||
|
||||
fprintf(stderr, "rumpuser: threads not available\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
int
|
||||
rumpuser_thread_join(void *p)
|
||||
{
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
rumpuser_mutex_init(struct rumpuser_mtx **mtx, int flgas)
|
||||
{
|
||||
|
||||
*mtx = calloc(1, sizeof(struct rumpuser_mtx));
|
||||
}
|
||||
|
||||
void
|
||||
rumpuser_mutex_enter(struct rumpuser_mtx *mtx)
|
||||
{
|
||||
|
||||
mtx->v++;
|
||||
mtx->o = curlwp;
|
||||
}
|
||||
|
||||
void
|
||||
rumpuser_mutex_enter_nowrap(struct rumpuser_mtx *mtx)
|
||||
{
|
||||
|
||||
rumpuser_mutex_enter(mtx);
|
||||
}
|
||||
|
||||
int
|
||||
rumpuser_mutex_tryenter(struct rumpuser_mtx *mtx)
|
||||
{
|
||||
|
||||
mtx->v++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
rumpuser_mutex_exit(struct rumpuser_mtx *mtx)
|
||||
{
|
||||
|
||||
assert(mtx->v > 0);
|
||||
if (--mtx->v == 0)
|
||||
mtx->o = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
rumpuser_mutex_destroy(struct rumpuser_mtx *mtx)
|
||||
{
|
||||
|
||||
free(mtx);
|
||||
}
|
||||
|
||||
void
|
||||
rumpuser_mutex_owner(struct rumpuser_mtx *mtx, struct lwp **lp)
|
||||
{
|
||||
|
||||
*lp = mtx->o;
|
||||
}
|
||||
|
||||
void
|
||||
rumpuser_rw_init(struct rumpuser_rw **rw)
|
||||
{
|
||||
|
||||
*rw = calloc(1, sizeof(struct rumpuser_rw));
|
||||
}
|
||||
|
||||
void
|
||||
rumpuser_rw_enter(int enum_rumprwlock, struct rumpuser_rw *rw)
|
||||
{
|
||||
enum rumprwlock lk = enum_rumprwlock;
|
||||
|
||||
switch (lk) {
|
||||
case RUMPUSER_RW_WRITER:
|
||||
rw->v++;
|
||||
assert(rw->v == 1);
|
||||
break;
|
||||
case RUMPUSER_RW_READER:
|
||||
assert(rw->v <= 0);
|
||||
rw->v--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
rumpuser_rw_tryenter(int enum_rumprwlock, struct rumpuser_rw *rw)
|
||||
{
|
||||
|
||||
rumpuser_rw_enter(enum_rumprwlock, rw);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
rumpuser_rw_exit(struct rumpuser_rw *rw)
|
||||
{
|
||||
|
||||
if (rw->v > 0) {
|
||||
assert(rw->v == 1);
|
||||
rw->v--;
|
||||
} else {
|
||||
rw->v++;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
rumpuser_rw_destroy(struct rumpuser_rw *rw)
|
||||
{
|
||||
|
||||
free(rw);
|
||||
}
|
||||
|
||||
void
|
||||
rumpuser_rw_held(int enum_rumprwlock, struct rumpuser_rw *rw, int *rvp)
|
||||
{
|
||||
enum rumprwlock lk = enum_rumprwlock;
|
||||
|
||||
switch (lk) {
|
||||
case RUMPUSER_RW_WRITER:
|
||||
*rvp = rw->v > 0;
|
||||
break;
|
||||
case RUMPUSER_RW_READER:
|
||||
*rvp = rw->v < 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
rumpuser_rw_downgrade(struct rumpuser_rw *rw)
|
||||
{
|
||||
|
||||
assert(rw->v == 1);
|
||||
rw->v = -1;
|
||||
}
|
||||
|
||||
int
|
||||
rumpuser_rw_tryupgrade(struct rumpuser_rw *rw)
|
||||
{
|
||||
|
||||
if (rw->v == -1) {
|
||||
rw->v = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return EBUSY;
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
void
|
||||
rumpuser_cv_init(struct rumpuser_cv **cv)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
void
|
||||
rumpuser_cv_destroy(struct rumpuser_cv *cv)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
void
|
||||
rumpuser_cv_wait(struct rumpuser_cv *cv, struct rumpuser_mtx *mtx)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
void
|
||||
rumpuser_cv_wait_nowrap(struct rumpuser_cv *cv, struct rumpuser_mtx *mtx)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
int
|
||||
rumpuser_cv_timedwait(struct rumpuser_cv *cv, struct rumpuser_mtx *mtx,
|
||||
int64_t sec, int64_t nsec)
|
||||
{
|
||||
struct timespec ts;
|
||||
|
||||
/*LINTED*/
|
||||
ts.tv_sec = sec;
|
||||
/*LINTED*/
|
||||
ts.tv_nsec = nsec;
|
||||
|
||||
nanosleep(&ts, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
void
|
||||
rumpuser_cv_signal(struct rumpuser_cv *cv)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
void
|
||||
rumpuser_cv_broadcast(struct rumpuser_cv *cv)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
void
|
||||
rumpuser_cv_has_waiters(struct rumpuser_cv *cv, int *rvp)
|
||||
{
|
||||
|
||||
*rvp = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* curlwp
|
||||
*/
|
||||
|
||||
void
|
||||
rumpuser_curlwpop(int enum_rumplwpop, struct lwp *l)
|
||||
{
|
||||
enum rumplwpop op = enum_rumplwpop;
|
||||
|
||||
switch (op) {
|
||||
case RUMPUSER_LWP_CREATE:
|
||||
case RUMPUSER_LWP_DESTROY:
|
||||
break;
|
||||
case RUMPUSER_LWP_SET:
|
||||
curlwp = l;
|
||||
break;
|
||||
case RUMPUSER_LWP_CLEAR:
|
||||
assert(curlwp == l);
|
||||
curlwp = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct lwp *
|
||||
rumpuser_curlwp(void)
|
||||
{
|
||||
|
||||
return curlwp;
|
||||
}
|
||||
93
lib/librumpuser/rumpuser_random.c
Normal file
93
lib/librumpuser/rumpuser_random.c
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
/* $NetBSD: rumpuser_random.c,v 1.4 2014/11/04 19:05:17 pooka Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2014 Justin Cormack. 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 "rumpuser_port.h"
|
||||
|
||||
#if !defined(lint)
|
||||
__RCSID("$NetBSD: rumpuser_random.c,v 1.4 2014/11/04 19:05:17 pooka Exp $");
|
||||
#endif /* !lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <rump/rumpuser.h>
|
||||
|
||||
#include "rumpuser_int.h"
|
||||
|
||||
static const size_t random_maxread = 32;
|
||||
|
||||
#ifdef HAVE_ARC4RANDOM_BUF
|
||||
int
|
||||
rumpuser__random_init(void)
|
||||
{
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static const char *random_device = "/dev/urandom";
|
||||
static int random_fd = -1;
|
||||
|
||||
int
|
||||
rumpuser__random_init(void)
|
||||
{
|
||||
|
||||
random_fd = open(random_device, O_RDONLY);
|
||||
if (random_fd < 0) {
|
||||
fprintf(stderr, "random init open failed\n");
|
||||
return errno;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
rumpuser_getrandom(void *buf, size_t buflen, int flags, size_t *retp)
|
||||
{
|
||||
#ifndef HAVE_ARC4RANDOM_BUF
|
||||
ssize_t rv;
|
||||
|
||||
rv = read(random_fd, buf, buflen > random_maxread ? random_maxread : buflen);
|
||||
if (rv < 0) {
|
||||
ET(errno);
|
||||
}
|
||||
*retp = rv;
|
||||
#else
|
||||
buflen = buflen > random_maxread ? random_maxread : buflen;
|
||||
arc4random_buf(buf, buflen);
|
||||
*retp = buflen;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
126
lib/librumpuser/rumpuser_sigtrans.c
Normal file
126
lib/librumpuser/rumpuser_sigtrans.c
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
/* $NetBSD: rumpuser_sigtrans.c,v 1.1 2014/02/20 00:42:27 pooka Exp $ */
|
||||
|
||||
/*
|
||||
* pseudo-automatically generated. PLEASE DO EDIT (e.g. in case there
|
||||
* are errnos which are defined to be the same value)
|
||||
*
|
||||
* The body of the switch statement was generated using:
|
||||
*
|
||||
* awk '/^#define/ && $2 ~ "^SIG[A-Z]" \
|
||||
* {printf "#ifdef %s\n\tcase %d\t: return %s;\n#endif\n", $2, $3, $2}' \
|
||||
* signal.h
|
||||
*/
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
/*
|
||||
* Translate rump kernel signal number to host signal number
|
||||
*/
|
||||
int rumpuser__sig_rump2host(int); /* a naughty decouple */
|
||||
int
|
||||
rumpuser__sig_rump2host(int rumpsig)
|
||||
{
|
||||
|
||||
switch(rumpsig) {
|
||||
case 0 : return 0;
|
||||
#ifdef SIGHUP
|
||||
case 1 : return SIGHUP;
|
||||
#endif
|
||||
#ifdef SIGINT
|
||||
case 2 : return SIGINT;
|
||||
#endif
|
||||
#ifdef SIGQUIT
|
||||
case 3 : return SIGQUIT;
|
||||
#endif
|
||||
#ifdef SIGILL
|
||||
case 4 : return SIGILL;
|
||||
#endif
|
||||
#ifdef SIGTRAP
|
||||
case 5 : return SIGTRAP;
|
||||
#endif
|
||||
#ifdef SIGABRT
|
||||
case 6 : return SIGABRT;
|
||||
#endif
|
||||
#ifdef SIGEMT
|
||||
case 7 : return SIGEMT;
|
||||
#endif
|
||||
#ifdef SIGFPE
|
||||
case 8 : return SIGFPE;
|
||||
#endif
|
||||
#ifdef SIGKILL
|
||||
case 9 : return SIGKILL;
|
||||
#endif
|
||||
#ifdef SIGBUS
|
||||
case 10 : return SIGBUS;
|
||||
#endif
|
||||
#ifdef SIGSEGV
|
||||
case 11 : return SIGSEGV;
|
||||
#endif
|
||||
#ifdef SIGSYS
|
||||
case 12 : return SIGSYS;
|
||||
#endif
|
||||
#ifdef SIGPIPE
|
||||
case 13 : return SIGPIPE;
|
||||
#endif
|
||||
#ifdef SIGALRM
|
||||
case 14 : return SIGALRM;
|
||||
#endif
|
||||
#ifdef SIGTERM
|
||||
case 15 : return SIGTERM;
|
||||
#endif
|
||||
#ifdef SIGURG
|
||||
case 16 : return SIGURG;
|
||||
#endif
|
||||
#ifdef SIGSTOP
|
||||
case 17 : return SIGSTOP;
|
||||
#endif
|
||||
#ifdef SIGTSTP
|
||||
case 18 : return SIGTSTP;
|
||||
#endif
|
||||
#ifdef SIGCONT
|
||||
case 19 : return SIGCONT;
|
||||
#endif
|
||||
#ifdef SIGCHLD
|
||||
case 20 : return SIGCHLD;
|
||||
#elif defined(SIGCLD)
|
||||
case 20 : return SIGCLD;
|
||||
#endif
|
||||
#ifdef SIGTTIN
|
||||
case 21 : return SIGTTIN;
|
||||
#endif
|
||||
#ifdef SIGTTOU
|
||||
case 22 : return SIGTTOU;
|
||||
#endif
|
||||
#ifdef SIGIO
|
||||
case 23 : return SIGIO;
|
||||
#endif
|
||||
#ifdef SIGXCPU
|
||||
case 24 : return SIGXCPU;
|
||||
#endif
|
||||
#ifdef SIGXFSZ
|
||||
case 25 : return SIGXFSZ;
|
||||
#endif
|
||||
#ifdef SIGVTALRM
|
||||
case 26 : return SIGVTALRM;
|
||||
#endif
|
||||
#ifdef SIGPROF
|
||||
case 27 : return SIGPROF;
|
||||
#endif
|
||||
#ifdef SIGWINCH
|
||||
case 28 : return SIGWINCH;
|
||||
#endif
|
||||
#ifdef SIGINFO
|
||||
case 29 : return SIGINFO;
|
||||
#endif
|
||||
#ifdef SIGUSR1
|
||||
case 30 : return SIGUSR1;
|
||||
#endif
|
||||
#ifdef SIGUSR2
|
||||
case 31 : return SIGUSR2;
|
||||
#endif
|
||||
#ifdef SIGPWR
|
||||
case 32 : return SIGPWR;
|
||||
#endif
|
||||
default: return -1;
|
||||
}
|
||||
}
|
||||
1410
lib/librumpuser/rumpuser_sp.c
Normal file
1410
lib/librumpuser/rumpuser_sp.c
Normal file
File diff suppressed because it is too large
Load Diff
6
lib/librumpuser/shlib_version
Normal file
6
lib/librumpuser/shlib_version
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
# $NetBSD: shlib_version,v 1.2 2013/03/01 18:15:36 pooka Exp $
|
||||
#
|
||||
|
||||
# see comment in rumpuser_component.c
|
||||
major=0
|
||||
minor=1
|
||||
781
lib/librumpuser/sp_common.c
Normal file
781
lib/librumpuser/sp_common.c
Normal file
|
|
@ -0,0 +1,781 @@
|
|||
/* $NetBSD: sp_common.c,v 1.38 2014/01/08 01:45:29 pooka Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2010, 2011 Antti Kantee. 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Common client/server sysproxy routines. #included.
|
||||
*/
|
||||
|
||||
#include "rumpuser_port.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
#include <poll.h>
|
||||
#include <pthread.h>
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/*
|
||||
* XXX: NetBSD's __unused collides with Linux headers, so we cannot
|
||||
* define it before we've included everything.
|
||||
*/
|
||||
#if !defined(__unused) && defined(__GNUC__)
|
||||
#define __unused __attribute__((__unused__))
|
||||
#endif
|
||||
|
||||
//#define DEBUG
|
||||
#ifdef DEBUG
|
||||
#define DPRINTF(x) mydprintf x
|
||||
static void
|
||||
mydprintf(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
#else
|
||||
#define DPRINTF(x)
|
||||
#endif
|
||||
|
||||
#ifndef HOSTOPS
|
||||
#define host_poll poll
|
||||
#define host_read read
|
||||
#define host_sendmsg sendmsg
|
||||
#define host_setsockopt setsockopt
|
||||
#endif
|
||||
|
||||
#define IOVPUT(_io_, _b_) _io_.iov_base = \
|
||||
(void *)&_b_; _io_.iov_len = sizeof(_b_);
|
||||
#define IOVPUT_WITHSIZE(_io_, _b_, _l_) _io_.iov_base = \
|
||||
(void *)(_b_); _io_.iov_len = _l_;
|
||||
#define SENDIOV(_spc_, _iov_) dosend(_spc_, _iov_, __arraycount(_iov_))
|
||||
|
||||
/*
|
||||
* Bah, I hate writing on-off-wire conversions in C
|
||||
*/
|
||||
|
||||
enum { RUMPSP_REQ, RUMPSP_RESP, RUMPSP_ERROR };
|
||||
enum { RUMPSP_HANDSHAKE,
|
||||
RUMPSP_SYSCALL,
|
||||
RUMPSP_COPYIN, RUMPSP_COPYINSTR,
|
||||
RUMPSP_COPYOUT, RUMPSP_COPYOUTSTR,
|
||||
RUMPSP_ANONMMAP,
|
||||
RUMPSP_PREFORK,
|
||||
RUMPSP_RAISE };
|
||||
|
||||
enum { HANDSHAKE_GUEST, HANDSHAKE_AUTH, HANDSHAKE_FORK, HANDSHAKE_EXEC };
|
||||
|
||||
/*
|
||||
* error types used for RUMPSP_ERROR
|
||||
*/
|
||||
enum rumpsp_err { RUMPSP_ERR_NONE = 0, RUMPSP_ERR_TRYAGAIN, RUMPSP_ERR_AUTH,
|
||||
RUMPSP_ERR_INVALID_PREFORK, RUMPSP_ERR_RFORK_FAILED,
|
||||
RUMPSP_ERR_INEXEC, RUMPSP_ERR_NOMEM, RUMPSP_ERR_MALFORMED_REQUEST };
|
||||
|
||||
/*
|
||||
* The mapping of the above types to errno. They are almost never exposed
|
||||
* to the client after handshake (except for a server resource shortage
|
||||
* and the client trying to be funny). This is a function instead of
|
||||
* an array to catch missing values. Theoretically, the compiled code
|
||||
* should be the same.
|
||||
*/
|
||||
static int
|
||||
errmap(enum rumpsp_err error)
|
||||
{
|
||||
|
||||
switch (error) {
|
||||
/* XXX: no EAUTH on Linux */
|
||||
case RUMPSP_ERR_NONE: return 0;
|
||||
case RUMPSP_ERR_AUTH: return EPERM;
|
||||
case RUMPSP_ERR_TRYAGAIN: return EAGAIN;
|
||||
case RUMPSP_ERR_INVALID_PREFORK: return ESRCH;
|
||||
case RUMPSP_ERR_RFORK_FAILED: return EIO; /* got a light? */
|
||||
case RUMPSP_ERR_INEXEC: return EBUSY;
|
||||
case RUMPSP_ERR_NOMEM: return ENOMEM;
|
||||
case RUMPSP_ERR_MALFORMED_REQUEST: return EINVAL;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
#define AUTHLEN 4 /* 128bit fork auth */
|
||||
|
||||
struct rsp_hdr {
|
||||
uint64_t rsp_len;
|
||||
uint64_t rsp_reqno;
|
||||
uint16_t rsp_class;
|
||||
uint16_t rsp_type;
|
||||
/*
|
||||
* We want this structure 64bit-aligned for typecast fun,
|
||||
* so might as well use the following for something.
|
||||
*/
|
||||
union {
|
||||
uint32_t sysnum;
|
||||
uint32_t error;
|
||||
uint32_t handshake;
|
||||
uint32_t signo;
|
||||
} u;
|
||||
};
|
||||
#define HDRSZ sizeof(struct rsp_hdr)
|
||||
#define rsp_sysnum u.sysnum
|
||||
#define rsp_error u.error
|
||||
#define rsp_handshake u.handshake
|
||||
#define rsp_signo u.signo
|
||||
|
||||
#define MAXBANNER 96
|
||||
|
||||
/*
|
||||
* Data follows the header. We have two types of structured data.
|
||||
*/
|
||||
|
||||
/* copyin/copyout */
|
||||
struct rsp_copydata {
|
||||
size_t rcp_len;
|
||||
void *rcp_addr;
|
||||
uint8_t rcp_data[0];
|
||||
};
|
||||
|
||||
/* syscall response */
|
||||
struct rsp_sysresp {
|
||||
int rsys_error;
|
||||
register_t rsys_retval[2];
|
||||
};
|
||||
|
||||
struct handshake_fork {
|
||||
uint32_t rf_auth[4];
|
||||
int rf_cancel;
|
||||
};
|
||||
|
||||
struct respwait {
|
||||
uint64_t rw_reqno;
|
||||
void *rw_data;
|
||||
size_t rw_dlen;
|
||||
int rw_done;
|
||||
int rw_error;
|
||||
|
||||
pthread_cond_t rw_cv;
|
||||
|
||||
TAILQ_ENTRY(respwait) rw_entries;
|
||||
};
|
||||
|
||||
struct prefork;
|
||||
struct spclient {
|
||||
int spc_fd;
|
||||
int spc_refcnt;
|
||||
int spc_state;
|
||||
|
||||
pthread_mutex_t spc_mtx;
|
||||
pthread_cond_t spc_cv;
|
||||
|
||||
struct lwp *spc_mainlwp;
|
||||
pid_t spc_pid;
|
||||
|
||||
TAILQ_HEAD(, respwait) spc_respwait;
|
||||
|
||||
/* rest of the fields are zeroed upon disconnect */
|
||||
#define SPC_ZEROFF offsetof(struct spclient, spc_pfd)
|
||||
struct pollfd *spc_pfd;
|
||||
|
||||
struct rsp_hdr spc_hdr;
|
||||
uint8_t *spc_buf;
|
||||
size_t spc_off;
|
||||
|
||||
uint64_t spc_nextreq;
|
||||
uint64_t spc_syscallreq;
|
||||
uint64_t spc_generation;
|
||||
int spc_ostatus, spc_istatus;
|
||||
int spc_reconnecting;
|
||||
int spc_inexec;
|
||||
|
||||
LIST_HEAD(, prefork) spc_pflist;
|
||||
};
|
||||
#define SPCSTATUS_FREE 0
|
||||
#define SPCSTATUS_BUSY 1
|
||||
#define SPCSTATUS_WANTED 2
|
||||
|
||||
#define SPCSTATE_NEW 0
|
||||
#define SPCSTATE_RUNNING 1
|
||||
#define SPCSTATE_DYING 2
|
||||
|
||||
typedef int (*addrparse_fn)(const char *, struct sockaddr **, int);
|
||||
typedef int (*connecthook_fn)(int);
|
||||
typedef void (*cleanup_fn)(struct sockaddr *);
|
||||
|
||||
static int readframe(struct spclient *);
|
||||
static void handlereq(struct spclient *);
|
||||
|
||||
static __inline void
|
||||
spcresetbuf(struct spclient *spc)
|
||||
{
|
||||
|
||||
spc->spc_buf = NULL;
|
||||
spc->spc_off = 0;
|
||||
}
|
||||
|
||||
static __inline void
|
||||
spcfreebuf(struct spclient *spc)
|
||||
{
|
||||
|
||||
free(spc->spc_buf);
|
||||
spcresetbuf(spc);
|
||||
}
|
||||
|
||||
static void
|
||||
sendlockl(struct spclient *spc)
|
||||
{
|
||||
|
||||
while (spc->spc_ostatus != SPCSTATUS_FREE) {
|
||||
spc->spc_ostatus = SPCSTATUS_WANTED;
|
||||
pthread_cond_wait(&spc->spc_cv, &spc->spc_mtx);
|
||||
}
|
||||
spc->spc_ostatus = SPCSTATUS_BUSY;
|
||||
}
|
||||
|
||||
static void __unused
|
||||
sendlock(struct spclient *spc)
|
||||
{
|
||||
|
||||
pthread_mutex_lock(&spc->spc_mtx);
|
||||
sendlockl(spc);
|
||||
pthread_mutex_unlock(&spc->spc_mtx);
|
||||
}
|
||||
|
||||
static void
|
||||
sendunlockl(struct spclient *spc)
|
||||
{
|
||||
|
||||
if (spc->spc_ostatus == SPCSTATUS_WANTED)
|
||||
pthread_cond_broadcast(&spc->spc_cv);
|
||||
spc->spc_ostatus = SPCSTATUS_FREE;
|
||||
}
|
||||
|
||||
static void
|
||||
sendunlock(struct spclient *spc)
|
||||
{
|
||||
|
||||
pthread_mutex_lock(&spc->spc_mtx);
|
||||
sendunlockl(spc);
|
||||
pthread_mutex_unlock(&spc->spc_mtx);
|
||||
}
|
||||
|
||||
static int
|
||||
dosend(struct spclient *spc, struct iovec *iov, size_t iovlen)
|
||||
{
|
||||
struct msghdr msg;
|
||||
struct pollfd pfd;
|
||||
ssize_t n = 0;
|
||||
int fd = spc->spc_fd;
|
||||
|
||||
pfd.fd = fd;
|
||||
pfd.events = POLLOUT;
|
||||
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
|
||||
for (;;) {
|
||||
/* not first round? poll */
|
||||
if (n) {
|
||||
if (host_poll(&pfd, 1, INFTIM) == -1) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
return errno;
|
||||
}
|
||||
}
|
||||
|
||||
msg.msg_iov = iov;
|
||||
msg.msg_iovlen = iovlen;
|
||||
n = host_sendmsg(fd, &msg, MSG_NOSIGNAL);
|
||||
if (n == -1) {
|
||||
if (errno == EPIPE)
|
||||
return ENOTCONN;
|
||||
if (errno != EAGAIN)
|
||||
return errno;
|
||||
continue;
|
||||
}
|
||||
if (n == 0) {
|
||||
return ENOTCONN;
|
||||
}
|
||||
|
||||
/* ok, need to adjust iovec for potential next round */
|
||||
while (n >= (ssize_t)iov[0].iov_len && iovlen) {
|
||||
n -= iov[0].iov_len;
|
||||
iov++;
|
||||
iovlen--;
|
||||
}
|
||||
|
||||
if (iovlen == 0) {
|
||||
_DIAGASSERT(n == 0);
|
||||
break;
|
||||
} else {
|
||||
iov[0].iov_base =
|
||||
(void *)((uint8_t *)iov[0].iov_base + n);
|
||||
iov[0].iov_len -= n;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
doputwait(struct spclient *spc, struct respwait *rw, struct rsp_hdr *rhdr)
|
||||
{
|
||||
|
||||
rw->rw_data = NULL;
|
||||
rw->rw_dlen = rw->rw_done = rw->rw_error = 0;
|
||||
pthread_cond_init(&rw->rw_cv, NULL);
|
||||
|
||||
pthread_mutex_lock(&spc->spc_mtx);
|
||||
rw->rw_reqno = rhdr->rsp_reqno = spc->spc_nextreq++;
|
||||
TAILQ_INSERT_TAIL(&spc->spc_respwait, rw, rw_entries);
|
||||
}
|
||||
|
||||
static void __unused
|
||||
putwait_locked(struct spclient *spc, struct respwait *rw, struct rsp_hdr *rhdr)
|
||||
{
|
||||
|
||||
doputwait(spc, rw, rhdr);
|
||||
pthread_mutex_unlock(&spc->spc_mtx);
|
||||
}
|
||||
|
||||
static void
|
||||
putwait(struct spclient *spc, struct respwait *rw, struct rsp_hdr *rhdr)
|
||||
{
|
||||
|
||||
doputwait(spc, rw, rhdr);
|
||||
sendlockl(spc);
|
||||
pthread_mutex_unlock(&spc->spc_mtx);
|
||||
}
|
||||
|
||||
static void
|
||||
dounputwait(struct spclient *spc, struct respwait *rw)
|
||||
{
|
||||
|
||||
TAILQ_REMOVE(&spc->spc_respwait, rw, rw_entries);
|
||||
pthread_mutex_unlock(&spc->spc_mtx);
|
||||
pthread_cond_destroy(&rw->rw_cv);
|
||||
|
||||
}
|
||||
|
||||
static void __unused
|
||||
unputwait_locked(struct spclient *spc, struct respwait *rw)
|
||||
{
|
||||
|
||||
pthread_mutex_lock(&spc->spc_mtx);
|
||||
dounputwait(spc, rw);
|
||||
}
|
||||
|
||||
static void
|
||||
unputwait(struct spclient *spc, struct respwait *rw)
|
||||
{
|
||||
|
||||
pthread_mutex_lock(&spc->spc_mtx);
|
||||
sendunlockl(spc);
|
||||
|
||||
dounputwait(spc, rw);
|
||||
}
|
||||
|
||||
static void
|
||||
kickwaiter(struct spclient *spc)
|
||||
{
|
||||
struct respwait *rw;
|
||||
int error = 0;
|
||||
|
||||
pthread_mutex_lock(&spc->spc_mtx);
|
||||
TAILQ_FOREACH(rw, &spc->spc_respwait, rw_entries) {
|
||||
if (rw->rw_reqno == spc->spc_hdr.rsp_reqno)
|
||||
break;
|
||||
}
|
||||
if (rw == NULL) {
|
||||
DPRINTF(("no waiter found, invalid reqno %" PRIu64 "?\n",
|
||||
spc->spc_hdr.rsp_reqno));
|
||||
pthread_mutex_unlock(&spc->spc_mtx);
|
||||
spcfreebuf(spc);
|
||||
return;
|
||||
}
|
||||
DPRINTF(("rump_sp: client %p woke up waiter at %p\n", spc, rw));
|
||||
rw->rw_data = spc->spc_buf;
|
||||
rw->rw_done = 1;
|
||||
rw->rw_dlen = (size_t)(spc->spc_off - HDRSZ);
|
||||
if (spc->spc_hdr.rsp_class == RUMPSP_ERROR) {
|
||||
error = rw->rw_error = errmap(spc->spc_hdr.rsp_error);
|
||||
}
|
||||
pthread_cond_signal(&rw->rw_cv);
|
||||
pthread_mutex_unlock(&spc->spc_mtx);
|
||||
|
||||
if (error)
|
||||
spcfreebuf(spc);
|
||||
else
|
||||
spcresetbuf(spc);
|
||||
}
|
||||
|
||||
static void
|
||||
kickall(struct spclient *spc)
|
||||
{
|
||||
struct respwait *rw;
|
||||
|
||||
/* DIAGASSERT(mutex_owned(spc_lock)) */
|
||||
TAILQ_FOREACH(rw, &spc->spc_respwait, rw_entries)
|
||||
pthread_cond_broadcast(&rw->rw_cv);
|
||||
}
|
||||
|
||||
static int
|
||||
readframe(struct spclient *spc)
|
||||
{
|
||||
int fd = spc->spc_fd;
|
||||
size_t left;
|
||||
size_t framelen;
|
||||
ssize_t n;
|
||||
|
||||
/* still reading header? */
|
||||
if (spc->spc_off < HDRSZ) {
|
||||
DPRINTF(("rump_sp: readframe getting header at offset %zu\n",
|
||||
spc->spc_off));
|
||||
|
||||
left = HDRSZ - spc->spc_off;
|
||||
/*LINTED: cast ok */
|
||||
n = host_read(fd, (uint8_t*)&spc->spc_hdr + spc->spc_off, left);
|
||||
if (n == 0) {
|
||||
return -1;
|
||||
}
|
||||
if (n == -1) {
|
||||
if (errno == EAGAIN)
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
spc->spc_off += n;
|
||||
if (spc->spc_off < HDRSZ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*LINTED*/
|
||||
framelen = spc->spc_hdr.rsp_len;
|
||||
|
||||
if (framelen < HDRSZ) {
|
||||
return -1;
|
||||
} else if (framelen == HDRSZ) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
spc->spc_buf = malloc(framelen - HDRSZ);
|
||||
if (spc->spc_buf == NULL) {
|
||||
return -1;
|
||||
}
|
||||
memset(spc->spc_buf, 0, framelen - HDRSZ);
|
||||
|
||||
/* "fallthrough" */
|
||||
} else {
|
||||
/*LINTED*/
|
||||
framelen = spc->spc_hdr.rsp_len;
|
||||
}
|
||||
|
||||
left = framelen - spc->spc_off;
|
||||
|
||||
DPRINTF(("rump_sp: readframe getting body at offset %zu, left %zu\n",
|
||||
spc->spc_off, left));
|
||||
|
||||
if (left == 0)
|
||||
return 1;
|
||||
n = host_read(fd, spc->spc_buf + (spc->spc_off - HDRSZ), left);
|
||||
if (n == 0) {
|
||||
return -1;
|
||||
}
|
||||
if (n == -1) {
|
||||
if (errno == EAGAIN)
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
spc->spc_off += n;
|
||||
left -= n;
|
||||
|
||||
/* got everything? */
|
||||
if (left == 0)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
tcp_parse(const char *addr, struct sockaddr **sa, int allow_wildcard)
|
||||
{
|
||||
struct sockaddr_in sin;
|
||||
char buf[64];
|
||||
const char *p;
|
||||
size_t l;
|
||||
int port;
|
||||
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
SIN_SETLEN(sin, sizeof(sin));
|
||||
sin.sin_family = AF_INET;
|
||||
|
||||
p = strchr(addr, ':');
|
||||
if (!p) {
|
||||
fprintf(stderr, "rump_sp_tcp: missing port specifier\n");
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
l = p - addr;
|
||||
if (l > sizeof(buf)-1) {
|
||||
fprintf(stderr, "rump_sp_tcp: address too long\n");
|
||||
return EINVAL;
|
||||
}
|
||||
strncpy(buf, addr, l);
|
||||
buf[l] = '\0';
|
||||
|
||||
/* special INADDR_ANY treatment */
|
||||
if (strcmp(buf, "*") == 0 || strcmp(buf, "0") == 0) {
|
||||
sin.sin_addr.s_addr = INADDR_ANY;
|
||||
} else {
|
||||
switch (inet_pton(AF_INET, buf, &sin.sin_addr)) {
|
||||
case 1:
|
||||
break;
|
||||
case 0:
|
||||
fprintf(stderr, "rump_sp_tcp: cannot parse %s\n", buf);
|
||||
return EINVAL;
|
||||
case -1:
|
||||
fprintf(stderr, "rump_sp_tcp: inet_pton failed\n");
|
||||
return errno;
|
||||
default:
|
||||
assert(/*CONSTCOND*/0);
|
||||
return EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!allow_wildcard && sin.sin_addr.s_addr == INADDR_ANY) {
|
||||
fprintf(stderr, "rump_sp_tcp: client needs !INADDR_ANY\n");
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
/* advance to port number & parse */
|
||||
p++;
|
||||
l = strspn(p, "0123456789");
|
||||
if (l == 0) {
|
||||
fprintf(stderr, "rump_sp_tcp: port now found: %s\n", p);
|
||||
return EINVAL;
|
||||
}
|
||||
strncpy(buf, p, l);
|
||||
buf[l] = '\0';
|
||||
|
||||
if (*(p+l) != '/' && *(p+l) != '\0') {
|
||||
fprintf(stderr, "rump_sp_tcp: junk at end of port: %s\n", addr);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
port = atoi(buf);
|
||||
if (port < 0 || port >= (1<<(8*sizeof(in_port_t)))) {
|
||||
fprintf(stderr, "rump_sp_tcp: port %d out of range\n", port);
|
||||
return ERANGE;
|
||||
}
|
||||
sin.sin_port = htons(port);
|
||||
|
||||
*sa = malloc(sizeof(sin));
|
||||
if (*sa == NULL)
|
||||
return errno;
|
||||
memcpy(*sa, &sin, sizeof(sin));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
tcp_connecthook(int s)
|
||||
{
|
||||
int x;
|
||||
|
||||
x = 1;
|
||||
host_setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &x, sizeof(x));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char parsedurl[256];
|
||||
|
||||
/*ARGSUSED*/
|
||||
static int
|
||||
unix_parse(const char *addr, struct sockaddr **sa, int allow_wildcard)
|
||||
{
|
||||
struct sockaddr_un s_un;
|
||||
size_t slen;
|
||||
int savepath = 0;
|
||||
|
||||
if (strlen(addr) >= sizeof(s_un.sun_path))
|
||||
return ENAMETOOLONG;
|
||||
|
||||
/*
|
||||
* The pathname can be all kinds of spaghetti elementals,
|
||||
* so meek and obidient we accept everything. However, use
|
||||
* full path for easy cleanup in case someone gives a relative
|
||||
* one and the server does a chdir() between now than the
|
||||
* cleanup.
|
||||
*/
|
||||
memset(&s_un, 0, sizeof(s_un));
|
||||
s_un.sun_family = AF_LOCAL;
|
||||
if (*addr != '/') {
|
||||
char mywd[PATH_MAX];
|
||||
|
||||
if (getcwd(mywd, sizeof(mywd)) == NULL) {
|
||||
fprintf(stderr, "warning: cannot determine cwd, "
|
||||
"omitting socket cleanup\n");
|
||||
} else {
|
||||
if (strlen(addr)+strlen(mywd)+1
|
||||
>= sizeof(s_un.sun_path))
|
||||
return ENAMETOOLONG;
|
||||
strcpy(s_un.sun_path, mywd);
|
||||
strcat(s_un.sun_path, "/");
|
||||
savepath = 1;
|
||||
}
|
||||
}
|
||||
strcat(s_un.sun_path, addr);
|
||||
#if defined(__linux__) || defined(__sun__) || defined(__CYGWIN__)
|
||||
slen = sizeof(s_un);
|
||||
#else
|
||||
s_un.sun_len = SUN_LEN(&s_un);
|
||||
slen = s_un.sun_len+1; /* get the 0 too */
|
||||
#endif
|
||||
|
||||
if (savepath && *parsedurl == '\0') {
|
||||
snprintf(parsedurl, sizeof(parsedurl),
|
||||
"unix://%s", s_un.sun_path);
|
||||
}
|
||||
|
||||
*sa = malloc(slen);
|
||||
if (*sa == NULL)
|
||||
return errno;
|
||||
memcpy(*sa, &s_un, slen);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
unix_cleanup(struct sockaddr *sa)
|
||||
{
|
||||
struct sockaddr_un *s_sun = (void *)sa;
|
||||
|
||||
/*
|
||||
* cleanup only absolute paths. see unix_parse() above
|
||||
*/
|
||||
if (*s_sun->sun_path == '/') {
|
||||
unlink(s_sun->sun_path);
|
||||
}
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
static int
|
||||
notsupp(void)
|
||||
{
|
||||
|
||||
fprintf(stderr, "rump_sp: support not yet implemented\n");
|
||||
return EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static int
|
||||
success(void)
|
||||
{
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct {
|
||||
const char *id;
|
||||
int domain;
|
||||
socklen_t slen;
|
||||
addrparse_fn ap;
|
||||
connecthook_fn connhook;
|
||||
cleanup_fn cleanup;
|
||||
} parsetab[] = {
|
||||
{ "tcp", PF_INET, sizeof(struct sockaddr_in),
|
||||
tcp_parse, tcp_connecthook, (cleanup_fn)success },
|
||||
{ "unix", PF_LOCAL, sizeof(struct sockaddr_un),
|
||||
unix_parse, (connecthook_fn)success, unix_cleanup },
|
||||
{ "tcp6", PF_INET6, sizeof(struct sockaddr_in6),
|
||||
(addrparse_fn)notsupp, (connecthook_fn)success,
|
||||
(cleanup_fn)success },
|
||||
};
|
||||
#define NPARSE (sizeof(parsetab)/sizeof(parsetab[0]))
|
||||
|
||||
static int
|
||||
parseurl(const char *url, struct sockaddr **sap, unsigned *idxp,
|
||||
int allow_wildcard)
|
||||
{
|
||||
char id[16];
|
||||
const char *p, *p2;
|
||||
size_t l;
|
||||
unsigned i;
|
||||
int error;
|
||||
|
||||
/*
|
||||
* Parse the url
|
||||
*/
|
||||
|
||||
p = url;
|
||||
p2 = strstr(p, "://");
|
||||
if (!p2) {
|
||||
fprintf(stderr, "rump_sp: invalid locator ``%s''\n", p);
|
||||
return EINVAL;
|
||||
}
|
||||
l = p2-p;
|
||||
if (l > sizeof(id)-1) {
|
||||
fprintf(stderr, "rump_sp: identifier too long in ``%s''\n", p);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
strncpy(id, p, l);
|
||||
id[l] = '\0';
|
||||
p2 += 3; /* beginning of address */
|
||||
|
||||
for (i = 0; i < NPARSE; i++) {
|
||||
if (strcmp(id, parsetab[i].id) == 0) {
|
||||
error = parsetab[i].ap(p2, sap, allow_wildcard);
|
||||
if (error)
|
||||
return error;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == NPARSE) {
|
||||
fprintf(stderr, "rump_sp: invalid identifier ``%s''\n", p);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
*idxp = i;
|
||||
return 0;
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user