diff options
135 files changed, 3991 insertions, 2392 deletions
@@ -101,5 +101,5 @@ endif cp -f mdheader.jar $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/$(OBJDIR_NAME); \ chmod 664 $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/$(OBJDIR_NAME)/mdheader.jar -depend: clean +depend: @echo "NSPR20 has no dependencies. Skipped." diff --git a/Makefile.in b/Makefile.in index 11ffcee9..8ff221b8 100644 --- a/Makefile.in +++ b/Makefile.in @@ -106,5 +106,5 @@ endif cp -f mdheader.jar $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/$(OBJDIR_NAME); \ chmod 664 $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/$(OBJDIR_NAME)/mdheader.jar -depend: clean +depend: @echo "NSPR20 has no dependencies. Skipped." diff --git a/config/Linux.mk b/config/Linux.mk index 21c85ebc..29832d08 100644 --- a/config/Linux.mk +++ b/config/Linux.mk @@ -47,6 +47,8 @@ IMPL_STRATEGY = _PTH DEFINES += -D_REENTRANT endif +USE_IPV6 = 1 + ifeq (86,$(findstring 86,$(OS_TEST))) CPU_ARCH := x86 else diff --git a/config/autoconf.mk.in b/config/autoconf.mk.in index 3c7e77a3..83b7a86f 100644 --- a/config/autoconf.mk.in +++ b/config/autoconf.mk.in @@ -26,6 +26,7 @@ CC = @CC@ CCC = @CXX@ AR = @AR@ AR_FLAGS = @AR_FLAGS@ +LD = @LD@ RANLIB = @RANLIB@ PERL = @PERL@ DLLTOOL = @DLLTOOL@ diff --git a/config/module.df b/config/module.df index 126476b5..04522daf 100644 --- a/config/module.df +++ b/config/module.df @@ -20,4 +20,4 @@ # A module is also called a component or a subsystem. MOD_NAME = nspr20 -MOD_VERSION = 3 +MOD_VERSION = 4 diff --git a/config/prdepend.h b/config/prdepend.h index 16423bc7..e95d6f92 100644 --- a/config/prdepend.h +++ b/config/prdepend.h @@ -23,3 +23,4 @@ */ #error "Do not include this header file." + diff --git a/config/rules.mk b/config/rules.mk index 15430076..b885c33e 100644 --- a/config/rules.mk +++ b/config/rules.mk @@ -62,14 +62,12 @@ endif ifdef USE_AUTOCONF ifdef INTERNAL_TOOLS -ifdef CROSS_COMPILE CC=$(HOST_CC) CCC=$(HOST_CXX) CFLAGS=$(HOST_CFLAGS) CXXFLAGS=$(HOST_CXXFLAGS) endif endif -endif # # This makefile contains rules for building the following kinds of @@ -410,6 +408,29 @@ $(OBJDIR)/%.$(OBJ_SUFFIX): %.s %: %.pl rm -f $@; cp $< $@; chmod +x $@ +# +# HACK ALERT +# +# The only purpose of this rule is to pass Mozilla's Tinderbox depend +# builds (http://tinderbox.mozilla.org/showbuilds.cgi). Mozilla's +# Tinderbox builds NSPR continuously as part of the Mozilla client. +# Because NSPR's make depend is not implemented, whenever we change +# an NSPR header file, the depend build does not recompile the NSPR +# files that depend on the header. +# +# This rule makes all the objects depend on a dummy header file. +# Touch this dummy header file to force the depend build to recompile +# everything. +# +# This rule should be removed when make depend is implemented. +# + +DUMMY_DEPEND_H = $(topsrcdir)/config/prdepend.h + +$(filter $(OBJDIR)/%.$(OBJ_SUFFIX),$(OBJS)): $(OBJDIR)/%.$(OBJ_SUFFIX): $(DUMMY_DEPEND_H) + +# END OF HACK + ################################################################################ # Special gmake rules. ################################################################################ @@ -693,7 +693,7 @@ cat >> confdefs.h <<\EOF EOF -NSPR_VERSION=3 +NSPR_VERSION=4 NSPR_MODNAME=nspr20 _HAVE_PTHREADS= USE_PTHREADS= @@ -1490,13 +1490,50 @@ done test -n "$AS" || AS=":" fi + if test -z "$LD"; then + for ac_prog in "${target_alias}-ld" "${target}-ld" +do +# Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1500: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_LD'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$LD"; then + ac_cv_prog_LD="$LD" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_LD="$ac_prog" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +LD="$ac_cv_prog_LD" +if test -n "$LD"; then + echo "$ac_t""$LD" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +test -n "$LD" && break +done +test -n "$LD" || LD=":" + + fi if test -z "$DLLTOOL"; then for ac_prog in "${target_alias}-dlltool" "${target}-dlltool" do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1500: checking for $ac_word" >&5 +echo "configure:1537: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_DLLTOOL'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1533,7 +1570,7 @@ do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1537: checking for $ac_word" >&5 +echo "configure:1574: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_WINDRES'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1568,7 +1605,7 @@ else # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1572: checking for $ac_word" >&5 +echo "configure:1609: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1598,7 +1635,7 @@ if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1602: checking for $ac_word" >&5 +echo "configure:1639: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1649,7 +1686,7 @@ fi # Extract the first word of "cl", so it can be a program name with args. set dummy cl; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1653: checking for $ac_word" >&5 +echo "configure:1690: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1681,7 +1718,7 @@ fi fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 -echo "configure:1685: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 +echo "configure:1722: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 ac_ext=c # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. @@ -1692,12 +1729,12 @@ cross_compiling=$ac_cv_prog_cc_cross cat > conftest.$ac_ext << EOF -#line 1696 "configure" +#line 1733 "configure" #include "confdefs.h" main(){return(0);} EOF -if { (eval echo configure:1701: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1738: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then ac_cv_prog_cc_works=yes # If we can't run a trivial program, we are probably using a cross compiler. if (./conftest; exit) 2>/dev/null; then @@ -1723,12 +1760,12 @@ if test $ac_cv_prog_cc_works = no; then { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 -echo "configure:1727: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "configure:1764: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 cross_compiling=$ac_cv_prog_cc_cross echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 -echo "configure:1732: checking whether we are using GNU C" >&5 +echo "configure:1769: checking whether we are using GNU C" >&5 if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1737,7 +1774,7 @@ else yes; #endif EOF -if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1741: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then +if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1778: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then ac_cv_prog_gcc=yes else ac_cv_prog_gcc=no @@ -1756,7 +1793,7 @@ ac_test_CFLAGS="${CFLAGS+set}" ac_save_CFLAGS="$CFLAGS" CFLAGS= echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 -echo "configure:1760: checking whether ${CC-cc} accepts -g" >&5 +echo "configure:1797: checking whether ${CC-cc} accepts -g" >&5 if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1792,7 +1829,7 @@ do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1796: checking for $ac_word" >&5 +echo "configure:1833: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CXX'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1824,7 +1861,7 @@ test -n "$CXX" || CXX="gcc" echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works""... $ac_c" 1>&6 -echo "configure:1828: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works" >&5 +echo "configure:1865: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works" >&5 ac_ext=C # CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. @@ -1835,12 +1872,12 @@ cross_compiling=$ac_cv_prog_cxx_cross cat > conftest.$ac_ext << EOF -#line 1839 "configure" +#line 1876 "configure" #include "confdefs.h" int main(){return(0);} EOF -if { (eval echo configure:1844: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1881: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then ac_cv_prog_cxx_works=yes # If we can't run a trivial program, we are probably using a cross compiler. if (./conftest; exit) 2>/dev/null; then @@ -1866,12 +1903,12 @@ if test $ac_cv_prog_cxx_works = no; then { echo "configure: error: installation or configuration problem: C++ compiler cannot create executables." 1>&2; exit 1; } fi echo $ac_n "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 -echo "configure:1870: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "configure:1907: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) is a cross-compiler" >&5 echo "$ac_t""$ac_cv_prog_cxx_cross" 1>&6 cross_compiling=$ac_cv_prog_cxx_cross echo $ac_n "checking whether we are using GNU C++""... $ac_c" 1>&6 -echo "configure:1875: checking whether we are using GNU C++" >&5 +echo "configure:1912: checking whether we are using GNU C++" >&5 if eval "test \"`echo '$''{'ac_cv_prog_gxx'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1880,7 +1917,7 @@ else yes; #endif EOF -if { ac_try='${CXX-g++} -E conftest.C'; { (eval echo configure:1884: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then +if { ac_try='${CXX-g++} -E conftest.C'; { (eval echo configure:1921: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then ac_cv_prog_gxx=yes else ac_cv_prog_gxx=no @@ -1899,7 +1936,7 @@ ac_test_CXXFLAGS="${CXXFLAGS+set}" ac_save_CXXFLAGS="$CXXFLAGS" CXXFLAGS= echo $ac_n "checking whether ${CXX-g++} accepts -g""... $ac_c" 1>&6 -echo "configure:1903: checking whether ${CXX-g++} accepts -g" >&5 +echo "configure:1940: checking whether ${CXX-g++} accepts -g" >&5 if eval "test \"`echo '$''{'ac_cv_prog_cxx_g'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1933,7 +1970,7 @@ fi # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1937: checking for $ac_word" >&5 +echo "configure:1974: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1965,7 +2002,7 @@ do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1969: checking for $ac_word" >&5 +echo "configure:2006: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_AS'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2006,7 +2043,7 @@ do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2010: checking for $ac_word" >&5 +echo "configure:2047: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_AR'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2042,12 +2079,53 @@ test -n "$AR" && break done test -n "$AR" || AR=":" + for ac_prog in ld +do +# Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:2088: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_LD'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$LD" in + /*) + ac_cv_path_LD="$LD" # Let the user override the test with a path. + ;; + ?:/*) + ac_cv_path_LD="$LD" # Let the user override the test with a dos path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_LD="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + ;; +esac +fi +LD="$ac_cv_path_LD" +if test -n "$LD"; then + echo "$ac_t""$LD" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +test -n "$LD" && break +done +test -n "$LD" || LD=":" + for ac_prog in dlltool do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2051: checking for $ac_word" >&5 +echo "configure:2129: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_DLLTOOL'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2088,7 +2166,7 @@ do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2092: checking for $ac_word" >&5 +echo "configure:2170: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_WINDRES'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2152,7 +2230,7 @@ rm -f a.out # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # ./install, which can be erroneously created by make from ./install.sh. echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 -echo "configure:2156: checking for a BSD compatible install" >&5 +echo "configure:2234: checking for a BSD compatible install" >&5 if test -z "$INSTALL"; then if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -2205,7 +2283,7 @@ test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6 -echo "configure:2209: checking whether ln -s works" >&5 +echo "configure:2287: checking whether ln -s works" >&5 if eval "test \"`echo '$''{'ac_cv_prog_LN_S'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2230,7 +2308,7 @@ do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2234: checking for $ac_word" >&5 +echo "configure:2312: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_PERL'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2284,6 +2362,9 @@ OS_TEST=`uname -m` case "$host" in *-mingw*) ;; +*-beos*) + HOST_CFLAGS="$HOST_CFLAGS -DXP_BEOS -DBeOS -DBEOS -D_POSIX_SOURCE" + ;; *) HOST_CFLAGS="$HOST_CFLAGS -DXP_UNIX" ;; @@ -2785,6 +2866,10 @@ EOF #define _SVID_SOURCE 1 EOF + cat >> confdefs.h <<\EOF +#define LINUX 1 +EOF + CFLAGS="$CFLAGS -pipe -ansi" CXXFLAGS="$CXXFLAGS -pipe -ansi" MDCPUCFG_H=_linux.cfg @@ -2822,6 +2907,10 @@ EOF #define XP_PC 1 EOF + cat >> confdefs.h <<\EOF +#define NONAMELESSUNION 1 +EOF + PR_MD_ARCH_DIR=windows if test -z "$GNU_CC"; then OBJ_SUFFIX=obj @@ -3024,7 +3113,7 @@ fi echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 -echo "configure:3028: checking how to run the C preprocessor" >&5 +echo "configure:3117: checking how to run the C preprocessor" >&5 # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= @@ -3039,13 +3128,13 @@ else # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. cat > conftest.$ac_ext <<EOF -#line 3043 "configure" +#line 3132 "configure" #include "confdefs.h" #include <assert.h> Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:3049: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:3138: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : @@ -3056,13 +3145,13 @@ else rm -rf conftest* CPP="${CC-cc} -E -traditional-cpp" cat > conftest.$ac_ext <<EOF -#line 3060 "configure" +#line 3149 "configure" #include "confdefs.h" #include <assert.h> Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:3066: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:3155: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : @@ -3073,13 +3162,13 @@ else rm -rf conftest* CPP="${CC-cc} -nologo -E" cat > conftest.$ac_ext <<EOF -#line 3077 "configure" +#line 3166 "configure" #include "confdefs.h" #include <assert.h> Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:3083: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:3172: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : @@ -3105,13 +3194,13 @@ echo "$ac_t""$CPP" 1>&6 if test $ac_cv_prog_gcc = yes; then echo $ac_n "checking whether ${CC-cc} needs -traditional""... $ac_c" 1>&6 -echo "configure:3109: checking whether ${CC-cc} needs -traditional" >&5 +echo "configure:3198: checking whether ${CC-cc} needs -traditional" >&5 if eval "test \"`echo '$''{'ac_cv_prog_gcc_traditional'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_pattern="Autoconf.*'x'" cat > conftest.$ac_ext <<EOF -#line 3115 "configure" +#line 3204 "configure" #include "confdefs.h" #include <sgtty.h> Autoconf TIOCGETP @@ -3129,7 +3218,7 @@ rm -f conftest* if test $ac_cv_prog_gcc_traditional = no; then cat > conftest.$ac_ext <<EOF -#line 3133 "configure" +#line 3222 "configure" #include "confdefs.h" #include <termio.h> Autoconf TCGETA @@ -3153,12 +3242,12 @@ fi for ac_func in lchown strerror do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:3157: checking for $ac_func" >&5 +echo "configure:3246: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 3162 "configure" +#line 3251 "configure" #include "confdefs.h" /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func(); below. */ @@ -3181,7 +3270,7 @@ $ac_func(); ; return 0; } EOF -if { (eval echo configure:3185: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:3274: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -3209,7 +3298,7 @@ done echo $ac_n "checking for pthread_attr_init in -lpthread""... $ac_c" 1>&6 -echo "configure:3213: checking for pthread_attr_init in -lpthread" >&5 +echo "configure:3302: checking for pthread_attr_init in -lpthread" >&5 ac_lib_var=`echo pthread'_'pthread_attr_init | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -3217,7 +3306,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lpthread $LIBS" cat > conftest.$ac_ext <<EOF -#line 3221 "configure" +#line 3310 "configure" #include "confdefs.h" /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 @@ -3228,7 +3317,7 @@ int main() { pthread_attr_init() ; return 0; } EOF -if { (eval echo configure:3232: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:3321: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -3247,7 +3336,7 @@ if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then else echo "$ac_t""no" 1>&6 echo $ac_n "checking for pthread_attr_init in -lc_r""... $ac_c" 1>&6 -echo "configure:3251: checking for pthread_attr_init in -lc_r" >&5 +echo "configure:3340: checking for pthread_attr_init in -lc_r" >&5 ac_lib_var=`echo c_r'_'pthread_attr_init | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -3255,7 +3344,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lc_r $LIBS" cat > conftest.$ac_ext <<EOF -#line 3259 "configure" +#line 3348 "configure" #include "confdefs.h" /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 @@ -3266,7 +3355,7 @@ int main() { pthread_attr_init() ; return 0; } EOF -if { (eval echo configure:3270: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:3359: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -3285,7 +3374,7 @@ if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then else echo "$ac_t""no" 1>&6 echo $ac_n "checking for pthread_attr_init in -lc""... $ac_c" 1>&6 -echo "configure:3289: checking for pthread_attr_init in -lc" >&5 +echo "configure:3378: checking for pthread_attr_init in -lc" >&5 ac_lib_var=`echo c'_'pthread_attr_init | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -3293,7 +3382,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lc $LIBS" cat > conftest.$ac_ext <<EOF -#line 3297 "configure" +#line 3386 "configure" #include "confdefs.h" /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 @@ -3304,7 +3393,7 @@ int main() { pthread_attr_init() ; return 0; } EOF -if { (eval echo configure:3308: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:3397: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -3431,7 +3520,7 @@ if test -n "$USE_PTHREADS"; then rm -f conftest* ac_cv_have_dash_pthread=no echo $ac_n "checking whether ${CC-cc} accepts -pthread""... $ac_c" 1>&6 -echo "configure:3435: checking whether ${CC-cc} accepts -pthread" >&5 +echo "configure:3524: checking whether ${CC-cc} accepts -pthread" >&5 echo 'int main() { return 0; }' | cat > conftest.c ${CC-cc} -pthread -o conftest conftest.c > conftest.out 2>&1 if test $? -eq 0; then @@ -3501,12 +3590,12 @@ EOF esac echo $ac_n "checking for pthread_create""... $ac_c" 1>&6 -echo "configure:3505: checking for pthread_create" >&5 +echo "configure:3594: checking for pthread_create" >&5 if eval "test \"`echo '$''{'ac_cv_func_pthread_create'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 3510 "configure" +#line 3599 "configure" #include "confdefs.h" /* System header to define __stub macros and hopefully few prototypes, which can conflict with char pthread_create(); below. */ @@ -3529,7 +3618,7 @@ pthread_create(); ; return 0; } EOF -if { (eval echo configure:3533: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:3622: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_pthread_create=yes" else @@ -3548,7 +3637,7 @@ else echo "$ac_t""no" 1>&6 echo $ac_n "checking for pthread_create in -lpthread""... $ac_c" 1>&6 -echo "configure:3552: checking for pthread_create in -lpthread" >&5 +echo "configure:3641: checking for pthread_create in -lpthread" >&5 ac_lib_var=`echo pthread'_'pthread_create | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -3556,7 +3645,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lpthread $LIBS" cat > conftest.$ac_ext <<EOF -#line 3560 "configure" +#line 3649 "configure" #include "confdefs.h" /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 @@ -3567,7 +3656,7 @@ int main() { pthread_create() ; return 0; } EOF -if { (eval echo configure:3571: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:3660: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -3666,12 +3755,12 @@ EOF esac echo $ac_n "checking for dlopen""... $ac_c" 1>&6 -echo "configure:3670: checking for dlopen" >&5 +echo "configure:3759: checking for dlopen" >&5 if eval "test \"`echo '$''{'ac_cv_func_dlopen'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 3675 "configure" +#line 3764 "configure" #include "confdefs.h" /* System header to define __stub macros and hopefully few prototypes, which can conflict with char dlopen(); below. */ @@ -3694,7 +3783,7 @@ dlopen(); ; return 0; } EOF -if { (eval echo configure:3698: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:3787: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_dlopen=yes" else @@ -3713,7 +3802,7 @@ else echo "$ac_t""no" 1>&6 echo $ac_n "checking for dlopen in -ldl""... $ac_c" 1>&6 -echo "configure:3717: checking for dlopen in -ldl" >&5 +echo "configure:3806: checking for dlopen in -ldl" >&5 ac_lib_var=`echo dl'_'dlopen | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -3721,7 +3810,7 @@ else ac_save_LIBS="$LIBS" LIBS="-ldl $LIBS" cat > conftest.$ac_ext <<EOF -#line 3725 "configure" +#line 3814 "configure" #include "confdefs.h" /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 @@ -3732,7 +3821,7 @@ int main() { dlopen() ; return 0; } EOF -if { (eval echo configure:3736: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:3825: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -3826,6 +3915,7 @@ fi + trap '' 1 2 15 cat > confcache <<\EOF # This file is a shell script that caches the results of configure @@ -4036,6 +4126,7 @@ s%@CXX@%$CXX%g s%@RANLIB@%$RANLIB%g s%@AR@%$AR%g s%@AS@%$AS%g +s%@LD@%$LD%g s%@DLLTOOL@%$DLLTOOL%g s%@WINDRES@%$WINDRES%g s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g diff --git a/configure.in b/configure.in index 450e0502..aa7fa6a0 100644 --- a/configure.in +++ b/configure.in @@ -40,7 +40,7 @@ AC_DEFINE(USE_AUTOCONF) dnl ======================================================== dnl = Defaults dnl ======================================================== -NSPR_VERSION=3 +NSPR_VERSION=4 NSPR_MODNAME=nspr20 _HAVE_PTHREADS= USE_PTHREADS= @@ -195,6 +195,9 @@ if test "$target" != "$host"; then if test -z "$AS"; then AC_CHECK_PROGS(AS, "${target_alias}-as" "${target}-as", :) fi + if test -z "$LD"; then + AC_CHECK_PROGS(LD, "${target_alias}-ld" "${target}-ld", :) + fi if test -z "$DLLTOOL"; then AC_CHECK_PROGS(DLLTOOL, "${target_alias}-dlltool" "${target}-dlltool", :) fi @@ -207,6 +210,7 @@ else AC_PROG_RANLIB AC_PATH_PROGS(AS, as, $CC) AC_PATH_PROGS(AR, ar, :) + AC_PATH_PROGS(LD, ld, :) AC_PATH_PROGS(DLLTOOL, dlltool, :) AC_PATH_PROGS(WINDRES, windres, :) if test -z "$HOST_CC"; then @@ -255,6 +259,9 @@ dnl ======================================================== case "$host" in *-mingw*) ;; +*-beos*) + HOST_CFLAGS="$HOST_CFLAGS -DXP_BEOS -DBeOS -DBEOS -D_POSIX_SOURCE" + ;; *) HOST_CFLAGS="$HOST_CFLAGS -DXP_UNIX" ;; @@ -555,6 +562,7 @@ case "$target" in AC_DEFINE(_POSIX_SOURCE) AC_DEFINE(_BSD_SOURCE) AC_DEFINE(_SVID_SOURCE) + AC_DEFINE(LINUX) CFLAGS="$CFLAGS -pipe -ansi" CXXFLAGS="$CXXFLAGS -pipe -ansi" MDCPUCFG_H=_linux.cfg @@ -583,6 +591,7 @@ case "$target" in *-mingw*) AC_DEFINE(XP_PC) + AC_DEFINE(NONAMELESSUNION) PR_MD_ARCH_DIR=windows if test -z "$GNU_CC"; then OBJ_SUFFIX=obj @@ -1051,6 +1060,7 @@ AC_SUBST(AR) AC_SUBST(AR_FLAGS) AC_SUBST(AS) AC_SUBST(ASFLAGS) +AC_SUBST(LD) AC_SUBST(DLLTOOL) AC_SUBST(WINDRES) AC_SUBST(RANLIB) diff --git a/lib/Makefile b/lib/Makefile index 503670a7..9bb7d95c 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -25,10 +25,6 @@ include $(MOD_DEPTH)/config/config.mk DIRS = ds libc -ifneq (,$(filter-out Rhapsody WIN16 NEWS-OS,$(OS_TARGET))) -DIRS += prstreams -endif - include $(MOD_DEPTH)/config/rules.mk export:: $(TARGETS) diff --git a/lib/Makefile.in b/lib/Makefile.in index ff842c69..e6a1c312 100644 --- a/lib/Makefile.in +++ b/lib/Makefile.in @@ -30,10 +30,6 @@ include $(topsrcdir)/config/config.mk DIRS = ds libc -ifneq (,$(filter-out Rhapsody WIN16 NEWS-OS,$(OS_TARGET))) -DIRS += prstreams -endif - include $(topsrcdir)/config/rules.mk export:: $(TARGETS) diff --git a/lib/ds/plds.rc b/lib/ds/plds.rc index c9aceae8..10311c0a 100644 --- a/lib/ds/plds.rc +++ b/lib/ds/plds.rc @@ -22,6 +22,10 @@ #define MY_LIBNAME "plds" #define MY_FILEDESCRIPTION "PLDS Library" +#define STRINGIZE(x) #x +#define STRINGIZE2(x) STRINGIZE(x) +#define PR_VMAJOR_STR STRINGIZE2(PR_VMAJOR) + #ifdef _DEBUG #define MY_DEBUG_STR " (debug)" #define MY_FILEFLAGS_1 VS_FF_DEBUG @@ -66,7 +70,7 @@ BEGIN VALUE "FileDescription", MY_FILEDESCRIPTION MY_DEBUG_STR "\0" VALUE "FileVersion", PR_VERSION "\0" VALUE "InternalName", MY_INTERNAL_NAME "\0" - VALUE "LegalCopyright", "Copyright \251 1996-1999 Netscape Communications Corporation\0" + VALUE "LegalCopyright", "Copyright \251 1996-2000 Netscape Communications Corporation\0" VALUE "OriginalFilename", MY_INTERNAL_NAME ".dll\0" VALUE "ProductName", "Netscape Portable Runtime\0" VALUE "ProductVersion", PR_VERSION "\0" diff --git a/lib/ds/plvrsion.c b/lib/ds/plvrsion.c index ac88e344..009ed53a 100644 --- a/lib/ds/plvrsion.c +++ b/lib/ds/plvrsion.c @@ -42,7 +42,14 @@ #define _DEBUG_STRING "" #endif -PRVersionDescription prVersionDescription_libplds3 = +/* + * A trick to expand the PR_VMAJOR macro before concatenation. + */ +#define CONCAT(x, y) x ## y +#define CONCAT2(x, y) CONCAT(x, y) +#define VERSION_DESC_NAME CONCAT2(prVersionDescription_libplds, PR_VMAJOR) + +PRVersionDescription VERSION_DESC_NAME = { /* version */ 2, /* this is the only one supported */ /* buildTime */ _BUILD_TIME, /* usecs since midnight 1/1/1970 GMT */ @@ -92,7 +99,7 @@ PR_IMPLEMENT(const PRVersionDescription*) libVersionPoint() dummy = rcsid; dummy = sccsid; #endif - return &prVersionDescription_libplds3; + return &VERSION_DESC_NAME; } /* versionEntryPointType */ /* plvrsion.c */ diff --git a/lib/libc/src/plc.rc b/lib/libc/src/plc.rc index 3283a44b..30287525 100644 --- a/lib/libc/src/plc.rc +++ b/lib/libc/src/plc.rc @@ -22,6 +22,10 @@ #define MY_LIBNAME "plc" #define MY_FILEDESCRIPTION "PLC Library" +#define STRINGIZE(x) #x +#define STRINGIZE2(x) STRINGIZE(x) +#define PR_VMAJOR_STR STRINGIZE2(PR_VMAJOR) + #ifdef _DEBUG #define MY_DEBUG_STR " (debug)" #define MY_FILEFLAGS_1 VS_FF_DEBUG @@ -66,7 +70,7 @@ BEGIN VALUE "FileDescription", MY_FILEDESCRIPTION MY_DEBUG_STR "\0" VALUE "FileVersion", PR_VERSION "\0" VALUE "InternalName", MY_INTERNAL_NAME "\0" - VALUE "LegalCopyright", "Copyright \251 1996-1999 Netscape Communications Corporation\0" + VALUE "LegalCopyright", "Copyright \251 1996-2000 Netscape Communications Corporation\0" VALUE "OriginalFilename", MY_INTERNAL_NAME ".dll\0" VALUE "ProductName", "Netscape Portable Runtime\0" VALUE "ProductVersion", PR_VERSION "\0" diff --git a/lib/libc/src/plvrsion.c b/lib/libc/src/plvrsion.c index 619fc4bb..93c08c77 100644 --- a/lib/libc/src/plvrsion.c +++ b/lib/libc/src/plvrsion.c @@ -42,7 +42,14 @@ #define _DEBUG_STRING "" #endif -PRVersionDescription prVersionDescription_libplc3 = +/* + * A trick to expand the PR_VMAJOR macro before concatenation. + */ +#define CONCAT(x, y) x ## y +#define CONCAT2(x, y) CONCAT(x, y) +#define VERSION_DESC_NAME CONCAT2(prVersionDescription_libplc, PR_VMAJOR) + +PRVersionDescription VERSION_DESC_NAME = { /* version */ 2, /* this is the only one supported */ /* buildTime */ _BUILD_TIME, /* usecs since midnight 1/1/1970 GMT */ @@ -92,7 +99,7 @@ PR_IMPLEMENT(const PRVersionDescription*) libVersionPoint() dummy = rcsid; dummy = sccsid; #endif - return &prVersionDescription_libplc3; + return &VERSION_DESC_NAME; } /* versionEntryPointType */ /* plvrsion.c */ diff --git a/lib/prstreams/plvrsion.c b/lib/prstreams/plvrsion.c index 55251da2..47b0311e 100644 --- a/lib/prstreams/plvrsion.c +++ b/lib/prstreams/plvrsion.c @@ -42,7 +42,14 @@ #define _DEBUG_STRING "" #endif -PRVersionDescription prVersionDescription_libprstrms3 = +/* + * A trick to expand the PR_VMAJOR macro before concatenation. + */ +#define CONCAT(x, y) x ## y +#define CONCAT2(x, y) CONCAT(x, y) +#define VERSION_DESC_NAME CONCAT2(prVersionDescription_libprstrms, PR_VMAJOR) + +PRVersionDescription VERSION_DESC_NAME = { /* version */ 2, /* this is the only one supported */ /* buildTime */ _BUILD_TIME, /* usecs since midnight 1/1/1970 GMT */ @@ -92,7 +99,7 @@ PR_IMPLEMENT(const PRVersionDescription*) libVersionPoint() dummy = rcsid; dummy = sccsid; #endif - return &prVersionDescription_libprstrms3; + return &VERSION_DESC_NAME; } /* versionEntryPointType */ /* plvrsion.c */ diff --git a/lib/prstreams/prstrms.cpp b/lib/prstreams/prstrms.cpp index 09ecc26c..0fb34f79 100644 --- a/lib/prstreams/prstrms.cpp +++ b/lib/prstreams/prstrms.cpp @@ -222,7 +222,7 @@ PRfilebuf::underflow() } streambuf* -PRfilebuf::setbuf(char *buffptr, int bufflen) +PRfilebuf::setbuf(char *buffptr, PRstreambuflen bufflen) { if (is_open() && (ebuf())) return 0; diff --git a/lib/prstreams/prstrms.h b/lib/prstreams/prstrms.h index 2af53953..43ce7fed 100644 --- a/lib/prstreams/prstrms.h +++ b/lib/prstreams/prstrms.h @@ -31,6 +31,12 @@ #endif #include <iostream.h> +#if defined(AIX) && defined(__64BIT__) +typedef long PRstreambuflen; +#else +typedef int PRstreambuflen; +#endif + #if defined (PRFSTREAMS_BROKEN) // fix it sometime @@ -51,7 +57,7 @@ public: ~PRfilebuf(); virtual int overflow(int=EOF); virtual int underflow(); - virtual streambuf *setbuf(char *buff, int bufflen); + virtual streambuf *setbuf(char *buff, PRstreambuflen bufflen); virtual streampos seekoff(streamoff, ios::seek_dir, int); virtual int sync(); PRfilebuf *open(const char *name, int mode, int flags); diff --git a/lib/prstreams/prstrms.rc b/lib/prstreams/prstrms.rc index 6fecf644..4938cc7d 100644 --- a/lib/prstreams/prstrms.rc +++ b/lib/prstreams/prstrms.rc @@ -22,6 +22,10 @@ #define MY_LIBNAME "prstrms" #define MY_FILEDESCRIPTION "PRSTRMS Library" +#define STRINGIZE(x) #x +#define STRINGIZE2(x) STRINGIZE(x) +#define PR_VMAJOR_STR STRINGIZE2(PR_VMAJOR) + #ifdef _DEBUG #define MY_DEBUG_STR " (debug)" #define MY_FILEFLAGS_1 VS_FF_DEBUG @@ -66,7 +70,7 @@ BEGIN VALUE "FileDescription", MY_FILEDESCRIPTION MY_DEBUG_STR "\0" VALUE "FileVersion", PR_VERSION "\0" VALUE "InternalName", MY_INTERNAL_NAME "\0" - VALUE "LegalCopyright", "Copyright \251 1996-1999 Netscape Communications Corporation\0" + VALUE "LegalCopyright", "Copyright \251 1996-2000 Netscape Communications Corporation\0" VALUE "OriginalFilename", MY_INTERNAL_NAME ".dll\0" VALUE "ProductName", "Netscape Portable Runtime\0" VALUE "ProductVersion", PR_VERSION "\0" diff --git a/macbuild/NSPR20PPC.mcp b/macbuild/NSPR20PPC.mcp Binary files differindex 04732ff7..fa75d4da 100644 --- a/macbuild/NSPR20PPC.mcp +++ b/macbuild/NSPR20PPC.mcp diff --git a/makefile.win b/makefile.win index 6c45879f..5948366b 100644 --- a/makefile.win +++ b/makefile.win @@ -82,7 +82,7 @@ PR_OBJDIR = WIN954.0_OPT.OBJ all:: export libs install -export libs install clobber clobber_all clean:: +export libs install clobber clobber_all clean depend:: !if "$(MOZ_BITS)" == "16" set PATH=%WATCPATH% set INCLUDE=%WATC_INC% @@ -103,6 +103,3 @@ export:: $(MAKE_INSTALL) $(XPDIST)\$(PR_OBJDIR)\lib\*.lib $(DIST)\lib $(MAKE_INSTALL) $(XPDIST)\$(PR_OBJDIR)\lib\*.dll $(DIST)\bin !endif - -depend:: - @echo NSPR20 has no dependencies. Skipped. diff --git a/pr/include/MANIFEST b/pr/include/MANIFEST index d62b6ae9..634968ef 100644 --- a/pr/include/MANIFEST +++ b/pr/include/MANIFEST @@ -37,6 +37,7 @@ prshma.h prsystem.h prthread.h prtime.h +prtpool.h prtrace.h prtypes.h prvrsion.h diff --git a/pr/include/md/_aix.h b/pr/include/md/_aix.h index a80ccb06..58f37d39 100644 --- a/pr/include/md/_aix.h +++ b/pr/include/md/_aix.h @@ -59,6 +59,7 @@ #endif #define _PR_HAVE_SYSV_SEMAPHORES #define PR_HAVE_SYSV_NAMED_SHARED_MEMORY +#define _PR_ACCEPT_INHERIT_NONBLOCK /* Timer operations */ #if defined(AIX_TIMERS) diff --git a/pr/include/md/_aix32.cfg b/pr/include/md/_aix32.cfg index c1267e23..2fca5190 100644 --- a/pr/include/md/_aix32.cfg +++ b/pr/include/md/_aix32.cfg @@ -73,6 +73,8 @@ #undef HAVE_ALIGNED_DOUBLES #undef HAVE_ALIGNED_LONGLONGS +#define PR_AF_INET6 24 /* same as AF_INET6 */ + #ifndef NO_NSPR_10_SUPPORT #define BYTES_PER_BYTE PR_BYTES_PER_BYTE diff --git a/pr/include/md/_aix32in6.cfg b/pr/include/md/_aix32in6.cfg index bc9458c6..0385e86a 100644 --- a/pr/include/md/_aix32in6.cfg +++ b/pr/include/md/_aix32in6.cfg @@ -76,6 +76,7 @@ #ifndef _PR_INET6 #define _PR_INET6 #endif +#define PR_AF_INET6 24 /* same as AF_INET6 */ #ifndef NO_NSPR_10_SUPPORT diff --git a/pr/include/md/_aix64.cfg b/pr/include/md/_aix64.cfg index b8e3e884..59bb1a79 100644 --- a/pr/include/md/_aix64.cfg +++ b/pr/include/md/_aix64.cfg @@ -77,6 +77,7 @@ #ifndef _PR_INET6 #define _PR_INET6 #endif +#define PR_AF_INET6 24 /* same as AF_INET6 */ #ifndef NO_NSPR_10_SUPPORT diff --git a/pr/include/md/_beos.h b/pr/include/md/_beos.h index e98e8f36..8b56dec3 100644 --- a/pr/include/md/_beos.h +++ b/pr/include/md/_beos.h @@ -285,6 +285,7 @@ struct protoent* getprotobynumber(int number); #define _MD_CLOSE_DIR _MD_close_dir #define _MD_MAKE_NONBLOCK _MD_make_nonblock #define _MD_OPEN _MD_open +#define _MD_OPEN_FILE _MD_open #define _MD_CLOSE_FILE _MD_close_file #define _MD_READ _MD_read #define _MD_WRITE _MD_write @@ -301,6 +302,7 @@ struct protoent* getprotobynumber(int number); #define _MD_ACCESS _MD_access #define _MD_STAT stat #define _MD_MKDIR _MD_mkdir +#define _MD_MAKE_DIR _MD_mkdir #define _MD_RMDIR _MD_rmdir #define _MD_PR_POLL _MD_pr_poll diff --git a/pr/include/md/_hpux.h b/pr/include/md/_hpux.h index 0d45f6c3..22c38c44 100644 --- a/pr/include/md/_hpux.h +++ b/pr/include/md/_hpux.h @@ -48,6 +48,7 @@ #define _PR_STAT_HAS_ONLY_ST_ATIME #define _PR_HAVE_POSIX_SEMAPHORES #define PR_HAVE_POSIX_NAMED_SHARED_MEMORY +#define _PR_ACCEPT_INHERIT_NONBLOCK #undef _PR_HAVE_ATOMIC_OPS diff --git a/pr/include/md/_hpux32.cfg b/pr/include/md/_hpux32.cfg index 1afc14a4..85ff9476 100644 --- a/pr/include/md/_hpux32.cfg +++ b/pr/include/md/_hpux32.cfg @@ -30,6 +30,8 @@ #undef IS_LITTLE_ENDIAN #define IS_BIG_ENDIAN 1 +#define PR_AF_INET6 22 /* same as AF_INET6 */ + #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 diff --git a/pr/include/md/_hpux64.cfg b/pr/include/md/_hpux64.cfg index d2b626e2..3450f7fa 100644 --- a/pr/include/md/_hpux64.cfg +++ b/pr/include/md/_hpux64.cfg @@ -31,6 +31,8 @@ #define IS_BIG_ENDIAN 1 #define IS_64 +#define PR_AF_INET6 22 /* same as AF_INET6 */ + #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 diff --git a/pr/include/md/_irix.h b/pr/include/md/_irix.h index f5f20eb2..dea7f654 100644 --- a/pr/include/md/_irix.h +++ b/pr/include/md/_irix.h @@ -60,6 +60,7 @@ #define HAVE_POINTER_LOCALTIME_R #define _PR_HAVE_POSIX_SEMAPHORES #define PR_HAVE_POSIX_NAMED_SHARED_MEMORY +#define _PR_ACCEPT_INHERIT_NONBLOCK /* Initialization entry points */ NSPR_API(void) _MD_EarlyInit(void); diff --git a/pr/include/md/_irix32.cfg b/pr/include/md/_irix32.cfg index f791faf8..ee6fc686 100644 --- a/pr/include/md/_irix32.cfg +++ b/pr/include/md/_irix32.cfg @@ -34,6 +34,8 @@ #undef IS_LITTLE_ENDIAN #define IS_BIG_ENDIAN 1 +#define PR_AF_INET6 24 /* same as AF_INET6 */ + #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 diff --git a/pr/include/md/_irix64.cfg b/pr/include/md/_irix64.cfg index 7e988172..ddc4305c 100644 --- a/pr/include/md/_irix64.cfg +++ b/pr/include/md/_irix64.cfg @@ -35,6 +35,8 @@ #define IS_BIG_ENDIAN 1 #define IS_64 +#define PR_AF_INET6 24 /* same as AF_INET6 */ + #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 diff --git a/pr/include/md/_linux.cfg b/pr/include/md/_linux.cfg index aa99901c..33fa2683 100644 --- a/pr/include/md/_linux.cfg +++ b/pr/include/md/_linux.cfg @@ -27,6 +27,8 @@ #define LINUX #endif +#define PR_AF_INET6 10 /* same as AF_INET6 */ + #ifdef __powerpc__ #undef IS_LITTLE_ENDIAN diff --git a/pr/include/md/_linux.h b/pr/include/md/_linux.h index 7980934c..11885b41 100644 --- a/pr/include/md/_linux.h +++ b/pr/include/md/_linux.h @@ -70,6 +70,10 @@ #else #define _PR_NO_LARGE_FILES #endif +#ifdef _PR_INET6 +#define _PR_HAVE_GETHOSTBYNAME2 +#define _PR_INET6_PROBE +#endif #define _PR_HAVE_SYSV_SEMAPHORES #define PR_HAVE_SYSV_NAMED_SHARED_MEMORY diff --git a/pr/include/md/_macos.h b/pr/include/md/_macos.h index e6ecd016..cf38977f 100644 --- a/pr/include/md/_macos.h +++ b/pr/include/md/_macos.h @@ -318,6 +318,7 @@ typedef enum IOOperation { #define _MD_INIT_IO() #define _MD_OPEN _MD_Open +#define _MD_OPEN_FILE _MD_Open #define _MD_CLOSE_FILE FSClose #define _MD_READ(fd,buf,amount) ReadWriteProc(fd,buf,amount,READ_ASYNC) #define _MD_WRITE(fd,buf,amount) ReadWriteProc(fd,buf,amount,WRITE_ASYNC) @@ -368,6 +369,7 @@ extern char* _MD_ReadDir(struct _MDDir *md,PRIntn flags); #define _MD_CLOSE_DIR _MD_CloseDir #define _MD_MKDIR _MD_MkDir +#define _MD_MAKE_DIR _MD_MkDir #define _MD_RMDIR _MD_Delete /* diff --git a/pr/include/md/_os2.h b/pr/include/md/_os2.h index 9fb935c2..70e8d112 100644 --- a/pr/include/md/_os2.h +++ b/pr/include/md/_os2.h @@ -182,6 +182,7 @@ struct _MDProcess { /* --- IO stuff --- */ #define _MD_OPEN (_PR_MD_OPEN) +#define _MD_OPEN_FILE (_PR_MD_OPEN) #define _MD_READ (_PR_MD_READ) #define _MD_WRITE (_PR_MD_WRITE) #define _MD_WRITEV (_PR_MD_WRITEV) @@ -198,6 +199,7 @@ extern PRInt32 _MD_CloseFile(PRInt32 osfd); #define _MD_ACCESS (_PR_MD_ACCESS) #define _MD_DELETE (_PR_MD_DELETE) #define _MD_MKDIR (_PR_MD_MKDIR) +#define _MD_MAKE_DIR (_PR_MD_MKDIR) #define _MD_RMDIR (_PR_MD_RMDIR) #define _MD_LOCKFILE (_PR_MD_LOCKFILE) #define _MD_TLOCKFILE (_PR_MD_TLOCKFILE) diff --git a/pr/include/md/_osf1.cfg b/pr/include/md/_osf1.cfg index 576af82b..e01e9df5 100644 --- a/pr/include/md/_osf1.cfg +++ b/pr/include/md/_osf1.cfg @@ -36,6 +36,8 @@ #define IS_64 #endif +#define PR_AF_INET6 26 /* same as AF_INET6 */ + #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 diff --git a/pr/include/md/_osf1.h b/pr/include/md/_osf1.h index 96a2fe22..c0b95cb5 100644 --- a/pr/include/md/_osf1.h +++ b/pr/include/md/_osf1.h @@ -46,9 +46,14 @@ #define _PR_USE_POLL #define _PR_STAT_HAS_ONLY_ST_ATIME #define _PR_HAVE_LARGE_OFF_T -#ifdef _PR_INET6 #define _PR_HAVE_GETIPNODEBYNAME #define _PR_HAVE_GETIPNODEBYADDR +#define _PR_INET6_PROBE +#ifndef _PR_INET6 +#define AF_INET6 26 +#define AI_V4MAPPED 0x00000010 +#define AI_ALL 0x00000008 +#define AI_ADDRCONFIG 0x00000020 #endif #define _PR_HAVE_POSIX_SEMAPHORES #define PR_HAVE_POSIX_NAMED_SHARED_MEMORY diff --git a/pr/include/md/_solaris.h b/pr/include/md/_solaris.h index 535c520e..081636e0 100644 --- a/pr/include/md/_solaris.h +++ b/pr/include/md/_solaris.h @@ -73,6 +73,15 @@ #define _PR_HAVE_POSIX_SEMAPHORES #define PR_HAVE_POSIX_NAMED_SHARED_MEMORY #define _PR_HAVE_GETIPNODEBYNAME +#define _PR_HAVE_GETIPNODEBYADDR +#define _PR_INET6_PROBE +#define _PR_ACCEPT_INHERIT_NONBLOCK +#ifndef _PR_INET6 +#define AF_INET6 26 +#define AI_V4MAPPED 0x0001 +#define AI_ALL 0x0002 +#define AI_ADDRCONFIG 0x0004 +#endif #include "prinrval.h" NSPR_API(PRIntervalTime) _MD_Solaris_GetInterval(void); diff --git a/pr/include/md/_solaris32.cfg b/pr/include/md/_solaris32.cfg index f6b988a1..e4c9a9fe 100644 --- a/pr/include/md/_solaris32.cfg +++ b/pr/include/md/_solaris32.cfg @@ -41,6 +41,8 @@ #error unknown processor #endif +#define PR_AF_INET6 26 /* same as AF_INET6 */ + #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 diff --git a/pr/include/md/_solaris64.cfg b/pr/include/md/_solaris64.cfg index 40832724..b302961b 100644 --- a/pr/include/md/_solaris64.cfg +++ b/pr/include/md/_solaris64.cfg @@ -42,6 +42,8 @@ #endif #define IS_64 +#define PR_AF_INET6 26 /* same as AF_INET6 */ + #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 diff --git a/pr/include/md/_unixos.h b/pr/include/md/_unixos.h index e44ab7b8..7bd86872 100644 --- a/pr/include/md/_unixos.h +++ b/pr/include/md/_unixos.h @@ -334,7 +334,8 @@ extern PRStatus _MD_UnlockFile(PRInt32 osfd); #define _MD_OPEN_DIR(dir, name) _MD_open_dir(dir, name) #define _MD_CLOSE_DIR(dir) _MD_close_dir(dir) #define _MD_READ_DIR(dir, flags) _MD_read_dir(dir, flags) -#define _MD_OPEN(name, osflags, mode ) _MD_open(name, osflags, mode) +#define _MD_OPEN(name, osflags, mode) _MD_open(name, osflags, mode) +#define _MD_OPEN_FILE(name, osflags, mode) _MD_open(name, osflags, mode) extern PRInt32 _MD_read(PRFileDesc *fd, void *buf, PRInt32 amount); #define _MD_READ(fd,buf,amount) _MD_read(fd,buf,amount) extern PRInt32 _MD_write(PRFileDesc *fd, const void *buf, PRInt32 amount); @@ -347,6 +348,7 @@ extern PRInt32 _MD_write(PRFileDesc *fd, const void *buf, PRInt32 amount); #define _MD_RENAME(from, to) _MD_rename(from, to) #define _MD_ACCESS(name, how) _MD_access(name, how) #define _MD_MKDIR(name, mode) _MD_mkdir(name, mode) +#define _MD_MAKE_DIR(name, mode) _MD_mkdir(name, mode) #define _MD_RMDIR(name) _MD_rmdir(name) #define _MD_ACCEPT_READ(sock, newSock, raddr, buf, amount) _MD_accept_read(sock, newSock, raddr, buf, amount) diff --git a/pr/include/md/_unixware7.cfg b/pr/include/md/_unixware7.cfg index 3e50f662..855500c1 100644 --- a/pr/include/md/_unixware7.cfg +++ b/pr/include/md/_unixware7.cfg @@ -33,6 +33,8 @@ #undef HAVE_ALIGNED_DOUBLES #undef HAVE_ALIGNED_LONGLONGS +#define PR_AF_INET6 27 /* same as AF_INET6 */ + #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 diff --git a/pr/include/md/_win95.cfg b/pr/include/md/_win95.cfg index af9e0d11..318422f1 100644 --- a/pr/include/md/_win95.cfg +++ b/pr/include/md/_win95.cfg @@ -31,6 +31,8 @@ #define WIN95 #endif +#define PR_AF_INET6 23 /* same as AF_INET6 */ + #if defined(_M_IX86) || defined(_X86_) #define IS_LITTLE_ENDIAN 1 diff --git a/pr/include/md/_win95.h b/pr/include/md/_win95.h index 6878b152..4e8e37a7 100644 --- a/pr/include/md/_win95.h +++ b/pr/include/md/_win95.h @@ -158,9 +158,23 @@ struct _MDProcess { /* --- Misc stuff --- */ #define _MD_GET_SP(thread) (thread)->md.gcContext[6] +/* --- NT security stuff --- */ + +extern void _PR_NT_InitSids(void); +extern void _PR_NT_FreeSids(void); +extern PRStatus _PR_NT_MakeSecurityDescriptorACL( + PRIntn mode, + DWORD accessTable[], + PSECURITY_DESCRIPTOR *resultSD, + PACL *resultACL +); +extern void _PR_NT_FreeSecurityDescriptorACL( + PSECURITY_DESCRIPTOR pSD, PACL pACL); + /* --- IO stuff --- */ #define _MD_OPEN _PR_MD_OPEN +#define _MD_OPEN_FILE _PR_MD_OPEN_FILE #define _MD_READ _PR_MD_READ #define _MD_WRITE _PR_MD_WRITE #define _MD_WRITEV _PR_MD_WRITEV @@ -177,6 +191,7 @@ extern PRInt32 _MD_CloseFile(PRInt32 osfd); #define _MD_ACCESS _PR_MD_ACCESS #define _MD_DELETE _PR_MD_DELETE #define _MD_MKDIR _PR_MD_MKDIR +#define _MD_MAKE_DIR _PR_MD_MAKE_DIR #define _MD_RMDIR _PR_MD_RMDIR #define _MD_LOCKFILE _PR_MD_LOCKFILE #define _MD_TLOCKFILE _PR_MD_TLOCKFILE diff --git a/pr/include/md/_winnt.cfg b/pr/include/md/_winnt.cfg index e3348445..76147e01 100644 --- a/pr/include/md/_winnt.cfg +++ b/pr/include/md/_winnt.cfg @@ -31,6 +31,8 @@ #define WINNT #endif +#define PR_AF_INET6 23 /* same as AF_INET6 */ + #if defined(_M_IX86) || defined(_X86_) #define IS_LITTLE_ENDIAN 1 diff --git a/pr/include/md/_winnt.h b/pr/include/md/_winnt.h index 85ddd505..49756c2e 100644 --- a/pr/include/md/_winnt.h +++ b/pr/include/md/_winnt.h @@ -200,12 +200,26 @@ struct _MDProcess { /* --- Misc stuff --- */ #define _MD_GET_SP(thread) (thread)->md.gcContext[6] +/* --- NT security stuff --- */ + +extern void _PR_NT_InitSids(void); +extern void _PR_NT_FreeSids(void); +extern PRStatus _PR_NT_MakeSecurityDescriptorACL( + PRIntn mode, + DWORD accessTable[], + PSECURITY_DESCRIPTOR *resultSD, + PACL *resultACL +); +extern void _PR_NT_FreeSecurityDescriptorACL( + PSECURITY_DESCRIPTOR pSD, PACL pACL); + /* --- IO stuff --- */ extern PRInt32 _md_Associate(HANDLE); extern PRInt32 _PR_MD_CLOSE(PRInt32 osfd, PRBool socket); #define _MD_OPEN _PR_MD_OPEN +#define _MD_OPEN_FILE _PR_MD_OPEN_FILE #define _MD_READ _PR_MD_READ #define _MD_WRITE _PR_MD_WRITE #define _MD_WRITEV _PR_MD_WRITEV @@ -221,6 +235,7 @@ extern PRInt32 _PR_MD_CLOSE(PRInt32 osfd, PRBool socket); #define _MD_ACCESS _PR_MD_ACCESS #define _MD_DELETE _PR_MD_DELETE #define _MD_MKDIR _PR_MD_MKDIR +#define _MD_MAKE_DIR _PR_MD_MAKE_DIR #define _MD_RMDIR _PR_MD_RMDIR #define _MD_LOCKFILE _PR_MD_LOCKFILE #define _MD_TLOCKFILE _PR_MD_TLOCKFILE diff --git a/pr/include/nspr.h b/pr/include/nspr.h index 45bec0b3..1936b5c4 100644 --- a/pr/include/nspr.h +++ b/pr/include/nspr.h @@ -49,6 +49,8 @@ #include "prsystem.h" #include "prthread.h" #include "prtime.h" +#include "prtpool.h" +#include "prtrace.h" #include "prtypes.h" #endif /* nspr_h___ */ diff --git a/pr/include/obsolete/probslet.h b/pr/include/obsolete/probslet.h index 91efa45a..f62cb8d8 100644 --- a/pr/include/obsolete/probslet.h +++ b/pr/include/obsolete/probslet.h @@ -34,17 +34,6 @@ PR_BEGIN_EXTERN_C */ NSPR_API(PRStatus) PR_Yield(void); -/* -** These are obsolete and are replaced by PR_GetSocketOption() and -** PR_SetSocketOption(). -*/ - -NSPR_API(PRStatus) PR_GetSockOpt( - PRFileDesc *fd, PRSockOption optname, void* optval, PRInt32* optlen); - -NSPR_API(PRStatus) PR_SetSockOpt( - PRFileDesc *fd, PRSockOption optname, const void* optval, PRInt32 optlen); - /************************************************************************/ /************* The following definitions are for select *****************/ /************************************************************************/ @@ -160,64 +149,6 @@ NSPR_API(PRInt32) PR_FD_NISSET(PRInt32 osfd, PR_fd_set *set); NSPR_API(PRInt32) PR_Stat(const char *path, struct stat *buf); #endif /* NO_NSPR_10_SUPPORT */ -/*********************************************************************** -** FUNCTION: PR_CreateNetAddr(), PR_DestroyNetAddr() -** DESCRIPTION: -** Create an instance of a PRNetAddr, assigning well known values as -** appropriate. -** -** INPUTS -** PRNetAddrValue val The value to be assigned to the IP Address portion -** of the network address. This can only specify the -** special well known values that are equivalent to -** INADDR_ANY and INADDR_LOOPBACK. -** -** PRUInt16 port The port number to be assigned in the structure. -** -** OUTPUTS: -** None -** -** RETURN: -** PRNetAddr *addr The initialized address that has been allocated -** from the heap. It must be freed by the caller. -** A returned value of zero indicates an error. The -** cause of the error (most likely low memory) may -** be retrieved by calling PR_GetError(). -** -***********************************************************************/ -NSPR_API(PRNetAddr*) PR_CreateNetAddr(PRNetAddrValue val, PRUint16 port); -NSPR_API(PRStatus) PR_DestroyNetAddr(PRNetAddr *addr); - - - -/*********************************************************************** -** FUNCTION: PR_GetHostName() **OBSOLETE** -** Use PR_GetSystemInfo() (prsystem.h) with an argument of -** PR_SI_HOSTNAME instead. -** DESCRIPTION: -** Get the DNS name of the hosting computer. -** -** INPUTS: -** char *name The location where the host's name is stored. -** PRIntn bufsize Number of bytes in 'name'. -** OUTPUTS: -** PRHostEnt *name -** This string is filled in by the runtime if the -** function returns PR_SUCCESS. The string must be -** allocated by the caller -** RETURN: -** PRStatus PR_SUCCESS if the succeeds. If it fails the -** result will be PR_FAILURE and the reason for -** the failure can be retrieved by PR_GetError(). -***********************************************************************/ -NSPR_API(PRStatus) PR_GetHostName(char *name, PRUint32 namelen); - -/* -** Return the current thread's last error string. -** obsoleted by PR_GetErrorText(). -*/ -NSPR_API(const char *) PR_GetErrorString(void); - PR_END_EXTERN_C #endif /* defined(PROBSLET_H) */ diff --git a/pr/include/prerr.h b/pr/include/prerr.h index a2073435..a1fe2803 100644 --- a/pr/include/prerr.h +++ b/pr/include/prerr.h @@ -220,8 +220,8 @@ /* The file is busy */ #define PR_FILE_IS_BUSY_ERROR (-5936L) -/* Reserved Error Code -5935 */ -#define PR_RESERVED_ERROR_5935 (-5935L) +/* The I/O operation was aborted */ +#define PR_OPERATION_ABORTED_ERROR (-5935L) /* Operation is still in progress (probably a non-blocking connect) */ #define PR_IN_PROGRESS_ERROR (-5934L) diff --git a/pr/include/prinit.h b/pr/include/prinit.h index 65fdb3ff..500182c3 100644 --- a/pr/include/prinit.h +++ b/pr/include/prinit.h @@ -44,10 +44,9 @@ PR_BEGIN_EXTERN_C ** The format of the version string is ** "<major version>.<minor version> <build date>" */ -#define PR_VERSION "3.5" -#define PR_VMAJOR 3 -#define PR_VMAJOR_STR "3" -#define PR_VMINOR 5 +#define PR_VERSION "4.0" +#define PR_VMAJOR 4 +#define PR_VMINOR 0 #define PR_VPATCH 0 #define PR_BETA PR_FALSE diff --git a/pr/include/prio.h b/pr/include/prio.h index 75898729..36017128 100644 --- a/pr/include/prio.h +++ b/pr/include/prio.h @@ -104,9 +104,6 @@ typedef enum PRTransmitFileFlags { #define PR_AF_INET AF_INET #define PR_AF_LOCAL AF_UNIX -#ifdef AF_INET6 -#define PR_AF_INET6 AF_INET6 -#endif #define PR_INADDR_ANY INADDR_ANY #define PR_INADDR_LOOPBACK INADDR_LOOPBACK #define PR_INADDR_BROADCAST INADDR_BROADCAST @@ -114,6 +111,15 @@ typedef enum PRTransmitFileFlags { #endif /* WIN32 */ /* +** Define PR_AF_INET6 in prcpucfg.h with the same +** value as AF_INET6 on platforms with IPv6 support. +** Otherwise define it here. +*/ +#ifndef PR_AF_INET6 +#define PR_AF_INET6 100 +#endif + +/* ************************************************************************** ** A network address ** @@ -122,15 +128,21 @@ typedef enum PRTransmitFileFlags { ** or IPv6 (AF_INET6). ************************************************************************** *************************************************************************/ -#if defined(_PR_INET6) -#if !defined(AF_INET6) -#error "AF_INET6 is not defined" -#endif +struct PRIPv6Addr { + union { + PRUint8 _S6_u8[16]; + PRUint16 _S6_u16[8]; + PRUint32 _S6_u32[4]; + PRUint64 _S6_u64[2]; + } _S6_un; +}; +#define pr_s6_addr _S6_un._S6_u8 +#define pr_s6_addr16 _S6_un._S6_u16 +#define pr_s6_addr32 _S6_un._S6_u32 +#define pr_s6_addr64 _S6_un._S6_addr64 -typedef struct in6_addr PRIPv6Addr; - -#endif /* defined(_PR_INET6) */ +typedef struct PRIPv6Addr PRIPv6Addr; union PRNetAddr { struct { @@ -151,7 +163,6 @@ union PRNetAddr { char pad[8]; #endif } inet; -#if defined(_PR_INET6) struct { PRUint16 family; /* address family (AF_INET6) */ PRUint16 port; /* port number */ @@ -159,7 +170,6 @@ union PRNetAddr { PRIPv6Addr ip; /* the actual 128 bits of address */ PRUint32 scope_id; /* set of interfaces for a scope */ } ipv6; -#endif /* defined(_PR_INET6) */ #if defined(XP_UNIX) struct { /* Unix domain socket address */ PRUint16 family; /* address family (AF_UNIX) */ @@ -181,12 +191,17 @@ union PRNetAddr { #else #if defined(XP_UNIX) -#define PR_NETADDR_SIZE(_addr) \ - ((_addr)->raw.family == AF_UNIX \ - ? sizeof((_addr)->local) \ - : sizeof((_addr)->inet)) +#define PR_NETADDR_SIZE(_addr) \ + ((_addr)->raw.family == PR_AF_INET \ + ? sizeof((_addr)->inet) \ + : ((_addr)->raw.family == PR_AF_INET6 \ + ? sizeof((_addr)->ipv6) \ + : sizeof((_addr)->local))) #else -#define PR_NETADDR_SIZE(_addr) sizeof((_addr)->inet) +#define PR_NETADDR_SIZE(_addr) \ + ((_addr)->raw.family == PR_AF_INET \ + ? sizeof((_addr)->inet) \ + : sizeof((_addr)->ipv6)) #endif /* defined(XP_UNIX) */ #endif /* defined(_PR_INET6) */ @@ -351,10 +366,6 @@ typedef PRInt32 (PR_CALLBACK *PRTransmitfileFN)( PRInt32 hlen, PRTransmitFileFlags flags, PRIntervalTime t); typedef PRStatus (PR_CALLBACK *PRGetsocknameFN)(PRFileDesc *fd, PRNetAddr *addr); typedef PRStatus (PR_CALLBACK *PRGetpeernameFN)(PRFileDesc *fd, PRNetAddr *addr); -typedef PRStatus (PR_CALLBACK *PRGetsockoptFN)( /* OBSOLETE */ - PRFileDesc *fd, PRSockOption optname, void* optval, PRInt32 *optlen); -typedef PRStatus (PR_CALLBACK *PRSetsockoptFN)( /* OBSOLETE */ - PRFileDesc *fd, PRSockOption optname, const void* optval, PRInt32 optlen); typedef PRStatus (PR_CALLBACK *PRGetsocketoptionFN)( PRFileDesc *fd, PRSocketOptionData *data); typedef PRStatus (PR_CALLBACK *PRSetsocketoptionFN)( @@ -391,8 +402,8 @@ struct PRIOMethods { PRTransmitfileFN transmitfile; /* Transmit at entire file */ PRGetsocknameFN getsockname; /* Get (net) address associated with fd */ PRGetpeernameFN getpeername; /* Get peer's (net) address */ - PRGetsockoptFN getsockopt; /* OBSOLETE */ - PRSetsockoptFN setsockopt; /* OBSOLETE */ + PRReservedFN reserved_fn_6; /* reserved for future use */ + PRReservedFN reserved_fn_5; /* reserved for future use */ PRGetsocketoptionFN getsocketoption; /* Get current setting of specified option */ PRSetsocketoptionFN setsocketoption; @@ -574,7 +585,6 @@ NSPR_API(PRFileDesc*) PR_PopIOLayer(PRFileDesc *fd_stack, PRDescIdentity id); ************************************************************************** */ -NSPR_API(PRFileDesc*) PR_Open(const char *name, PRIntn flags, PRIntn mode); /* Open flags */ #define PR_RDONLY 0x01 #define PR_WRONLY 0x02 @@ -588,8 +598,8 @@ NSPR_API(PRFileDesc*) PR_Open(const char *name, PRIntn flags, PRIntn mode); /* ** File modes .... ** -** CAVEAT: 'mode' is currently only applicable on UNIX platforms. We are -** still in the process of seeing how these apply to other file systems. +** CAVEAT: 'mode' is currently only applicable on UNIX platforms. +** The 'mode' argument may be ignored by PR_Open on other platforms. ** ** 00400 Read by owner. ** 00200 Write by owner. @@ -603,6 +613,35 @@ NSPR_API(PRFileDesc*) PR_Open(const char *name, PRIntn flags, PRIntn mode); ** */ +NSPR_API(PRFileDesc*) PR_Open(const char *name, PRIntn flags, PRIntn mode); + +/* + ************************************************************************** + * FUNCTION: PR_OpenFile + * DESCRIPTION: + * Open a file for reading, writing, or both. + * PR_OpenFile has the same prototype as PR_Open but implements + * the specified file mode where possible. + ************************************************************************** + */ + +/* File mode bits */ +#define PR_IRWXU 00700 /* read, write, execute/search by owner */ +#define PR_IRUSR 00400 /* read permission, owner */ +#define PR_IWUSR 00200 /* write permission, owner */ +#define PR_IXUSR 00100 /* execute/search permission, owner */ +#define PR_IRWXG 00070 /* read, write, execute/search by group */ +#define PR_IRGRP 00040 /* read permission, group */ +#define PR_IWGRP 00020 /* write permission, group */ +#define PR_IXGRP 00010 /* execute/search permission, group */ +#define PR_IRWXO 00007 /* read, write, execute/search by others */ +#define PR_IROTH 00004 /* read permission, others */ +#define PR_IWOTH 00002 /* write permission, others */ +#define PR_IXOTH 00001 /* execute/search permission, others */ + +NSPR_API(PRFileDesc*) PR_OpenFile( + const char *name, PRIntn flags, PRIntn mode); + /* ************************************************************************** * FUNCTION: PR_Close @@ -1039,6 +1078,18 @@ NSPR_API(PRStatus) PR_MkDir(const char *name, PRIntn mode); /* ************************************************************************* + * FUNCTION: PR_MakeDir + * DESCRIPTION: + * Create a new directory with the given name and access mode. + * PR_MakeDir has the same prototype as PR_MkDir but implements + * the specified access mode where possible. + ************************************************************************* + */ + +NSPR_API(PRStatus) PR_MakeDir(const char *name, PRIntn mode); + +/* + ************************************************************************* * FUNCTION: PR_RmDir * DESCRIPTION: * Remove a directory by the given name. @@ -1529,7 +1580,8 @@ NSPR_API(PRInt32) PR_SendFile( ** void *buf ** A pointer to a buffer to receive data sent by the client. This ** buffer must be large enough to receive <amount> bytes of data -** and two PRNetAddr structures, plus an extra 32 bytes. +** and two PRNetAddr structures, plus an extra 32 bytes. See: +** PR_ACCEPT_READ_BUF_OVERHEAD. ** PRInt32 amount ** The number of bytes of client data to receive. Does not include ** the size of the PRNetAddr structures. If 0, no data will be read @@ -1552,7 +1604,16 @@ NSPR_API(PRInt32) PR_SendFile( ** The number of bytes read from the client or -1 on failure. The reason ** for the failure is obtained by calling PR_GetError(). ************************************************************************** -**/ +**/ +/* define buffer overhead constant. Add this value to the user's +** data length when allocating a buffer to accept data. +** Example: +** #define USER_DATA_SIZE 10 +** char buf[USER_DATA_SIZE + PR_ACCEPT_READ_BUF_OVERHEAD]; +** bytesRead = PR_AcceptRead( s, fd, &a, &p, USER_DATA_SIZE, ...); +*/ +#define PR_ACCEPT_READ_BUF_OVERHEAD (32+(2*sizeof(PRNetAddr))) + NSPR_API(PRInt32) PR_AcceptRead( PRFileDesc *listenSock, PRFileDesc **acceptedSock, PRNetAddr **peerAddr, void *buf, PRInt32 amount, PRIntervalTime timeout); diff --git a/pr/include/pripcsem.h b/pr/include/pripcsem.h index 4a75d68e..8b15ee96 100644 --- a/pr/include/pripcsem.h +++ b/pr/include/pripcsem.h @@ -38,6 +38,7 @@ #define pripcsem_h___ #include "prtypes.h" +#include "prio.h" PR_BEGIN_EXTERN_C diff --git a/pr/include/private/pprio.h b/pr/include/private/pprio.h index 78d2cefb..4c12af38 100644 --- a/pr/include/private/pprio.h +++ b/pr/include/private/pprio.h @@ -208,18 +208,6 @@ NSPR_API(void) PR_NTFast_UpdateAcceptContext(PRFileDesc *acceptSock, PRFileDesc *listenSock); -/* FUNCTION: PR_NT_UseNonblock -** DESCRIPTION: -** This function only works on NT. It tells nspr to use nonblocking io -** rather than async IO. There is no way to use some of each. This -** function should be called immediately after calling PR_Init(). -** -** WARNING: THIS FUNCTION IS A TEMPORARY HACK AND WILL BE REMOVED SHORTLY -** (LIKE ALL FUNCTIONS IN THE PRIVATE AREA). DO NOT USE THIS FUNCTION AT -** ALL WITHOUT CONTACTING mbelshe@netscape.com. -*/ -NSPR_API(void) PR_NT_UseNonblock(); - /* FUNCTION: PR_NT_CancelIo ** DESCRIPTION: ** Cancel IO operations on fd. diff --git a/pr/include/private/primpl.h b/pr/include/private/primpl.h index ad468d2c..926c2585 100644 --- a/pr/include/private/primpl.h +++ b/pr/include/private/primpl.h @@ -186,11 +186,6 @@ struct _PT_Notified typedef struct PTDebug { PRTime timeStarted; - PRUintn predictionsFoiled; - PRUintn pollingListMax; - PRUintn continuationsServed; - PRUintn recyclesNeeded; - PRUintn quiescentIO; PRUintn locks_created, locks_destroyed; PRUintn locks_acquired, locks_released; PRUintn cvars_created, cvars_destroyed; @@ -1035,6 +1030,9 @@ extern void _PR_MD_MAKE_NONBLOCK(PRFileDesc *fd); extern PRInt32 _PR_MD_OPEN(const char *name, PRIntn osflags, PRIntn mode); #define _PR_MD_OPEN _MD_OPEN +extern PRInt32 _PR_MD_OPEN_FILE(const char *name, PRIntn osflags, PRIntn mode); +#define _PR_MD_OPEN_FILE _MD_OPEN_FILE + extern PRInt32 _PR_MD_CLOSE_FILE(PRInt32 osfd); #define _PR_MD_CLOSE_FILE _MD_CLOSE_FILE @@ -1067,6 +1065,9 @@ extern PRInt32 _PR_MD_STAT(const char *name, struct stat *buf); extern PRInt32 _PR_MD_MKDIR(const char *name, PRIntn mode); #define _PR_MD_MKDIR _MD_MKDIR +extern PRInt32 _PR_MD_MAKE_DIR(const char *name, PRIntn mode); +#define _PR_MD_MAKE_DIR _MD_MAKE_DIR + extern PRInt32 _PR_MD_RMDIR(const char *name); #define _PR_MD_RMDIR _MD_RMDIR @@ -1421,9 +1422,7 @@ struct PRThread { #if defined(_PR_PTHREADS) pthread_t id; /* pthread identifier for the thread */ PRBool okToDelete; /* ok to delete the PRThread struct? */ - PRCondVar *io_cv; /* a condition used to run i/o */ PRCondVar *waiting; /* where the thread is waiting | NULL */ - PRIntn io_tq_index; /* the io-queue index for this thread */ void *sp; /* recorded sp for garbage collection */ PRThread *next, *prev; /* simple linked list of all threads */ PRUint32 suspend; /* used to store suspend and resume flags */ @@ -1549,36 +1548,8 @@ struct PRFilePrivate { PRFileDesc *next; PRIntn lockCount; _MDFileDesc md; -#ifdef _PR_PTHREADS - PRIntn eventMask[1]; /* An array of _pt_tq_count bitmasks. - * eventMask[i] is only accessed by - * the i-th i/o continuation thread. - * A 0 in a bitmask means the event - * should be igored in the revents - * bitmask returned by poll. - * - * poll's revents bitmask is a short, - * but we need to declare eventMask - * as an array of PRIntn's so that - * each bitmask can be updated - * individually without disturbing - * adjacent memory. Only the lower - * 16 bits of each PRIntn are used. */ -#endif -/* IMPORTANT: eventMask MUST BE THE LAST FIELD OF THIS STRUCTURE */ }; -/* - * The actual size of the PRFilePrivate structure, - * including the eventMask array at the end - */ -#ifdef _PR_PTHREADS -extern PRIntn _pt_tq_count; -#define PRFILEPRIVATE_SIZE (sizeof(PRFilePrivate) + (_pt_tq_count-1) * sizeof(PRIntn)) -#else -#define PRFILEPRIVATE_SIZE sizeof(PRFilePrivate) -#endif - struct PRDir { PRDirEntry d; _MDDir md; @@ -1674,10 +1645,6 @@ extern PRFileDesc *_pr_stdin; extern PRFileDesc *_pr_stdout; extern PRFileDesc *_pr_stderr; -#if defined(_PR_INET6) -extern PRBool _pr_ipv6_enabled; /* defined in prnetdb.c */ -#endif - /* Overriding malloc, free, etc. */ #if !defined(_PR_NO_PREEMPT) && defined(XP_UNIX) \ && !defined(_PR_PTHREADS) && !defined(_PR_GLOBAL_THREADS_ONLY) \ diff --git a/pr/include/prnetdb.h b/pr/include/prnetdb.h index f729c422..df17daf7 100644 --- a/pr/include/prnetdb.h +++ b/pr/include/prnetdb.h @@ -117,13 +117,11 @@ NSPR_API(PRStatus) PR_GetHostByName( ** for the failure can be retrieved by PR_GetError(). ***********************************************************************/ -/* - * #define PR_AI_ALL 0x08 - * #define PR_AI_V4MAPPED 0x10 - * #define PR_AI_ADDRCONFIG 0x20 - * #define PR_AI_DEFAULT (PR_AI_V4MAPPED | PR_AI_ADDRCONFIG) - */ -#define PR_AI_DEFAULT 0x30 + +#define PR_AI_ALL 0x08 +#define PR_AI_V4MAPPED 0x10 +#define PR_AI_ADDRCONFIG 0x20 +#define PR_AI_DEFAULT (PR_AI_V4MAPPED | PR_AI_ADDRCONFIG) NSPR_API(PRStatus) PR_GetIPNodeByName( const char *hostname, @@ -217,7 +215,8 @@ typedef enum PRNetAddrValue { PR_IpAddrNull, /* do NOT overwrite the IP address */ PR_IpAddrAny, /* assign logical INADDR_ANY to IP address */ - PR_IpAddrLoopback /* assign logical INADDR_LOOPBACK */ + PR_IpAddrLoopback, /* assign logical INADDR_LOOPBACK */ + PR_IpAddrV4Mapped /* IPv4 mapped address */ } PRNetAddrValue; NSPR_API(PRStatus) PR_InitializeNetAddr( @@ -267,6 +266,23 @@ NSPR_API(PRStatus) PR_SetNetAddr( NSPR_API(PRBool) PR_IsNetAddrType(const PRNetAddr *addr, PRNetAddrValue val); /*********************************************************************** +** FUNCTION: +** DESCRIPTION: PR_ConvertIPv4AddrToIPv6() +** Convert an IPv4 addr to an (IPv4-mapped) IPv6 addr +** +** INPUTS: +** PRUint32 v4addr IPv4 address +** +** OUTPUTS: +** PRIPv6Addr *v6addr The converted IPv6 address +** +** RETURN: +** void +** +***********************************************************************/ +NSPR_API(void) PR_ConvertIPv4AddrToIPv6(PRUint32 v4addr, PRIPv6Addr *v6addr); + +/*********************************************************************** ** MACRO: ** DESCRIPTION: PR_NetAddrFamily() ** Get the 'family' field of a PRNetAddr union. @@ -290,12 +306,8 @@ NSPR_API(PRBool) PR_IsNetAddrType(const PRNetAddr *addr, PRNetAddrValue val); ** RETURN: ** PRUint16 The 'port' field of 'addr'. ***********************************************************************/ -#ifdef _PR_INET6 #define PR_NetAddrInetPort(addr) \ ((addr)->raw.family == PR_AF_INET6 ? (addr)->ipv6.port : (addr)->inet.port) -#else -#define PR_NetAddrInetPort(addr) ((addr)->inet.port) -#endif /*********************************************************************** ** FUNCTION: @@ -358,28 +370,6 @@ NSPR_API(PRStatus) PR_GetProtoByNumber( PRInt32 protocolnumber, char* buffer, PRInt32 bufsize, PRProtoEnt* result); /*********************************************************************** -** FUNCTION: -** DESCRIPTION: PR_SetIPv6Enable() -** Enable IPv6 capability on a platform that supports the architecture. -** -** Note: IPv6 must first be enabled for the host platform. If it is not, -** the function will always return PR_FAILURE on any attempt to -** change the setting. -** -** INPUTS: -** PRBool itIs -** Assign it a value of PR_TRUE to turn on IPv6 -** addressing, PR_FALSE to turn it off. -** RETURN: -** PRStatus PR_SUCCESS if the IPv6 is enabled for this particular -** host. Otherwise it will return failure and GetError() -** will confirm the result by indicating that the -** protocol is not supported -** (PR_PROTOCOL_NOT_SUPPORTED_ERROR) -***********************************************************************/ -NSPR_API(PRStatus) PR_SetIPv6Enable(PRBool itIs); - -/*********************************************************************** ** FUNCTIONS: PR_ntohs, PR_ntohl, PR_ntohll, PR_htons, PR_htonl, PR_htonll ** ** DESCRIPTION: API entries for the common byte ordering routines. @@ -399,14 +389,6 @@ NSPR_API(PRUint16) PR_htons(PRUint16); NSPR_API(PRUint32) PR_htonl(PRUint32); NSPR_API(PRUint64) PR_htonll(PRUint64); -/*********************************************************************** -** FUNCTION: PR_FamilyInet -** -** DESCRIPTION: Routine to get value of address family for Internet Protocol -** -***********************************************************************/ -NSPR_API(PRUint16) PR_FamilyInet(void); - PR_END_EXTERN_C #endif /* prnetdb_h___ */ diff --git a/pr/include/prrng.h b/pr/include/prrng.h index fa248e77..c6ad1333 100644 --- a/pr/include/prrng.h +++ b/pr/include/prrng.h @@ -16,49 +16,10 @@ * Reserved. */ -/* -** Delete this section of the header after (if) agreement is reached to -** provide the service suggested here. Move some parts of it, if -** appropriate to platform specific implementation files. -** -** Proposal: Nothing in this header file should be construed as a -** commitment on the part of the NSPR team, Netsacpe/AOL/Sun Alliance -** et.al. to provide the API or function suggested in this header file. -** This is a proposal, a draft, yadda. ... So, don't count on it. -** lth. 29-Oct-1999 -** -** -------------------------------------------------------------------- -** -** Requirements, Discussion: -** -** Goal: foreach platform, find at least 160 bits of "good noise", that -** is: from the platform itself, not extrapolated, stired, hashed, -** xor'd, whatever, from a little available noise. -** -** -** Required on the following platforms: -** MAC, Win9x, WinNT, Solaris, Linux (k: 2.2.x). -** Best effort on: -** AIX, HP-UX. -** Not required on: -** Tru65 Unix (Compaq) -** -** Notes: -** -** I presume it is legal to put this function on Mozilla.org, -** that it is not regulated as "cryptographic 'munitions'". -** -** Cartman says they need it 15-Jan-2000. -** -** -------------------------------------------------------------------- -*/ /* ** prrng.h -- NSPR Random Number Generator ** -** -** -** ** ** lth. 29-Oct-1999. */ @@ -113,8 +74,7 @@ PR_BEGIN_EXTERN_C ** History: ** Parts of the model dependent implementation for PR_GetRandomNoise() ** were taken in whole or part from code previously in Netscape's NSS -** component. There is no Goddamned Goverenment Munitions is this -** code. Clinton: FOAD. +** component. ** */ NSPR_API(PRSize) PR_GetRandomNoise( diff --git a/pr/include/prshm.h b/pr/include/prshm.h index d16cfce1..ae28e014 100644 --- a/pr/include/prshm.h +++ b/pr/include/prshm.h @@ -113,6 +113,7 @@ #define prshm_h___ #include "prtypes.h" +#include "prio.h" PR_BEGIN_EXTERN_C diff --git a/pr/include/prtpool.h b/pr/include/prtpool.h index 82ce2663..838031fc 100644 --- a/pr/include/prtpool.h +++ b/pr/include/prtpool.h @@ -22,9 +22,14 @@ #include "prtypes.h" #include "prthread.h" #include "prio.h" -#include "prerr.h" #include "prerror.h" +/* + * NOTE: + * THIS API IS A PRELIMINARY VERSION IN NSPR 4.0 AND IS SUBJECT TO + * CHANGE + */ + PR_BEGIN_EXTERN_C typedef struct PRJobIoDesc { @@ -35,50 +40,55 @@ typedef struct PRJobIoDesc { typedef struct PRThreadPool PRThreadPool; typedef struct PRJob PRJob; -typedef void (PR_CALLBACK *JobFn) (void *arg); +typedef void (PR_CALLBACK *PRJobFn) (void *arg); /* Create thread pool */ -PR_EXTERN(PRThreadPool *) +NSPR_API(PRThreadPool *) PR_CreateThreadPool(PRInt32 initial_threads, PRInt32 max_threads, - PRSize stacksize); + PRUint32 stacksize); /* queue a job */ -PR_EXTERN(PRJob *) -PR_QueueJob(PRThreadPool *tpool, JobFn fn, void *arg, PRBool joinable); +NSPR_API(PRJob *) +PR_QueueJob(PRThreadPool *tpool, PRJobFn fn, void *arg, PRBool joinable); /* queue a job, when a socket is readable */ -PR_EXTERN(PRJob *) +NSPR_API(PRJob *) PR_QueueJob_Read(PRThreadPool *tpool, PRJobIoDesc *iod, - JobFn fn, void * arg, PRBool joinable); + PRJobFn fn, void * arg, PRBool joinable); /* queue a job, when a socket is writeable */ -PR_EXTERN(PRJob *) +NSPR_API(PRJob *) PR_QueueJob_Write(PRThreadPool *tpool, PRJobIoDesc *iod, - JobFn fn, void * arg, PRBool joinable); + PRJobFn fn, void * arg, PRBool joinable); /* queue a job, when a socket has a pending connection */ -PR_EXTERN(PRJob *) +NSPR_API(PRJob *) PR_QueueJob_Accept(PRThreadPool *tpool, PRJobIoDesc *iod, - JobFn fn, void * arg, PRBool joinable); + PRJobFn fn, void * arg, PRBool joinable); + +/* queue a job, when the socket connection to addr succeeds or fails */ +NSPR_API(PRJob *) +PR_QueueJob_Connect(PRThreadPool *tpool, PRJobIoDesc *iod, + const PRNetAddr *addr, PRJobFn fn, void * arg, PRBool joinable); /* queue a job, when a timer exipres */ -PR_EXTERN(PRJob *) +NSPR_API(PRJob *) PR_QueueJob_Timer(PRThreadPool *tpool, PRIntervalTime timeout, - JobFn fn, void * arg, PRBool joinable); + PRJobFn fn, void * arg, PRBool joinable); /* cancel a job */ -PR_EXTERN(PRStatus) +NSPR_API(PRStatus) PR_CancelJob(PRJob *job); /* join a job */ -PR_EXTERN(PRStatus) +NSPR_API(PRStatus) PR_JoinJob(PRJob *job); /* shutdown pool */ -PR_EXTERN(PRStatus) +NSPR_API(PRStatus) PR_ShutdownThreadPool(PRThreadPool *tpool); /* join pool, wait for exit of all threads */ -PR_EXTERN(PRStatus) +NSPR_API(PRStatus) PR_JoinThreadPool(PRThreadPool *tpool); PR_END_EXTERN_C diff --git a/pr/include/prtypes.h b/pr/include/prtypes.h index 6b866ed4..02ea6412 100644 --- a/pr/include/prtypes.h +++ b/pr/include/prtypes.h @@ -30,13 +30,6 @@ ** for all C files. **/ -/* the following update, a big '#if 0' for most of this file -** intentionally breaks the build of NSPR on the tip of the source tree -** nobody but NSPR should be interested in the tip right now -** anyway. -*/ -#if 0 - #ifndef prtypes_h___ #define prtypes_h___ @@ -484,4 +477,3 @@ PR_END_EXTERN_C #endif /* prtypes_h___ */ -#endif /* the #if 0 that intentionally breaks the tree */ diff --git a/pr/include/prvrsion.h b/pr/include/prvrsion.h index 7bd8d464..e5ad037f 100755 --- a/pr/include/prvrsion.h +++ b/pr/include/prvrsion.h @@ -74,9 +74,19 @@ typedef struct { /* * All components must define an entrypoint named libVersionPoint which * is of type versionEntryPointType. + * + * For example, for a library named libfoo, we would have: + * + * PRVersionDescription prVersionDescription_libfoo = + * { + * ... + * }; + * + * PR_IMPLEMENT(const PRVersionDescription*) libVersionPoint(void) + * { + * return &prVersionDescription_libfoo; + * } */ -NSPR_API(const PRVersionDescription *) libVersionPoint(void); - typedef const PRVersionDescription *(*versionEntryPointType)(void); /* diff --git a/pr/src/Makefile b/pr/src/Makefile index 808f98aa..9f584e48 100644 --- a/pr/src/Makefile +++ b/pr/src/Makefile @@ -141,7 +141,7 @@ endif ifeq ($(OS_ARCH),WINNT) ifneq ($(OS_TARGET),WIN16) -OS_LIBS = wsock32.lib winmm.lib +OS_LIBS = advapi32.lib wsock32.lib winmm.lib endif endif @@ -155,6 +155,7 @@ OBJS = \ io/$(OBJDIR)/prmwait.$(OBJ_SUFFIX) \ io/$(OBJDIR)/prmapopt.$(OBJ_SUFFIX) \ io/$(OBJDIR)/priometh.$(OBJ_SUFFIX) \ + io/$(OBJDIR)/pripv6.$(OBJ_SUFFIX) \ io/$(OBJDIR)/prlayer.$(OBJ_SUFFIX) \ io/$(OBJDIR)/prlog.$(OBJ_SUFFIX) \ io/$(OBJDIR)/prmmap.$(OBJ_SUFFIX) \ @@ -227,10 +228,6 @@ endif endif -ifeq ($(USE_IPV6), 1) -OBJS += io/$(OBJDIR)/pripv6.$(OBJ_SUFFIX) -endif - ifeq ($(USE_CPLUS), 1) OBJS += \ cplus/$(OBJDIR)/rcbase.$(OBJ_SUFFIX) \ @@ -289,6 +286,7 @@ OBJS += md/windows/$(OBJDIR)/w95io.$(OBJ_SUFFIX) \ md/windows/$(OBJDIR)/ntgc.$(OBJ_SUFFIX) \ md/windows/$(OBJDIR)/ntmisc.$(OBJ_SUFFIX) \ md/windows/$(OBJDIR)/ntinrval.$(OBJ_SUFFIX) \ + md/windows/$(OBJDIR)/ntsec.$(OBJ_SUFFIX) \ md/windows/$(OBJDIR)/ntsem.$(OBJ_SUFFIX) \ md/windows/$(OBJDIR)/win32_errors.$(OBJ_SUFFIX) \ md/windows/$(OBJDIR)/w32ipcsem.$(OBJ_SUFFIX) \ @@ -303,6 +301,7 @@ OBJS += md/windows/$(OBJDIR)/ntdllmn.$(OBJ_SUFFIX) \ md/windows/$(OBJDIR)/ntthread.$(OBJ_SUFFIX) \ md/windows/$(OBJDIR)/ntmisc.$(OBJ_SUFFIX) \ md/windows/$(OBJDIR)/ntinrval.$(OBJ_SUFFIX) \ + md/windows/$(OBJDIR)/ntsec.$(OBJ_SUFFIX) \ md/windows/$(OBJDIR)/ntsem.$(OBJ_SUFFIX) \ md/windows/$(OBJDIR)/win32_errors.$(OBJ_SUFFIX) \ md/windows/$(OBJDIR)/w32ipcsem.$(OBJ_SUFFIX) \ diff --git a/pr/src/Makefile.in b/pr/src/Makefile.in index de397356..bad88779 100644 --- a/pr/src/Makefile.in +++ b/pr/src/Makefile.in @@ -162,6 +162,7 @@ OBJS = \ io/$(OBJDIR)/prmwait.$(OBJ_SUFFIX) \ io/$(OBJDIR)/prmapopt.$(OBJ_SUFFIX) \ io/$(OBJDIR)/priometh.$(OBJ_SUFFIX) \ + io/$(OBJDIR)/pripv6.$(OBJ_SUFFIX) \ io/$(OBJDIR)/prlayer.$(OBJ_SUFFIX) \ io/$(OBJDIR)/prlog.$(OBJ_SUFFIX) \ io/$(OBJDIR)/prmmap.$(OBJ_SUFFIX) \ @@ -229,10 +230,6 @@ endif endif -ifeq ($(USE_IPV6), 1) -OBJS += io/$(OBJDIR)/pripv6.$(OBJ_SUFFIX) -endif - ifeq ($(USE_CPLUS), 1) OBJS += \ cplus/$(OBJDIR)/rcbase.$(OBJ_SUFFIX) \ diff --git a/pr/src/io/Makefile b/pr/src/io/Makefile index 692976e7..d9cc321b 100644 --- a/pr/src/io/Makefile +++ b/pr/src/io/Makefile @@ -32,6 +32,7 @@ CSRCS = \ prfdcach.c \ prmwait.c \ priometh.c \ + pripv6.c \ prmapopt.c \ prlayer.c \ prlog.c \ @@ -51,10 +52,6 @@ ifndef USE_PTHREADS $(NULL) endif -ifdef USE_IPV6 -CSRCS += pripv6.c -endif - TARGETS = $(OBJS) INCLUDES = -I$(DIST)/include -I$(MOD_DEPTH)/pr/include -I$(MOD_DEPTH)/pr/include/private diff --git a/pr/src/io/Makefile.in b/pr/src/io/Makefile.in index 40be6e7d..b4272a8a 100644 --- a/pr/src/io/Makefile.in +++ b/pr/src/io/Makefile.in @@ -37,6 +37,7 @@ CSRCS = \ prfdcach.c \ prmwait.c \ priometh.c \ + pripv6.c \ prmapopt.c \ prlayer.c \ prlog.c \ @@ -56,10 +57,6 @@ ifndef USE_PTHREADS $(NULL) endif -ifdef USE_IPV6 -CSRCS += pripv6.c -endif - TARGETS = $(OBJS) INCLUDES = -I$(DIST)/include -I$(topsrcdir)/pr/include -I$(topsrcdir)/pr/include/private diff --git a/pr/src/io/prdir.c b/pr/src/io/prdir.c index 0576aa9a..1d2b6958 100644 --- a/pr/src/io/prdir.c +++ b/pr/src/io/prdir.c @@ -70,6 +70,18 @@ PRInt32 rv; return PR_SUCCESS; } +PR_IMPLEMENT(PRStatus) PR_MakeDir(const char *name, PRIntn mode) +{ +PRInt32 rv; + + if (!_pr_initialized) _PR_ImplicitInitialization(); + rv = _PR_MD_MAKE_DIR(name, mode); + if (rv < 0) { + return PR_FAILURE; + } else + return PR_SUCCESS; +} + PR_IMPLEMENT(PRStatus) PR_RmDir(const char *name) { PRInt32 rv; diff --git a/pr/src/io/prfdcach.c b/pr/src/io/prfdcach.c index 6ad2e84c..00947d31 100644 --- a/pr/src/io/prfdcach.c +++ b/pr/src/io/prfdcach.c @@ -115,14 +115,14 @@ finished: fd->dtor = NULL; fd->lower = fd->higher = NULL; fd->identity = PR_NSPR_IO_LAYER; - memset(fd->secret, 0, PRFILEPRIVATE_SIZE); + memset(fd->secret, 0, sizeof(PRFilePrivate)); return fd; allocate: fd = PR_NEW(PRFileDesc); if (NULL != fd) { - fd->secret = (PRFilePrivate *) PR_MALLOC(PRFILEPRIVATE_SIZE); + fd->secret = PR_NEW(PRFilePrivate); if (NULL == fd->secret) PR_DELETE(fd); } if (NULL != fd) goto finished; diff --git a/pr/src/io/prfile.c b/pr/src/io/prfile.c index accc618b..3365df39 100644 --- a/pr/src/io/prfile.c +++ b/pr/src/io/prfile.c @@ -268,8 +268,8 @@ static PRIOMethods _pr_fileMethods = { (PRTransmitfileFN)_PR_InvalidInt, (PRGetsocknameFN)_PR_InvalidStatus, (PRGetpeernameFN)_PR_InvalidStatus, - (PRGetsockoptFN)_PR_InvalidStatus, - (PRSetsockoptFN)_PR_InvalidStatus, + (PRReservedFN)_PR_InvalidInt, + (PRReservedFN)_PR_InvalidInt, (PRGetsocketoptionFN)_PR_InvalidStatus, (PRSetsocketoptionFN)_PR_InvalidStatus, (PRSendfileFN)_PR_InvalidInt, @@ -312,8 +312,8 @@ static PRIOMethods _pr_pipeMethods = { (PRTransmitfileFN)_PR_InvalidInt, (PRGetsocknameFN)_PR_InvalidStatus, (PRGetpeernameFN)_PR_InvalidStatus, - (PRGetsockoptFN)_PR_InvalidStatus, - (PRSetsockoptFN)_PR_InvalidStatus, + (PRReservedFN)_PR_InvalidInt, + (PRReservedFN)_PR_InvalidInt, (PRGetsocketoptionFN)_PR_InvalidStatus, (PRSetsocketoptionFN)_PR_InvalidStatus, (PRSendfileFN)_PR_InvalidInt, @@ -348,6 +348,26 @@ PR_IMPLEMENT(PRFileDesc*) PR_Open(const char *name, PRIntn flags, PRIntn mode) return fd; } +PR_IMPLEMENT(PRFileDesc*) PR_OpenFile( + const char *name, PRIntn flags, PRIntn mode) +{ + PRInt32 osfd; + PRFileDesc *fd = 0; + + if (!_pr_initialized) _PR_ImplicitInitialization(); + + /* Map pr open flags and mode to os specific flags */ + + osfd = _PR_MD_OPEN_FILE(name, flags, mode); + if (osfd != -1) { + fd = PR_AllocFileDesc(osfd, &_pr_fileMethods); + if (!fd) { + (void) _PR_MD_CLOSE_FILE(osfd); + } + } + return fd; +} + PRInt32 PR_GetSysfdTableMax(void) { #if defined(XP_UNIX) && !defined(AIX) && !defined(NEXTSTEP) && !defined(QNX) diff --git a/pr/src/io/priometh.c b/pr/src/io/priometh.c index 0203d28b..b52990a7 100644 --- a/pr/src/io/priometh.c +++ b/pr/src/io/priometh.c @@ -48,8 +48,8 @@ PRIOMethods _pr_faulty_methods = { (PRTransmitfileFN)_PR_InvalidInt, (PRGetsocknameFN)_PR_InvalidStatus, (PRGetpeernameFN)_PR_InvalidStatus, - (PRGetsockoptFN)_PR_InvalidStatus, - (PRSetsockoptFN)_PR_InvalidStatus, + (PRReservedFN)_PR_InvalidInt, + (PRReservedFN)_PR_InvalidInt, (PRGetsocketoptionFN)_PR_InvalidStatus, (PRSetsocketoptionFN)_PR_InvalidStatus, (PRSendfileFN)_PR_InvalidInt, @@ -247,26 +247,6 @@ PR_IMPLEMENT(PRStatus) PR_GetPeerName(PRFileDesc *fd, PRNetAddr *addr) return((fd->methods->getpeername)(fd,addr)); } -PR_IMPLEMENT(PRStatus) PR_GetSockOpt( - PRFileDesc *fd, PRSockOption optname, void* optval, PRInt32* optlen) -{ -#if defined(DEBUG) - static PRBool warn = PR_TRUE; - if (warn) warn = _PR_Obsolete("PR_GetSockOpt()", "PR_GetSocketOption()"); -#endif - return((fd->methods->getsockopt)(fd, optname, optval, optlen)); -} - -PR_IMPLEMENT(PRStatus) PR_SetSockOpt( - PRFileDesc *fd, PRSockOption optname, const void* optval, PRInt32 optlen) -{ -#if defined(DEBUG) - static PRBool warn = PR_TRUE; - if (warn) warn = _PR_Obsolete("PR_SetSockOpt()", "PR_SetSocketOption()"); -#endif - return((fd->methods->setsockopt)(fd, optname, optval, optlen)); -} - PR_IMPLEMENT(PRStatus) PR_GetSocketOption( PRFileDesc *fd, PRSocketOptionData *data) { diff --git a/pr/src/io/pripv6.c b/pr/src/io/pripv6.c index 564648c0..485e449d 100644 --- a/pr/src/io/pripv6.c +++ b/pr/src/io/pripv6.c @@ -20,7 +20,341 @@ ** File: pripv6.c ** Description: Support for various functions unique to IPv6 */ +#include "primpl.h" +#include <string.h> +#if !defined(_PR_INET6) || defined(_PR_INET6_PROBE) -/* pripv6.c */ +static PRIOMethods ipv6_to_v4_tcpMethods; +static PRIOMethods ipv6_to_v4_udpMethods; +static PRDescIdentity _pr_ipv6_to_ipv4_id; +extern PRBool IsValidNetAddr(const PRNetAddr *addr); +extern PRIPv6Addr _pr_in6addr_any; +extern PRIPv6Addr _pr_in6addr_loopback; +/* + * convert an IPv4-mapped IPv6 addr to an IPv4 addr + */ +static void _PR_ConvertToIpv4NetAddr(const PRNetAddr *src_v6addr, + PRNetAddr *dst_v4addr) +{ +const PRUint8 *srcp; + + PR_ASSERT(PR_AF_INET6 == src_v6addr->ipv6.family); + + if (PR_IsNetAddrType(src_v6addr, PR_IpAddrV4Mapped)) { + srcp = src_v6addr->ipv6.ip.pr_s6_addr; + memcpy((char *) &dst_v4addr->inet.ip, srcp + 12, 4); + } else if (PR_IsNetAddrType(src_v6addr, PR_IpAddrAny)) { + dst_v4addr->inet.ip = htonl(INADDR_ANY); + } else if (PR_IsNetAddrType(src_v6addr, PR_IpAddrLoopback)) { + dst_v4addr->inet.ip = htonl(INADDR_LOOPBACK); + } + dst_v4addr->inet.family = PR_AF_INET; + dst_v4addr->inet.port = src_v6addr->ipv6.port; +} + +/* + * convert an IPv4 addr to an IPv4-mapped IPv6 addr + */ +static void _PR_ConvertToIpv6NetAddr(const PRNetAddr *src_v4addr, + PRNetAddr *dst_v6addr) +{ +PRUint8 *dstp; + + PR_ASSERT(PR_AF_INET == src_v4addr->inet.family); + dst_v6addr->ipv6.family = PR_AF_INET6; + dst_v6addr->ipv6.port = src_v4addr->inet.port; + + if (htonl(INADDR_ANY) == src_v4addr->inet.ip) { + dst_v6addr->ipv6.ip = _pr_in6addr_any; + } else { + dstp = dst_v6addr->ipv6.ip.pr_s6_addr; + memset(dstp, 0, 10); + memset(dstp + 10, 0xff, 2); + memcpy(dstp + 12,(char *) &src_v4addr->inet.ip, 4); + } +} + +static PRStatus PR_CALLBACK Ipv6ToIpv4SocketBind(PRFileDesc *fd, + const PRNetAddr *addr) +{ + PRNetAddr tmp_ipv4addr; + const PRNetAddr *tmp_addrp; + PRFileDesc *lo = fd->lower; + + if (PR_AF_INET6 != addr->raw.family) { + PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, 0); + return PR_FAILURE; + } + if (PR_IsNetAddrType(addr, PR_IpAddrV4Mapped) || + PR_IsNetAddrType(addr, PR_IpAddrAny)) { + _PR_ConvertToIpv4NetAddr(addr, &tmp_ipv4addr); + tmp_addrp = &tmp_ipv4addr; + } else { + PR_SetError(PR_NETWORK_UNREACHABLE_ERROR, 0); + return PR_FAILURE; + } + return((lo->methods->bind)(lo,tmp_addrp)); +} + +static PRStatus PR_CALLBACK Ipv6ToIpv4SocketConnect( + PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime timeout) +{ + PRNetAddr tmp_ipv4addr; + const PRNetAddr *tmp_addrp; + + if (PR_AF_INET6 != addr->raw.family) { + PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, 0); + return PR_FAILURE; + } + if (PR_IsNetAddrType(addr, PR_IpAddrV4Mapped) || + PR_IsNetAddrType(addr, PR_IpAddrLoopback)) { + _PR_ConvertToIpv4NetAddr(addr, &tmp_ipv4addr); + tmp_addrp = &tmp_ipv4addr; + } else { + PR_SetError(PR_NETWORK_UNREACHABLE_ERROR, 0); + return PR_FAILURE; + } + return (fd->lower->methods->connect)(fd->lower, tmp_addrp, timeout); +} + +static PRInt32 PR_CALLBACK Ipv6ToIpv4SocketSendTo( + PRFileDesc *fd, const void *buf, PRInt32 amount, + PRIntn flags, const PRNetAddr *addr, PRIntervalTime timeout) +{ + PRNetAddr tmp_ipv4addr; + const PRNetAddr *tmp_addrp; + + if (PR_AF_INET6 != addr->raw.family) { + PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, 0); + return PR_FAILURE; + } + if (PR_IsNetAddrType(addr, PR_IpAddrV4Mapped) || + PR_IsNetAddrType(addr, PR_IpAddrLoopback)) { + _PR_ConvertToIpv4NetAddr(addr, &tmp_ipv4addr); + tmp_addrp = &tmp_ipv4addr; + } else { + PR_SetError(PR_NETWORK_UNREACHABLE_ERROR, 0); + return PR_FAILURE; + } + return (fd->lower->methods->sendto)( + fd->lower, buf, amount, flags, tmp_addrp, timeout); +} + +static PRFileDesc* PR_CALLBACK Ipv6ToIpv4SocketAccept ( + PRFileDesc *fd, PRNetAddr *addr, PRIntervalTime timeout) +{ + PRStatus rv; + PRFileDesc *newfd; + PRFileDesc *newstack; + PRNetAddr tmp_ipv4addr; + + PR_ASSERT(fd != NULL); + PR_ASSERT(fd->lower != NULL); + + newstack = PR_NEW(PRFileDesc); + if (NULL == newstack) + { + PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); + return NULL; + } + *newstack = *fd; /* make a copy of the accepting layer */ + + newfd = (fd->lower->methods->accept)(fd->lower, &tmp_ipv4addr, timeout); + if (NULL == newfd) + { + PR_DELETE(newstack); + return NULL; + } + _PR_ConvertToIpv6NetAddr(&tmp_ipv4addr, addr); + + rv = PR_PushIOLayer(newfd, PR_TOP_IO_LAYER, newstack); + PR_ASSERT(PR_SUCCESS == rv); + return newfd; /* that's it */ +} + +static PRInt32 PR_CALLBACK Ipv6ToIpv4SocketAcceptRead(PRFileDesc *sd, + PRFileDesc **nd, PRNetAddr **ipv6_raddr, void *buf, PRInt32 amount, + PRIntervalTime timeout) +{ + PRInt32 nbytes; + PRStatus rv; + PRNetAddr tmp_ipv4addr; + PRFileDesc *newstack; + + PR_ASSERT(sd != NULL); + PR_ASSERT(sd->lower != NULL); + + newstack = PR_NEW(PRFileDesc); + if (NULL == newstack) + { + PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); + return -1; + } + *newstack = *sd; /* make a copy of the accepting layer */ + + nbytes = sd->lower->methods->acceptread( + sd->lower, nd, ipv6_raddr, buf, amount, timeout); + if (-1 == nbytes) + { + PR_DELETE(newstack); + return nbytes; + } + tmp_ipv4addr = **ipv6_raddr; /* copy */ + _PR_ConvertToIpv6NetAddr(&tmp_ipv4addr, *ipv6_raddr); + + /* this PR_PushIOLayer call cannot fail */ + rv = PR_PushIOLayer(*nd, PR_TOP_IO_LAYER, newstack); + PR_ASSERT(PR_SUCCESS == rv); + return nbytes; +} + +static PRStatus PR_CALLBACK Ipv6ToIpv4SocketGetName(PRFileDesc *fd, + PRNetAddr *ipv6addr) +{ + PRStatus result; + PRNetAddr tmp_ipv4addr; + + result = (fd->lower->methods->getsockname)(fd->lower, &tmp_ipv4addr); + if (PR_SUCCESS == result) { + _PR_ConvertToIpv6NetAddr(&tmp_ipv4addr, ipv6addr); + PR_ASSERT(IsValidNetAddr(ipv6addr) == PR_TRUE); + } + return result; +} + +static PRStatus PR_CALLBACK Ipv6ToIpv4SocketGetPeerName(PRFileDesc *fd, + PRNetAddr *ipv6addr) +{ + PRStatus result; + PRNetAddr tmp_ipv4addr; + + result = (fd->lower->methods->getsockname)(fd->lower, &tmp_ipv4addr); + if (PR_SUCCESS == result) { + _PR_ConvertToIpv6NetAddr(&tmp_ipv4addr, ipv6addr); + PR_ASSERT(IsValidNetAddr(ipv6addr) == PR_TRUE); + } + return result; +} + +static PRInt32 PR_CALLBACK Ipv6ToIpv4SocketRecvFrom(PRFileDesc *fd, void *buf, + PRInt32 amount, PRIntn flags, PRNetAddr *ipv6addr, + PRIntervalTime timeout) +{ + PRNetAddr tmp_ipv4addr; + PRInt32 result; + + result = (fd->lower->methods->recvfrom)( + fd->lower, buf, amount, flags, &tmp_ipv4addr, timeout); + if (-1 != result) { + _PR_ConvertToIpv6NetAddr(&tmp_ipv4addr, ipv6addr); + PR_ASSERT(IsValidNetAddr(ipv6addr) == PR_TRUE); + } + return result; +} + +#if defined(_PR_INET6_PROBE) +PRBool _pr_ipv6_is_present; +PR_EXTERN(PRBool) _pr_test_ipv6_socket(); +#if defined(_PR_HAVE_GETIPNODEBYNAME) +void *_pr_getipnodebyname_fp; +void *_pr_getipnodebyaddr_fp; +void *_pr_freehostent_fp; +#endif +#endif + +PRStatus _pr_init_ipv6() +{ + const PRIOMethods *stubMethods; + +#if defined(_PR_INET6_PROBE) + +#if !defined(_PR_INET6) && defined(_PR_HAVE_GETIPNODEBYNAME) + PRLibrary *lib; + _pr_getipnodebyname_fp = PR_FindSymbolAndLibrary("getipnodebyname", &lib); + if (NULL != _pr_getipnodebyname_fp) { + _pr_freehostent_fp = PR_FindSymbol(lib, "freehostent"); + if (NULL != _pr_freehostent_fp) { + _pr_getipnodebyaddr_fp = PR_FindSymbol(lib, "getipnodebyaddr"); + if (NULL != _pr_getipnodebyaddr_fp) + _pr_ipv6_is_present = PR_TRUE; + else + _pr_ipv6_is_present = PR_FALSE; + } else + _pr_ipv6_is_present = PR_FALSE; + (void)PR_UnloadLibrary(lib); + } else + _pr_ipv6_is_present = PR_FALSE; + if (PR_TRUE == _pr_ipv6_is_present) +#endif + + _pr_ipv6_is_present = _pr_test_ipv6_socket(); + if (PR_TRUE == _pr_ipv6_is_present) + return PR_SUCCESS; +#endif + + _pr_ipv6_to_ipv4_id = PR_GetUniqueIdentity("Ipv6_to_Ipv4 layer"); + PR_ASSERT(PR_INVALID_IO_LAYER != _pr_ipv6_to_ipv4_id); + + stubMethods = PR_GetDefaultIOMethods(); + + ipv6_to_v4_tcpMethods = *stubMethods; /* first get the entire batch */ + /* then override the ones we care about */ + ipv6_to_v4_tcpMethods.connect = Ipv6ToIpv4SocketConnect; + ipv6_to_v4_tcpMethods.bind = Ipv6ToIpv4SocketBind; + ipv6_to_v4_tcpMethods.accept = Ipv6ToIpv4SocketAccept; + ipv6_to_v4_tcpMethods.acceptread = Ipv6ToIpv4SocketAcceptRead; + ipv6_to_v4_tcpMethods.getsockname = Ipv6ToIpv4SocketGetName; + ipv6_to_v4_tcpMethods.getpeername = Ipv6ToIpv4SocketGetPeerName; +/* + ipv6_to_v4_tcpMethods.getsocketoption = Ipv6ToIpv4GetSocketOption; + ipv6_to_v4_tcpMethods.setsocketoption = Ipv6ToIpv4SetSocketOption; +*/ + ipv6_to_v4_udpMethods = *stubMethods; /* first get the entire batch */ + /* then override the ones we care about */ + ipv6_to_v4_udpMethods.connect = Ipv6ToIpv4SocketConnect; + ipv6_to_v4_udpMethods.bind = Ipv6ToIpv4SocketBind; + ipv6_to_v4_udpMethods.sendto = Ipv6ToIpv4SocketSendTo; + ipv6_to_v4_udpMethods.recvfrom = Ipv6ToIpv4SocketRecvFrom; + ipv6_to_v4_tcpMethods.getsockname = Ipv6ToIpv4SocketGetName; + ipv6_to_v4_tcpMethods.getpeername = Ipv6ToIpv4SocketGetPeerName; +/* + ipv6_to_v4_tcpMethods.getsocketoption = Ipv6ToIpv4GetSocketOption; + ipv6_to_v4_tcpMethods.setsocketoption = Ipv6ToIpv4SetSocketOption; +*/ + return PR_SUCCESS; +} + +PR_IMPLEMENT(PRStatus) _pr_push_ipv6toipv4_layer(PRFileDesc *fd) +{ + PRFileDesc *ipv6_fd = NULL; + + /* + * For platforms with no support for IPv6 + * create layered socket for IPv4-mapped IPv6 addresses + */ + if (fd->methods->file_type == PR_DESC_SOCKET_TCP) + ipv6_fd = PR_CreateIOLayerStub(_pr_ipv6_to_ipv4_id, + &ipv6_to_v4_tcpMethods); + else + ipv6_fd = PR_CreateIOLayerStub(_pr_ipv6_to_ipv4_id, + &ipv6_to_v4_udpMethods); + if (NULL == ipv6_fd) { + goto errorExit; + } + ipv6_fd->secret = NULL; + + if (PR_PushIOLayer(fd, PR_TOP_IO_LAYER, ipv6_fd) == PR_FAILURE) { + goto errorExit; + } + + return PR_SUCCESS; +errorExit: + + if (ipv6_fd) + ipv6_fd->dtor(ipv6_fd); + return PR_FAILURE; +} + +#endif /* !defined(_PR_INET6) || defined(_PR_INET6_PROBE) */ diff --git a/pr/src/io/prlayer.c b/pr/src/io/prlayer.c index 39a5d694..541b9be4 100644 --- a/pr/src/io/prlayer.c +++ b/pr/src/io/prlayer.c @@ -319,24 +319,6 @@ static PRStatus PR_CALLBACK pl_DefGetpeername (PRFileDesc *fd, PRNetAddr *addr) return (fd->lower->methods->getpeername)(fd->lower, addr); } -static PRStatus PR_CALLBACK pl_DefGetsockopt ( - PRFileDesc *fd, PRSockOption optname, void* optval, PRInt32* optlen) -{ - PR_ASSERT(fd != NULL); - PR_ASSERT(fd->lower != NULL); - - return (fd->lower->methods->getsockopt)(fd->lower, optname, optval, optlen); -} - -static PRStatus PR_CALLBACK pl_DefSetsockopt ( - PRFileDesc *fd, PRSockOption optname, const void* optval, PRInt32 optlen) -{ - PR_ASSERT(fd != NULL); - PR_ASSERT(fd->lower != NULL); - - return (fd->lower->methods->setsockopt)(fd->lower, optname, optval, optlen); -} - static PRStatus PR_CALLBACK pl_DefGetsocketoption ( PRFileDesc *fd, PRSocketOptionData *data) { @@ -394,8 +376,8 @@ static PRIOMethods pl_methods = { pl_DefTransmitfile, pl_DefGetsockname, pl_DefGetpeername, - pl_DefGetsockopt, - pl_DefSetsockopt, + (PRReservedFN)_PR_InvalidInt, + (PRReservedFN)_PR_InvalidInt, pl_DefGetsocketoption, pl_DefSetsocketoption, pl_DefSendfile, diff --git a/pr/src/io/prpolevt.c b/pr/src/io/prpolevt.c index 3e26f226..0369ae7c 100644 --- a/pr/src/io/prpolevt.c +++ b/pr/src/io/prpolevt.c @@ -169,8 +169,8 @@ static PRIOMethods _pr_polevt_methods = { (PRTransmitfileFN)_PR_InvalidInt, (PRGetsocknameFN)_PR_InvalidStatus, (PRGetpeernameFN)_PR_InvalidStatus, - (PRGetsockoptFN)_PR_InvalidStatus, - (PRSetsockoptFN)_PR_InvalidStatus, + (PRReservedFN)_PR_InvalidInt, + (PRReservedFN)_PR_InvalidInt, (PRGetsocketoptionFN)_PR_InvalidStatus, (PRSetsocketoptionFN)_PR_InvalidStatus, (PRSendfileFN)_PR_InvalidInt, diff --git a/pr/src/io/prsocket.c b/pr/src/io/prsocket.c index 69c61bb2..4ee568fd 100644 --- a/pr/src/io/prsocket.c +++ b/pr/src/io/prsocket.c @@ -25,16 +25,14 @@ /* These two functions are only used in assertions. */ #if defined(DEBUG) -static PRBool IsValidNetAddr(const PRNetAddr *addr) +PRBool IsValidNetAddr(const PRNetAddr *addr) { if ((addr != NULL) #ifdef XP_UNIX - && (addr->raw.family != AF_UNIX) + && (addr->raw.family != PR_AF_LOCAL) #endif -#ifdef _PR_INET6 - && (addr->raw.family != AF_INET6) -#endif - && (addr->raw.family != AF_INET)) { + && (addr->raw.family != PR_AF_INET6) + && (addr->raw.family != PR_AF_INET)) { return PR_FALSE; } return PR_TRUE; @@ -228,6 +226,10 @@ static PRStatus PR_CALLBACK SocketConnect( PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime timeout) { PRInt32 rv; /* Return value of _PR_MD_CONNECT */ + const PRNetAddr *addrp = addr; +#if defined(_PR_INET6) + PRNetAddr addrCopy; +#endif PRThread *me = _PR_MD_CURRENT_THREAD(); if (_PR_PENDING_INTERRUPT(me)) { @@ -235,8 +237,15 @@ static PRStatus PR_CALLBACK SocketConnect( PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); return PR_FAILURE; } +#if defined(_PR_INET6) + if (addr->raw.family == PR_AF_INET6) { + addrCopy = *addr; + addrCopy.raw.family = AF_INET6; + addrp = &addrCopy; + } +#endif - rv = _PR_MD_CONNECT(fd, addr, PR_NETADDR_SIZE(addr), timeout); + rv = _PR_MD_CONNECT(fd, addrp, PR_NETADDR_SIZE(addr), timeout); PR_LOG(_pr_io_lm, PR_LOG_MAX, ("connect -> %d", rv)); if (rv == 0) return PR_SUCCESS; @@ -414,6 +423,10 @@ PRIntervalTime timeout) _PR_MD_MAKE_NONBLOCK(fd2); #endif +#ifdef _PR_INET6 + if (addr && (AF_INET6 == addr->raw.family)) + addr->raw.family = PR_AF_INET6; +#endif PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE); PR_ASSERT(IsValidNetAddrLen(addr, al) == PR_TRUE); @@ -458,6 +471,10 @@ PRIntervalTime timeout) PR_ASSERT(al == PR_NETADDR_SIZE(addr)); fd2->secret->md.accepted_socket = PR_TRUE; memcpy(&fd2->secret->md.peer_addr, addr, al); +#ifdef _PR_INET6 + if (AF_INET6 == addr->raw.family) + addr->raw.family = PR_AF_INET6; +#endif } return fd2; } @@ -467,6 +484,10 @@ PRIntervalTime timeout) static PRStatus PR_CALLBACK SocketBind(PRFileDesc *fd, const PRNetAddr *addr) { PRInt32 result; + const PRNetAddr *addrp = addr; +#if defined(_PR_INET6) + PRNetAddr addrCopy; +#endif PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE); @@ -480,7 +501,14 @@ static PRStatus PR_CALLBACK SocketBind(PRFileDesc *fd, const PRNetAddr *addr) } #endif /* XP_UNIX */ - result = _PR_MD_BIND(fd, addr, PR_NETADDR_SIZE(addr)); +#if defined(_PR_INET6) + if (addr->raw.family == PR_AF_INET6) { + addrCopy = *addr; + addrCopy.raw.family = AF_INET6; + addrp = &addrCopy; + } +#endif + result = _PR_MD_BIND(fd, addrp, PR_NETADDR_SIZE(addr)); if (result < 0) { return PR_FAILURE; } @@ -630,6 +658,10 @@ static PRInt32 PR_CALLBACK SocketSendTo( PRIntn flags, const PRNetAddr *addr, PRIntervalTime timeout) { PRInt32 temp, count; + const PRNetAddr *addrp = addr; +#if defined(_PR_INET6) + PRNetAddr addrCopy; +#endif PRThread *me = _PR_MD_CURRENT_THREAD(); if (_PR_PENDING_INTERRUPT(me)) { @@ -643,11 +675,18 @@ static PRInt32 PR_CALLBACK SocketSendTo( } PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE); +#if defined(_PR_INET6) + if (addr->raw.family == PR_AF_INET6) { + addrCopy = *addr; + addrCopy.raw.family = AF_INET6; + addrp = &addrCopy; + } +#endif count = 0; while (amount > 0) { temp = _PR_MD_SENDTO(fd, buf, amount, flags, - addr, PR_NETADDR_SIZE(addr), timeout); + addrp, PR_NETADDR_SIZE(addr), timeout); if (temp < 0) { count = -1; break; @@ -681,6 +720,10 @@ PRIntn flags, PRNetAddr *addr, PRIntervalTime timeout) al = sizeof(PRNetAddr); rv = _PR_MD_RECVFROM(fd, buf, amount, flags, addr, &al, timeout); +#ifdef _PR_INET6 + if (addr && (AF_INET6 == addr->raw.family)) + addr->raw.family = PR_AF_INET6; +#endif return rv; } @@ -730,6 +773,10 @@ PRIntervalTime timeout) (*nd)->secret->md.accepted_socket = PR_TRUE; memcpy(&(*nd)->secret->md.peer_addr, *raddr, PR_NETADDR_SIZE(*raddr)); +#ifdef _PR_INET6 + if (AF_INET6 == *raddr->raw.family) + *raddr->raw.family = PR_AF_INET6; +#endif } } } @@ -779,6 +826,10 @@ PRIntervalTime timeout) (*nd)->secret->md.accepted_socket = PR_TRUE; memcpy(&(*nd)->secret->md.peer_addr, *raddr, PR_NETADDR_SIZE(*raddr)); +#ifdef _PR_INET6 + if (AF_INET6 == *raddr->raw.family) + *raddr->raw.family = PR_AF_INET6; +#endif } } return rv; @@ -826,6 +877,10 @@ void *callbackArg) (*nd)->secret->md.accepted_socket = PR_TRUE; memcpy(&(*nd)->secret->md.peer_addr, *raddr, PR_NETADDR_SIZE(*raddr)); +#ifdef _PR_INET6 + if (AF_INET6 == *raddr->raw.family) + *raddr->raw.family = PR_AF_INET6; +#endif } } return rv; @@ -910,6 +965,10 @@ static PRStatus PR_CALLBACK SocketGetName(PRFileDesc *fd, PRNetAddr *addr) if (result < 0) { return PR_FAILURE; } +#ifdef _PR_INET6 + if (AF_INET6 == addr->raw.family) + addr->raw.family = PR_AF_INET6; +#endif PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE); PR_ASSERT(IsValidNetAddrLen(addr, addrlen) == PR_TRUE); return PR_SUCCESS; @@ -925,121 +984,15 @@ static PRStatus PR_CALLBACK SocketGetPeerName(PRFileDesc *fd, PRNetAddr *addr) if (result < 0) { return PR_FAILURE; } +#ifdef _PR_INET6 + if (AF_INET6 == addr->raw.family) + addr->raw.family = PR_AF_INET6; +#endif PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE); PR_ASSERT(IsValidNetAddrLen(addr, addrlen) == PR_TRUE); return PR_SUCCESS; } -static PRStatus PR_CALLBACK SocketGetSockOpt( - PRFileDesc *fd, PRSockOption optname, void* optval, PRInt32* optlen) -{ - PRInt32 level, name; - PRStatus rv; - - /* - * PR_SockOpt_Nonblocking is a special case that does not - * translate to a getsockopt() call - */ - if (PR_SockOpt_Nonblocking == optname) - { - PR_ASSERT(sizeof(PRIntn) <= *optlen); - *((PRIntn *) optval) = (PRIntn) fd->secret->nonblocking; - *optlen = sizeof(PRIntn); - return PR_SUCCESS; - } - - rv = _PR_MapOptionName(optname, &level, &name); - if (PR_SUCCESS == rv) - { - if (PR_SockOpt_Linger == optname) - { -#if !defined(XP_BEOS) - struct linger linger; - PRInt32 len = sizeof(linger); - rv = _PR_MD_GETSOCKOPT( - fd, level, name, (char *) &linger, &len); - if (PR_SUCCESS == rv) - { - ((PRLinger*)(optval))->polarity = linger.l_onoff - ? PR_TRUE : PR_FALSE; - ((PRLinger*)(optval))->linger = PR_SecondsToInterval( - linger.l_linger); - *optlen = sizeof(PRLinger); - } -#else - PR_SetError( PR_NOT_IMPLEMENTED_ERROR, 0 ); - return PR_FAILURE; -#endif - } - else - { - rv = _PR_MD_GETSOCKOPT( - fd, level, name, (char*)optval, optlen); - } - } - return rv; -} - -static PRStatus PR_CALLBACK SocketSetSockOpt( - PRFileDesc *fd, PRSockOption optname, const void* optval, PRInt32 optlen) -{ - PRInt32 level, name; - PRStatus rv; - - /* - * PR_SockOpt_Nonblocking is a special case that does not - * translate to a setsockopt call. - */ - if (PR_SockOpt_Nonblocking == optname) - { - PRBool fNonblocking = *((PRIntn *) optval) ? PR_TRUE : PR_FALSE; - PR_ASSERT(sizeof(PRIntn) == optlen); -#ifdef WINNT - PR_ASSERT((fd->secret->md.io_model_committed == PR_FALSE) - || (fd->secret->nonblocking == fNonblocking)); - if (fd->secret->md.io_model_committed - && (fd->secret->nonblocking != fNonblocking)) - { - /* - * On NT, once we have associated a socket with the io - * completion port, we can't disassociate it. So we - * can't change the nonblocking option of the socket - * afterwards. - */ - PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); - return PR_FAILURE; - } -#endif - fd->secret->nonblocking = fNonblocking; - return PR_SUCCESS; - } - - rv = _PR_MapOptionName(optname, &level, &name); - if (PR_SUCCESS == rv) - { - if (PR_SockOpt_Linger == optname) - { -#if !defined(XP_BEOS) - struct linger linger; - linger.l_onoff = ((PRLinger*)(optval))->polarity ? 1 : 0; - linger.l_linger = PR_IntervalToSeconds( - ((PRLinger*)(optval))->linger); - rv = _PR_MD_SETSOCKOPT( - fd, level, name, (char *) &linger, sizeof(linger)); -#else - PR_SetError( PR_NOT_IMPLEMENTED_ERROR, 0 ); - return PR_FAILURE; -#endif - } - else - { - rv = _PR_MD_SETSOCKOPT( - fd, level, name, (const char*)optval, optlen); - } - } - return rv; -} - static PRInt16 PR_CALLBACK SocketPoll( PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags) { @@ -1077,8 +1030,8 @@ static PRIOMethods tcpMethods = { SocketTransmitFile, SocketGetName, SocketGetPeerName, - SocketGetSockOpt, - SocketSetSockOpt, + (PRReservedFN)_PR_InvalidInt, + (PRReservedFN)_PR_InvalidInt, _PR_SocketGetSocketOption, _PR_SocketSetSocketOption, SocketSendFile, @@ -1116,8 +1069,8 @@ static PRIOMethods udpMethods = { (PRTransmitfileFN)_PR_InvalidInt, SocketGetName, SocketGetPeerName, - SocketGetSockOpt, - SocketSetSockOpt, + (PRReservedFN)_PR_InvalidInt, + (PRReservedFN)_PR_InvalidInt, _PR_SocketGetSocketOption, _PR_SocketSetSocketOption, (PRSendfileFN)_PR_InvalidInt, @@ -1156,8 +1109,8 @@ static PRIOMethods socketpollfdMethods = { (PRTransmitfileFN)_PR_InvalidInt, (PRGetsocknameFN)_PR_InvalidStatus, (PRGetpeernameFN)_PR_InvalidStatus, - (PRGetsockoptFN)_PR_InvalidStatus, - (PRSetsockoptFN)_PR_InvalidStatus, + (PRReservedFN)_PR_InvalidInt, + (PRReservedFN)_PR_InvalidInt, (PRGetsocketoptionFN)_PR_InvalidStatus, (PRSetsocketoptionFN)_PR_InvalidStatus, (PRSendfileFN)_PR_InvalidInt, @@ -1183,24 +1136,65 @@ static const PRIOMethods* PR_GetSocketPollFdMethods() return &socketpollfdMethods; } /* PR_GetSocketPollFdMethods */ +#if !defined(_PR_INET6) || defined(_PR_INET6_PROBE) +PR_EXTERN(PRStatus) _pr_push_ipv6toipv4_layer(PRFileDesc *fd); + +#if defined(_PR_INET6_PROBE) + +PR_EXTERN(PRBool) _pr_ipv6_is_present; + +PR_IMPLEMENT(PRBool) _pr_test_ipv6_socket() +{ +PRInt32 osfd; + + osfd = _PR_MD_SOCKET(AF_INET6, SOCK_STREAM, 0); + if (osfd != -1) { + _PR_MD_CLOSE_SOCKET(osfd); + return PR_TRUE; + } + return PR_FALSE; +} +#endif /* _PR_INET6_PROBE */ + +#endif PR_IMPLEMENT(PRFileDesc*) PR_Socket(PRInt32 domain, PRInt32 type, PRInt32 proto) { PRInt32 osfd; PRFileDesc *fd; + PRInt32 tmp_domain = domain; if (!_pr_initialized) _PR_ImplicitInitialization(); - if (AF_INET != domain -#if defined(_PR_INET6) - && AF_INET6 != domain -#endif + if (PR_AF_INET != domain + && PR_AF_INET6 != domain #if defined(XP_UNIX) - && AF_UNIX != domain + && PR_AF_LOCAL != domain #endif ) { PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, 0); return NULL; } + +#if defined(_PR_INET6) + if (PR_AF_INET6 == domain) { +#if defined(_PR_INET6_PROBE) + if (_pr_ipv6_is_present == PR_FALSE) + domain = AF_INET; + else +#endif + domain = AF_INET6; + } +#elif defined(_PR_INET6_PROBE) + if (PR_AF_INET6 == domain) { + if (_pr_ipv6_is_present == PR_FALSE) + domain = AF_INET; + else + domain = AF_INET6; + } +#else + if (PR_AF_INET6 == domain) + domain = AF_INET; +#endif /* _PR_INET6 */ osfd = _PR_MD_SOCKET(domain, type, proto); if (osfd == -1) { return 0; @@ -1212,10 +1206,23 @@ PR_IMPLEMENT(PRFileDesc*) PR_Socket(PRInt32 domain, PRInt32 type, PRInt32 proto) /* * Make the sockets non-blocking */ - if (fd != NULL) + if (fd != NULL) { _PR_MD_MAKE_NONBLOCK(fd); - else +#if !defined(_PR_INET6) || defined(_PR_INET6_PROBE) + /* + * For platforms with no support for IPv6 + * create layered socket for IPv4-mapped IPv6 addresses + */ + if (PR_AF_INET6 == tmp_domain && PR_AF_INET == domain) { + if (PR_FAILURE == _pr_push_ipv6toipv4_layer(fd)) { + PR_Close(fd); + fd = NULL; + } + } +#endif + } else _PR_MD_CLOSE_SOCKET(osfd); + return fd; } @@ -1223,11 +1230,6 @@ PR_IMPLEMENT(PRFileDesc *) PR_NewTCPSocket(void) { PRInt32 domain = AF_INET; -#if defined(_PR_INET6) - if (_pr_ipv6_enabled) { - domain = AF_INET6; - } -#endif return PR_Socket(domain, SOCK_STREAM, 0); } @@ -1235,11 +1237,6 @@ PR_IMPLEMENT(PRFileDesc*) PR_NewUDPSocket(void) { PRInt32 domain = AF_INET; -#if defined(_PR_INET6) - if (_pr_ipv6_enabled) { - domain = AF_INET6; - } -#endif return PR_Socket(domain, SOCK_DGRAM, 0); } diff --git a/pr/src/linking/prlink.c b/pr/src/linking/prlink.c index e80ac10c..e4d093f1 100644 --- a/pr/src/linking/prlink.c +++ b/pr/src/linking/prlink.c @@ -260,6 +260,7 @@ PR_IMPLEMENT(PRStatus) PR_SetLibraryPath(const char *path) { PRStatus rv = PR_SUCCESS; + if (!_pr_initialized) _PR_ImplicitInitialization(); PR_EnterMonitor(pr_linker_lock); PR_FREEIF(_pr_currentLibPath); if (path) { @@ -284,6 +285,7 @@ PR_GetLibraryPath() char *ev; char *copy = NULL; /* a copy of _pr_currentLibPath */ + if (!_pr_initialized) _PR_ImplicitInitialization(); PR_EnterMonitor(pr_linker_lock); if (_pr_currentLibPath != NULL) { goto exit; @@ -797,6 +799,7 @@ PR_FindLibrary(const char *name) { PRLibrary* result; + if (!_pr_initialized) _PR_ImplicitInitialization(); PR_EnterMonitor(pr_linker_lock); result = pr_UnlockedFindLibrary(name); PR_ExitMonitor(pr_linker_lock); @@ -1143,6 +1146,7 @@ PR_FindSymbolAndLibrary(const char *raw_name, PRLibrary* *lib) #endif PRLibrary* lm; + if (!_pr_initialized) _PR_ImplicitInitialization(); /* ** Mangle the raw symbol name in any way that is platform specific. */ diff --git a/pr/src/md/mac/macsocket.h b/pr/src/md/mac/macsocket.h index 9c4612d2..4c307b55 100644 --- a/pr/src/md/mac/macsocket.h +++ b/pr/src/md/mac/macsocket.h @@ -164,8 +164,6 @@ extern int select (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfd #define macsock_shutdown PR_Shutdown #define macsock_getpeername PR_GetPeerName #define macsock_getsockname PR_GetSockName -#define macsock_getsockopt PR_GetSockOpt -#define macsock_setsockopt PR_SetSockOpt #define macsock_socketavailable PR_SocketAvailable #define macsock_send PR_Send #define macsock_sendto PR_SendTo diff --git a/pr/src/md/mac/macsockotpt.c b/pr/src/md/mac/macsockotpt.c index 004bd103..7b6e4441 100644 --- a/pr/src/md/mac/macsockotpt.c +++ b/pr/src/md/mac/macsockotpt.c @@ -243,6 +243,22 @@ static void PrepareForAsyncCompletion(PRThread * thread, PRInt32 osfd) } +static void +WakeUpNotifiedThread(PRThread *thread, OTResult result) +{ + _PRCPU * cpu = _PR_MD_CURRENT_CPU(); + + if (thread) { + thread->md.osErrCode = result; + if (_PR_MD_GET_INTSOFF()) { + cpu->u.missed[cpu->where] |= _PR_MISSED_IO; + thread->md.missedIONotify = PR_TRUE; + return; + } + DoneWaitingOnThisThread(thread); + } +} + // Notification routine // Async callback routine. // A5 is OK. Cannot allocate memory here @@ -252,9 +268,9 @@ pascal void NotifierRoutine(void * contextPtr, OTEventCode code, OTResult resul _MDFileDesc * md = &(secret->md); EndpointRef endpoint = (EndpointRef)secret->md.osfd; PRThread * thread = NULL; - _PRCPU * cpu = _PR_MD_CURRENT_CPU(); OSStatus err; OTResult resultOT; + TDiscon discon; switch (code) { @@ -303,10 +319,28 @@ pascal void NotifierRoutine(void * contextPtr, OTEventCode code, OTResult resul return; case T_DISCONNECT: // A disconnect is available - err = OTRcvDisconnect(endpoint, NULL); + discon.udata.len = 0; + err = OTRcvDisconnect(endpoint, &discon); PR_ASSERT(err == kOTNoError); secret->md.exceptReady = PR_TRUE; secret->md.connectionOpen = PR_FALSE; + + // wake up waiting threads, if any + result = -3199 - discon.reason; // obtain the negative error code + + if ((thread = secret->md.read.thread) != NULL) { + secret->md.read.thread = NULL; + secret->md.read.cookie = cookie; + WakeUpNotifiedThread(thread, result); + } + + if ((thread = secret->md.write.thread) != NULL) { + secret->md.write.thread = NULL; + secret->md.write.cookie = cookie; + WakeUpNotifiedThread(thread, result); + } + + thread = NULL; // already took care of notification here break; case T_ERROR: // obsolete/unused in library @@ -323,6 +357,11 @@ pascal void NotifierRoutine(void * contextPtr, OTEventCode code, OTResult resul secret->md.readReady = PR_TRUE; // mark readable (to emulate bsd sockets) // remember connection is closed, so we can return 0 on read or receive secret->md.connectionOpen = PR_FALSE; + + thread = secret->md.read.thread; + secret->md.read.thread = NULL; + secret->md.read.cookie = cookie; + break; case T_GODATA: // Flow control lifted on standard data @@ -391,16 +430,7 @@ pascal void NotifierRoutine(void * contextPtr, OTEventCode code, OTResult resul return; } - if (thread) { - thread->md.osErrCode = result; - if (_PR_MD_GET_INTSOFF()) { - cpu->u.missed[cpu->where] |= _PR_MISSED_IO; - thread->md.missedIONotify = PR_TRUE; - return; - } - - DoneWaitingOnThisThread(thread); - } + WakeUpNotifiedThread(thread, result); } @@ -584,6 +614,7 @@ PRInt32 _MD_listen(PRFileDesc *fd, PRIntn backlog) goto ErrorExit; } + addr.inet.family = AF_INET; addr.inet.port = addr.inet.ip = 0; bindReq.addr.maxlen = PR_NETADDR_SIZE (&addr); @@ -667,12 +698,6 @@ PRInt32 _MD_getsockname(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen) goto ErrorExit; } -#if !defined(_PR_INET6) - addr->inet.family = AF_INET; -#endif - - PR_ASSERT(PR_NETADDR_SIZE(addr) >= (*addrlen)); - bindReq.addr.len = *addrlen; bindReq.addr.maxlen = *addrlen; bindReq.addr.buf = (UInt8*) addr; @@ -696,6 +721,7 @@ PRInt32 _MD_getsockname(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen) if (err != kOTNoError) goto ErrorExit; + *addrlen = PR_NETADDR_SIZE(addr); return kOTNoError; ErrorExit: @@ -988,7 +1014,7 @@ PRInt32 _MD_socketavailable(PRFileDesc *fd) err = OTCountDataBytes(endpoint, &bytes); if ((err == kOTLookErr) || // Not really errors, we just need to do a read, - (err == kOTNoDataErr)) // or there’s nothing there. + (err == kOTNoDataErr)) // or there's nothing there. err = kOTNoError; if (err != kOTNoError) @@ -1127,9 +1153,15 @@ PRInt32 _MD_accept(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen, PRInterva memset(&call, 0 , sizeof(call)); - call.addr.maxlen = PR_NETADDR_SIZE(&callAddr); - call.addr.len = PR_NETADDR_SIZE(&callAddr); - call.addr.buf = (UInt8*) &callAddr; + if (addr != NULL) { + call.addr.maxlen = *addrlen; + call.addr.len = *addrlen; + call.addr.buf = (UInt8*) addr; + } else { + call.addr.maxlen = sizeof(callAddr); + call.addr.len = sizeof(callAddr); + call.addr.buf = (UInt8*) &callAddr; + } do { PrepareForAsyncCompletion(me, fd->secret->md.osfd); @@ -1169,6 +1201,7 @@ PRInt32 _MD_accept(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen, PRInterva PR_ASSERT(err == kOTNoError); // Bind to a local port; let the system assign it. + bindAddr.inet.family = AF_INET; bindAddr.inet.port = bindAddr.inet.ip = 0; bindReq.addr.maxlen = PR_NETADDR_SIZE (&bindAddr); @@ -1199,8 +1232,6 @@ PRInt32 _MD_accept(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen, PRInterva if (err != kOTNoError) goto ErrorExit; - if (addr != NULL) - *addr = callAddr; if (addrlen != NULL) *addrlen = call.addr.len; @@ -1240,6 +1271,7 @@ PRInt32 _MD_connect(PRFileDesc *fd, PRNetAddr *addr, PRUint32 addrlen, PRInterva // Bind to a local port; let the system assign it. + bindAddr.inet.family = AF_INET; bindAddr.inet.port = bindAddr.inet.ip = 0; bindReq.addr.maxlen = PR_NETADDR_SIZE (&bindAddr); @@ -1784,7 +1816,7 @@ _MD_getpeername(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen) TBind peerAddr; OSErr err; - if (*addrlen < PR_NETADDR_SIZE(addr)) { + if (*addrlen < sizeof(InetAddress)) { err = (OSErr) kEINVALErr; goto ErrorExit; diff --git a/pr/src/md/mac/prcpucfg.h b/pr/src/md/mac/prcpucfg.h index e14a0cf8..bc203a42 100644 --- a/pr/src/md/mac/prcpucfg.h +++ b/pr/src/md/mac/prcpucfg.h @@ -26,6 +26,8 @@ #undef IS_LITTLE_ENDIAN #define IS_BIG_ENDIAN 1 +#define PR_AF_INET6 30 /* same as AF_INET6 */ + #define PR_BYTES_PER_BYTE 1L #define PR_BYTES_PER_SHORT 2L #define PR_BYTES_PER_INT 4L diff --git a/pr/src/md/windows/Makefile b/pr/src/md/windows/Makefile index 78a6527f..0655ba19 100644 --- a/pr/src/md/windows/Makefile +++ b/pr/src/md/windows/Makefile @@ -40,6 +40,7 @@ else ifeq ($(OS_TARGET), WIN95) CSRCS = \ ntmisc.c \ + ntsec.c \ ntsem.c \ ntinrval.c \ ntgc.c \ @@ -58,6 +59,7 @@ else CSRCS = \ ntdllmn.c \ ntmisc.c \ + ntsec.c \ ntsem.c \ ntinrval.c \ ntgc.c \ diff --git a/pr/src/md/windows/ntio.c b/pr/src/md/windows/ntio.c index 1b60a380..5326be68 100644 --- a/pr/src/md/windows/ntio.c +++ b/pr/src/md/windows/ntio.c @@ -37,6 +37,7 @@ #include "primpl.h" #include "pprmwait.h" #include <direct.h> +#include <mbstring.h> static HANDLE _pr_completion_port; static PRThread *_pr_io_completion_thread; @@ -60,6 +61,24 @@ extern PRUint32 _nt_idleCount; #define CLOSE_TIMEOUT PR_SecondsToInterval(5) /* + * NSPR-to-NT access right mapping table for files. + */ +static DWORD fileAccessTable[] = { + FILE_GENERIC_READ, + FILE_GENERIC_WRITE, + FILE_GENERIC_EXECUTE +}; + +/* + * NSPR-to-NT access right mapping table for directories. + */ +static DWORD dirAccessTable[] = { + FILE_GENERIC_READ, + FILE_GENERIC_WRITE|FILE_DELETE_CHILD, + FILE_GENERIC_EXECUTE +}; + +/* * The NSPR epoch (00:00:00 1 Jan 1970 UTC) in FILETIME. * We store the value in a PRTime variable for convenience. * This constant is used by _PR_FileTimeToPRTime(). @@ -76,10 +95,6 @@ PRInt32 IsFileLocal(HANDLE hFile); static PRInt32 _md_MakeNonblock(HANDLE); -/* The _nt_use_async flag is used to prevent nspr from using any async io. - * this is a temporary hack. Don't learn to rely on it. - */ -static int _nt_use_async = 1; PRInt32 _nt_nonblock_accept(PRFileDesc *fd, struct sockaddr_in *addr, int *len, PRIntervalTime); PRInt32 _nt_nonblock_recv(PRFileDesc *fd, char *buf, int len, PRIntervalTime); PRInt32 _nt_nonblock_send(PRFileDesc *fd, char *buf, int len, PRIntervalTime); @@ -889,6 +904,8 @@ _PR_MD_INIT_IO() PR_ASSERT(filetime.prt == _pr_filetime_offset); } #endif /* DEBUG */ + + _PR_NT_InitSids(); } /* --- SOCKET IO --------------------------------------------------------- */ @@ -913,11 +930,6 @@ _md_get_recycled_socket() } _MD_UNLOCK(&_pr_recycle_lock); -#ifdef _PR_INET6 - if (_pr_ipv6_enabled) { - af = AF_INET6; - } -#endif rv = _PR_MD_SOCKET(af, SOCK_STREAM, 0); if (rv != INVALID_SOCKET && _md_Associate((HANDLE)rv) == 0) { closesocket(rv); @@ -1127,7 +1139,7 @@ _PR_MD_CONNECT(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen, PRThread *cThread; struct connect_data_s cd; - if (!_nt_use_async || fd->secret->nonblocking) { + if (fd->secret->nonblocking) { PRInt32 rv; fd_set wd; struct timeval tv, *tvp; @@ -1294,7 +1306,7 @@ _PR_MD_FAST_ACCEPT(PRFileDesc *fd, PRNetAddr *raddr, PRUint32 *rlen, PRUint32 llen, err; int rv; - if (!_nt_use_async || fd->secret->nonblocking || fd->secret->inheritable) { + if (fd->secret->nonblocking || fd->secret->inheritable) { if (!fd->secret->md.io_model_committed) { rv = _md_MakeNonblock((HANDLE)osfd); PR_ASSERT(0 != rv); @@ -1306,7 +1318,7 @@ _PR_MD_FAST_ACCEPT(PRFileDesc *fd, PRNetAddr *raddr, PRUint32 *rlen, * the listening socket. */ accept_sock = _nt_nonblock_accept(fd, (struct sockaddr_in *)raddr, rlen, timeout); - if (_nt_use_async && !fd->secret->nonblocking) { + if (!fd->secret->nonblocking) { u_long zero = 0; rv = ioctlsocket(accept_sock, FIONBIO, &zero); @@ -1441,21 +1453,6 @@ _PR_MD_FAST_ACCEPT_READ(PRFileDesc *sd, PRInt32 *newSock, PRNetAddr **raddr, PRBool isConnected; PRBool madeCallback = PR_FALSE; - if (!_nt_use_async) { - PRFileDesc *nd; - bytes = _PR_EmulateAcceptRead(sd, &nd, raddr, buf, amount, timeout); - if (bytes != -1) { - /* - * This part is the same as SocketClose(nd), except - * that we don't close the osfd. - */ - PR_ASSERT(nd->secret->state == _PR_FILEDESC_OPEN); - *newSock = nd->secret->md.osfd; - PR_FreeFileDesc(nd); - } - return bytes; - } - if (me->io_suspended) { PR_SetError(PR_INVALID_STATE_ERROR, 0); return -1; @@ -1620,15 +1617,6 @@ _PR_MD_SENDFILE(PRFileDesc *sock, PRSendFileData *sfd, PRInt32 tflags; int rv, err; - if (!_nt_use_async) { - if (!sock->secret->md.io_model_committed) { - rv = _md_MakeNonblock((HANDLE)sock->secret->md.osfd); - PR_ASSERT(0 != rv); - sock->secret->md.io_model_committed = PR_TRUE; - } - return _PR_EmulateSendFile(sock, sfd, flags, timeout); - } - if (me->io_suspended) { PR_SetError(PR_INVALID_STATE_ERROR, 0); return -1; @@ -1735,7 +1723,7 @@ _PR_MD_RECV(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, int bytes; int rv, err; - if (!_nt_use_async || fd->secret->nonblocking || fd->secret->inheritable) { + if (fd->secret->nonblocking || fd->secret->inheritable) { if (!fd->secret->md.io_model_committed) { rv = _md_MakeNonblock((HANDLE)osfd); PR_ASSERT(0 != rv); @@ -1834,7 +1822,7 @@ _PR_MD_SEND(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, int bytes; int rv, err; - if (!_nt_use_async || fd->secret->nonblocking || fd->secret->inheritable) { + if (fd->secret->nonblocking || fd->secret->inheritable) { if (!fd->secret->md.io_model_committed) { rv = _md_MakeNonblock((HANDLE)osfd); PR_ASSERT(0 != rv); @@ -1932,7 +1920,7 @@ _PR_MD_SENDTO(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, PR_ASSERT(0 != rv); fd->secret->md.io_model_committed = PR_TRUE; } - if (_nt_use_async && !fd->secret->nonblocking && !fd->secret->inheritable) + if (!fd->secret->nonblocking && !fd->secret->inheritable) return pt_SendTo(osfd, buf, amount, flags, addr, addrlen, timeout); else return _nt_nonblock_sendto(fd, buf, amount, (struct sockaddr *)addr, addrlen, timeout); @@ -1950,7 +1938,7 @@ _PR_MD_RECVFROM(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PR_ASSERT(0 != rv); fd->secret->md.io_model_committed = PR_TRUE; } - if (_nt_use_async && !fd->secret->nonblocking && !fd->secret->inheritable) + if (!fd->secret->nonblocking && !fd->secret->inheritable) return pt_RecvFrom(osfd, buf, amount, flags, addr, addrlen, timeout); else return _nt_nonblock_recvfrom(fd, buf, amount, (struct sockaddr *)addr, addrlen, timeout); @@ -1965,7 +1953,7 @@ _PR_MD_WRITEV(PRFileDesc *fd, const PRIOVec *iov, PRInt32 iov_size, PRIntervalTi int sent = 0; int rv; - if (!_nt_use_async || fd->secret->nonblocking || fd->secret->inheritable) { + if (fd->secret->nonblocking || fd->secret->inheritable) { if (!fd->secret->md.io_model_committed) { rv = _md_MakeNonblock((HANDLE)osfd); PR_ASSERT(0 != rv); @@ -2115,79 +2103,102 @@ _PR_MD_OPEN(const char *name, PRIntn osflags, PRIntn mode) if (osflags & PR_SYNC) flag6 = FILE_FLAG_WRITE_THROUGH; - if (_nt_use_async) - { - if (osflags & PR_RDONLY || osflags & PR_RDWR) access |= GENERIC_READ; - if (osflags & PR_WRONLY || osflags & PR_RDWR) access |= GENERIC_WRITE; - - if ( osflags & PR_CREATE_FILE && osflags & PR_EXCL ) - flags = CREATE_NEW; - else if (osflags & PR_CREATE_FILE) - flags = (0 != (osflags & PR_TRUNCATE)) ? CREATE_ALWAYS : OPEN_ALWAYS; - else if (osflags & PR_TRUNCATE) flags = TRUNCATE_EXISTING; - else flags = OPEN_EXISTING; - - - flag6 |= FILE_FLAG_OVERLAPPED; - - file = CreateFile(name, - access, - FILE_SHARE_READ|FILE_SHARE_WRITE, - NULL, - flags, - flag6, - NULL); - if (file == INVALID_HANDLE_VALUE) { - _PR_MD_MAP_OPEN_ERROR(GetLastError()); - return -1; - } + if (osflags & PR_RDONLY || osflags & PR_RDWR) access |= GENERIC_READ; + if (osflags & PR_WRONLY || osflags & PR_RDWR) access |= GENERIC_WRITE; - if (osflags & PR_APPEND) { - if ( SetFilePointer(file, 0, 0, FILE_END) == 0xFFFFFFFF ) { - _PR_MD_MAP_LSEEK_ERROR(GetLastError()); - CloseHandle(file); - return -1; - } - } + if ( osflags & PR_CREATE_FILE && osflags & PR_EXCL ) + flags = CREATE_NEW; + else if (osflags & PR_CREATE_FILE) + flags = (0 != (osflags & PR_TRUNCATE)) ? CREATE_ALWAYS : OPEN_ALWAYS; + else if (osflags & PR_TRUNCATE) flags = TRUNCATE_EXISTING; + else flags = OPEN_EXISTING; + + + flag6 |= FILE_FLAG_OVERLAPPED; - return (PRInt32)file; + file = CreateFile(name, + access, + FILE_SHARE_READ|FILE_SHARE_WRITE, + NULL, + flags, + flag6, + NULL); + if (file == INVALID_HANDLE_VALUE) { + _PR_MD_MAP_OPEN_ERROR(GetLastError()); + return -1; } - else - { - - if (osflags & PR_RDONLY || osflags & PR_RDWR) - access |= GENERIC_READ; - if (osflags & PR_WRONLY || osflags & PR_RDWR) - access |= GENERIC_WRITE; - - if ( osflags & PR_CREATE_FILE && osflags & PR_EXCL ) - flags = CREATE_NEW; - else if (osflags & PR_CREATE_FILE) { - if (osflags & PR_TRUNCATE) - flags = CREATE_ALWAYS; - else - flags = OPEN_ALWAYS; - } else { - if (osflags & PR_TRUNCATE) - flags = TRUNCATE_EXISTING; - else - flags = OPEN_EXISTING; + + if (osflags & PR_APPEND) { + if ( SetFilePointer(file, 0, 0, FILE_END) == 0xFFFFFFFF ) { + _PR_MD_MAP_LSEEK_ERROR(GetLastError()); + CloseHandle(file); + return -1; } + } + + return (PRInt32)file; +} + +PRInt32 +_PR_MD_OPEN_FILE(const char *name, PRIntn osflags, PRIntn mode) +{ + HANDLE file; + PRInt32 access = 0; + PRInt32 flags = 0; + PRInt32 flag6 = 0; + SECURITY_ATTRIBUTES sa; + LPSECURITY_ATTRIBUTES lpSA = NULL; + PSECURITY_DESCRIPTOR pSD = NULL; + PACL pACL = NULL; - file = CreateFile(name, - access, - FILE_SHARE_READ|FILE_SHARE_WRITE, - NULL, - flags, - flag6, - NULL); - if (file == INVALID_HANDLE_VALUE) { - _PR_MD_MAP_OPEN_ERROR(GetLastError()); - return -1; + if (osflags & PR_SYNC) flag6 = FILE_FLAG_WRITE_THROUGH; + + if (osflags & PR_RDONLY || osflags & PR_RDWR) access |= GENERIC_READ; + if (osflags & PR_WRONLY || osflags & PR_RDWR) access |= GENERIC_WRITE; + + if ( osflags & PR_CREATE_FILE && osflags & PR_EXCL ) + flags = CREATE_NEW; + else if (osflags & PR_CREATE_FILE) + flags = (0 != (osflags & PR_TRUNCATE)) ? CREATE_ALWAYS : OPEN_ALWAYS; + else if (osflags & PR_TRUNCATE) flags = TRUNCATE_EXISTING; + else flags = OPEN_EXISTING; + + + flag6 |= FILE_FLAG_OVERLAPPED; + + if (osflags & PR_CREATE_FILE) { + if (_PR_NT_MakeSecurityDescriptorACL(mode, fileAccessTable, + &pSD, &pACL) == PR_SUCCESS) { + sa.nLength = sizeof(sa); + sa.lpSecurityDescriptor = pSD; + sa.bInheritHandle = FALSE; + lpSA = &sa; } + } + file = CreateFile(name, + access, + FILE_SHARE_READ|FILE_SHARE_WRITE, + lpSA, + flags, + flag6, + NULL); + if (lpSA != NULL) { + _PR_NT_FreeSecurityDescriptorACL(pSD, pACL); + } + if (file == INVALID_HANDLE_VALUE) { + _PR_MD_MAP_OPEN_ERROR(GetLastError()); + return -1; + } - return (PRInt32)file; + if (osflags & PR_APPEND) { + if ( SetFilePointer(file, 0, 0, FILE_END) == 0xFFFFFFFF ) { + _PR_MD_MAP_LSEEK_ERROR(GetLastError()); + CloseHandle(file); + return -1; + } } + + return (PRInt32)file; } PRInt32 @@ -2196,8 +2207,10 @@ _PR_MD_READ(PRFileDesc *fd, void *buf, PRInt32 len) PRInt32 f = fd->secret->md.osfd; PRUint32 bytes; int rv, err; + LONG hiOffset = 0; + LONG loOffset; - if (_nt_use_async && !fd->secret->md.sync_file_io) { + if (!fd->secret->md.sync_file_io) { PRThread *me = _PR_MD_CURRENT_THREAD(); if (me->io_suspended) { @@ -2207,7 +2220,8 @@ _PR_MD_READ(PRFileDesc *fd, void *buf, PRInt32 len) memset(&(me->md.overlapped.overlapped), 0, sizeof(OVERLAPPED)); - me->md.overlapped.overlapped.Offset = SetFilePointer((HANDLE)f, 0, 0, FILE_CURRENT); + me->md.overlapped.overlapped.Offset = SetFilePointer((HANDLE)f, 0, &me->md.overlapped.overlapped.OffsetHigh, FILE_CURRENT); + PR_ASSERT((me->md.overlapped.overlapped.Offset != 0xffffffff) || (GetLastError() == NO_ERROR)); if (fd->secret->inheritable) { rv = ReadFile((HANDLE)f, @@ -2216,7 +2230,8 @@ _PR_MD_READ(PRFileDesc *fd, void *buf, PRInt32 len) &bytes, &me->md.overlapped.overlapped); if (rv != 0) { - SetFilePointer((HANDLE)f, bytes, 0, FILE_CURRENT); + loOffset = SetFilePointer((HANDLE)f, bytes, &hiOffset, FILE_CURRENT); + PR_ASSERT((loOffset != 0xffffffff) || (GetLastError() == NO_ERROR)); return bytes; } err = GetLastError(); @@ -2224,7 +2239,8 @@ _PR_MD_READ(PRFileDesc *fd, void *buf, PRInt32 len) rv = GetOverlappedResult((HANDLE)f, &me->md.overlapped.overlapped, &bytes, TRUE); if (rv != 0) { - SetFilePointer((HANDLE)f, bytes, 0, FILE_CURRENT); + loOffset = SetFilePointer((HANDLE)f, bytes, &hiOffset, FILE_CURRENT); + PR_ASSERT((loOffset != 0xffffffff) || (GetLastError() == NO_ERROR)); return bytes; } err = GetLastError(); @@ -2342,8 +2358,10 @@ _PR_MD_WRITE(PRFileDesc *fd, void *buf, PRInt32 len) PRInt32 f = fd->secret->md.osfd; PRInt32 bytes; int rv, err; + LONG hiOffset = 0; + LONG loOffset; - if (_nt_use_async && !fd->secret->md.sync_file_io) { + if (!fd->secret->md.sync_file_io) { PRThread *me = _PR_MD_CURRENT_THREAD(); if (me->io_suspended) { @@ -2353,7 +2371,8 @@ _PR_MD_WRITE(PRFileDesc *fd, void *buf, PRInt32 len) memset(&(me->md.overlapped.overlapped), 0, sizeof(OVERLAPPED)); - me->md.overlapped.overlapped.Offset = SetFilePointer((HANDLE)f, 0, 0, FILE_CURRENT); + me->md.overlapped.overlapped.Offset = SetFilePointer((HANDLE)f, 0, &me->md.overlapped.overlapped.OffsetHigh, FILE_CURRENT); + PR_ASSERT((me->md.overlapped.overlapped.Offset != 0xffffffff) || (GetLastError() == NO_ERROR)); if (fd->secret->inheritable) { rv = WriteFile((HANDLE)f, @@ -2362,7 +2381,8 @@ _PR_MD_WRITE(PRFileDesc *fd, void *buf, PRInt32 len) &bytes, &me->md.overlapped.overlapped); if (rv != 0) { - SetFilePointer((HANDLE)f, bytes, 0, FILE_CURRENT); + loOffset = SetFilePointer((HANDLE)f, bytes, &hiOffset, FILE_CURRENT); + PR_ASSERT((loOffset != 0xffffffff) || (GetLastError() == NO_ERROR)); return bytes; } err = GetLastError(); @@ -2370,7 +2390,8 @@ _PR_MD_WRITE(PRFileDesc *fd, void *buf, PRInt32 len) rv = GetOverlappedResult((HANDLE)f, &me->md.overlapped.overlapped, &bytes, TRUE); if (rv != 0) { - SetFilePointer((HANDLE)f, bytes, 0, FILE_CURRENT); + loOffset = SetFilePointer((HANDLE)f, bytes, &hiOffset, FILE_CURRENT); + PR_ASSERT((loOffset != 0xffffffff) || (GetLastError() == NO_ERROR)); return bytes; } err = GetLastError(); @@ -2587,62 +2608,50 @@ PRInt32 _PR_MD_CLOSE(PRInt32 osfd, PRBool socket) { PRInt32 rv; - if (_nt_use_async) { - PRThread *me = _PR_MD_CURRENT_THREAD(); + PRThread *me = _PR_MD_CURRENT_THREAD(); - if (socket) { - rv = closesocket((SOCKET)osfd); - if (rv < 0) - _PR_MD_MAP_CLOSE_ERROR(WSAGetLastError()); - } else { - rv = CloseHandle((HANDLE)osfd)?0:-1; - if (rv < 0) - _PR_MD_MAP_CLOSE_ERROR(GetLastError()); - } + if (socket) { + rv = closesocket((SOCKET)osfd); + if (rv < 0) + _PR_MD_MAP_CLOSE_ERROR(WSAGetLastError()); + } else { + rv = CloseHandle((HANDLE)osfd)?0:-1; + if (rv < 0) + _PR_MD_MAP_CLOSE_ERROR(GetLastError()); + } - if (rv == 0 && me->io_suspended) { - if (me->io_fd == osfd) { - PRBool fWait; + if (rv == 0 && me->io_suspended) { + if (me->io_fd == osfd) { + PRBool fWait; - _PR_THREAD_LOCK(me); - me->state = _PR_IO_WAIT; - /* The IO could have completed on another thread just after - * calling closesocket while the io_suspended flag was true. - * So we now grab the lock to do a safe check on io_pending to - * see if we need to wait or not. - */ - fWait = me->io_pending; - me->io_suspended = PR_FALSE; - me->md.interrupt_disabled = PR_TRUE; - _PR_THREAD_UNLOCK(me); + _PR_THREAD_LOCK(me); + me->state = _PR_IO_WAIT; + /* The IO could have completed on another thread just after + * calling closesocket while the io_suspended flag was true. + * So we now grab the lock to do a safe check on io_pending to + * see if we need to wait or not. + */ + fWait = me->io_pending; + me->io_suspended = PR_FALSE; + me->md.interrupt_disabled = PR_TRUE; + _PR_THREAD_UNLOCK(me); - if (fWait) - _NT_IO_WAIT(me, PR_INTERVAL_NO_TIMEOUT); - PR_ASSERT(me->io_suspended == PR_FALSE); - PR_ASSERT(me->io_pending == PR_FALSE); - /* - * I/O operation is no longer pending; the thread can now - * run on any cpu - */ - _PR_THREAD_LOCK(me); - me->md.interrupt_disabled = PR_FALSE; - me->md.thr_bound_cpu = NULL; - me->io_suspended = PR_FALSE; - me->io_pending = PR_FALSE; - me->state = _PR_RUNNING; - _PR_THREAD_UNLOCK(me); - } + if (fWait) + _NT_IO_WAIT(me, PR_INTERVAL_NO_TIMEOUT); + PR_ASSERT(me->io_suspended == PR_FALSE); + PR_ASSERT(me->io_pending == PR_FALSE); + /* + * I/O operation is no longer pending; the thread can now + * run on any cpu + */ + _PR_THREAD_LOCK(me); + me->md.interrupt_disabled = PR_FALSE; + me->md.thr_bound_cpu = NULL; + me->io_suspended = PR_FALSE; + me->io_pending = PR_FALSE; + me->state = _PR_RUNNING; + _PR_THREAD_UNLOCK(me); } - } else { - if (socket) { - rv = closesocket((SOCKET)osfd); - if (rv == -1) - _PR_MD_MAP_CLOSE_ERROR(WSAGetLastError()); - } else { - rv = CloseHandle((HANDLE)osfd)?0:-1; - if (rv == -1) - _PR_MD_MAP_CLOSE_ERROR(GetLastError()); - } } return rv; } @@ -2661,7 +2670,7 @@ _PR_MD_SET_FD_INHERITABLE(PRFileDesc *fd, PRBool inheritable) HANDLE_FLAG_INHERIT, inheritable ? HANDLE_FLAG_INHERIT : 0); if (0 == rv) { - PR_SetError(PR_UNKNOWN_ERROR, GetLastError()); + _PR_MD_MAP_DEFAULT_ERROR(GetLastError()); return PR_FAILURE; } return PR_SUCCESS; @@ -2675,12 +2684,12 @@ _PR_MD_SET_FD_INHERITABLE(PRFileDesc *fd, PRBool inheritable) void FlipSlashes(char *cp, int len) { while (--len >= 0) { - if (cp[0] == '/') { - cp[0] = PR_DIRECTORY_SEPARATOR; - } - cp++; + if (cp[0] == '/') { + cp[0] = PR_DIRECTORY_SEPARATOR; + } + cp = _mbsinc(cp); } -} +} /* end FlipSlashes() */ /* ** @@ -2979,7 +2988,7 @@ _PR_MD_GETFILEINFO64(const char *fn, PRFileInfo64 *info) * FindFirstFile() expands wildcard characters. So * we make sure the pathname contains no wildcard. */ - if (NULL != strpbrk(fn, "?*")) { + if (NULL != _mbspbrk(fn, "?*")) { PR_SetError(PR_FILE_NOT_FOUND_ERROR, 0); return -1; } @@ -3001,7 +3010,7 @@ _PR_MD_GETFILEINFO64(const char *fn, PRFileInfo64 *info) * If the pathname does not contain ., \, and /, it cannot be * a root directory or a pathname that ends in a slash. */ - if (NULL == strpbrk(fn, ".\\/")) { + if (NULL == _mbspbrk(fn, ".\\/")) { _PR_MD_MAP_OPENDIR_ERROR(GetLastError()); return -1; } @@ -3177,6 +3186,34 @@ _PR_MD_MKDIR(const char *name, PRIntn mode) } PRInt32 +_PR_MD_MAKE_DIR(const char *name, PRIntn mode) +{ + BOOL rv; + SECURITY_ATTRIBUTES sa; + LPSECURITY_ATTRIBUTES lpSA = NULL; + PSECURITY_DESCRIPTOR pSD = NULL; + PACL pACL = NULL; + + if (_PR_NT_MakeSecurityDescriptorACL(mode, dirAccessTable, + &pSD, &pACL) == PR_SUCCESS) { + sa.nLength = sizeof(sa); + sa.lpSecurityDescriptor = pSD; + sa.bInheritHandle = FALSE; + lpSA = &sa; + } + rv = CreateDirectory(name, lpSA); + if (lpSA != NULL) { + _PR_NT_FreeSecurityDescriptorACL(pSD, pACL); + } + if (rv) { + return 0; + } else { + _PR_MD_MAP_MKDIR_ERROR(GetLastError()); + return -1; + } +} + +PRInt32 _PR_MD_RMDIR(const char *name) { if (RemoveDirectory(name)) { @@ -3668,11 +3705,6 @@ PRInt32 IsFileLocal(HANDLE hFile) } #endif /* _NEED_351_FILE_LOCKING_HACK */ -PR_IMPLEMENT(void) PR_NT_UseNonblock() -{ - _nt_use_async = 0; -} - PR_IMPLEMENT(PRStatus) PR_NT_CancelIo(PRFileDesc *fd) { PRThread *me = _PR_MD_CURRENT_THREAD(); diff --git a/pr/src/md/windows/ntsec.c b/pr/src/md/windows/ntsec.c new file mode 100644 index 00000000..d1c137b4 --- /dev/null +++ b/pr/src/md/windows/ntsec.c @@ -0,0 +1,252 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 2000 Netscape Communications Corporation. All Rights + * Reserved. + */ + +#include "primpl.h" + +/* + * ntsec.c + * + * Implement the POSIX-style mode bits (access permissions) for + * files and other securable objects in Windows NT using Windows + * NT's security descriptors with appropriate discretionary + * access-control lists. + */ + +/* + * The security identifiers (SIDs) for owner, primary group, + * and the Everyone (World) group. + * + * These SIDs are looked up during NSPR initialization and + * saved in this global structure (see _PR_NT_InitSids) so + * that _PR_NT_MakeSecurityDescriptorACL doesn't need to + * look them up every time. + */ +static struct { + PSID owner; + PSID group; + PSID everyone; +} _pr_nt_sids; + +/* + * Initialize the SIDs for owner, primary group, and the Everyone + * group in the _pr_nt_sids structure. + * + * This function needs to be called by NSPR initialization. + */ +void _PR_NT_InitSids(void) +{ + SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY; + HANDLE hToken; + UCHAR infoBuffer[1024]; + PTOKEN_OWNER pTokenOwner = (PTOKEN_OWNER) infoBuffer; + PTOKEN_PRIMARY_GROUP pTokenPrimaryGroup + = (PTOKEN_PRIMARY_GROUP) infoBuffer; + DWORD dwLength; + BOOL rv; + + /* Create a well-known SID for the Everyone group. */ + if (!AllocateAndInitializeSid(&SIDAuthWorld, 1, + SECURITY_WORLD_RID, + 0, 0, 0, 0, 0, 0, 0, + &_pr_nt_sids.everyone)) { + /* + * On non-NT systems, this function is not implemented, + * and neither are the other security functions. There + * is no point in going further. + */ + PR_ASSERT(GetLastError() == ERROR_CALL_NOT_IMPLEMENTED); + return; + } + + /* + * Look up and make a copy of the owner and primary group + * SIDs in the access token of the calling process. + */ + rv = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken); + PR_ASSERT(rv != 0); + + rv = GetTokenInformation(hToken, TokenOwner, infoBuffer, + sizeof(infoBuffer), &dwLength); + PR_ASSERT(rv != 0); + dwLength = GetLengthSid(pTokenOwner->Owner); + _pr_nt_sids.owner = (PSID) PR_Malloc(dwLength); + PR_ASSERT(_pr_nt_sids.owner != NULL); + rv = CopySid(dwLength, _pr_nt_sids.owner, pTokenOwner->Owner); + PR_ASSERT(rv != 0); + + rv = GetTokenInformation(hToken, TokenPrimaryGroup, infoBuffer, + sizeof(infoBuffer), &dwLength); + PR_ASSERT(rv != 0); + dwLength = GetLengthSid(pTokenPrimaryGroup->PrimaryGroup); + _pr_nt_sids.group = (PSID) PR_Malloc(dwLength); + PR_ASSERT(_pr_nt_sids.group != NULL); + rv = CopySid(dwLength, _pr_nt_sids.group, + pTokenPrimaryGroup->PrimaryGroup); + PR_ASSERT(rv != 0); + + rv = CloseHandle(hToken); + PR_ASSERT(rv != 0); +} + +/* + * Free the SIDs for owner, primary group, and the Everyone group + * in the _pr_nt_sids structure. + * + * This function needs to be called by NSPR cleanup. + */ +void +_PR_NT_FreeSids(void) +{ + if (_pr_nt_sids.owner) { + PR_Free(_pr_nt_sids.owner); + } + if (_pr_nt_sids.group) { + PR_Free(_pr_nt_sids.group); + } + if (_pr_nt_sids.everyone) { + FreeSid(_pr_nt_sids.everyone); + } +} + +/* + * Construct a security descriptor whose discretionary access-control + * list implements the specified mode bits. The SIDs for owner, group, + * and everyone are obtained from the global _pr_nt_sids structure. + * Both the security descriptor and access-control list are returned + * and should be freed by a _PR_NT_FreeSecurityDescriptorACL call. + * + * The accessTable array maps NSPR's read, write, and execute access + * rights to the corresponding NT access rights for the securable + * object. + */ +PRStatus +_PR_NT_MakeSecurityDescriptorACL( + PRIntn mode, + DWORD accessTable[], + PSECURITY_DESCRIPTOR *resultSD, + PACL *resultACL) +{ + PSECURITY_DESCRIPTOR pSD = NULL; + PACL pACL = NULL; + DWORD cbACL; /* size of ACL */ + DWORD accessMask; + + if (_pr_nt_sids.owner == NULL) { + PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); + return PR_FAILURE; + } + + pSD = (PSECURITY_DESCRIPTOR) PR_Malloc(SECURITY_DESCRIPTOR_MIN_LENGTH); + if (pSD == NULL) { + _PR_MD_MAP_DEFAULT_ERROR(GetLastError()); + goto failed; + } + if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION)) { + _PR_MD_MAP_DEFAULT_ERROR(GetLastError()); + goto failed; + } + if (!SetSecurityDescriptorOwner(pSD, _pr_nt_sids.owner, FALSE)) { + _PR_MD_MAP_DEFAULT_ERROR(GetLastError()); + goto failed; + } + if (!SetSecurityDescriptorGroup(pSD, _pr_nt_sids.group, FALSE)) { + _PR_MD_MAP_DEFAULT_ERROR(GetLastError()); + goto failed; + } + + /* + * Construct a discretionary access-control list with three + * access-control entries, one each for owner, primary group, + * and Everyone. + */ + + cbACL = sizeof(ACL) + + 3 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)) + + GetLengthSid(_pr_nt_sids.owner) + + GetLengthSid(_pr_nt_sids.group) + + GetLengthSid(_pr_nt_sids.everyone); + pACL = (PACL) PR_Malloc(cbACL); + if (pACL == NULL) { + _PR_MD_MAP_DEFAULT_ERROR(GetLastError()); + goto failed; + } + if (!InitializeAcl(pACL, cbACL, ACL_REVISION)) { + _PR_MD_MAP_DEFAULT_ERROR(GetLastError()); + goto failed; + } + accessMask = 0; + if (mode & 00400) accessMask |= accessTable[0]; + if (mode & 00200) accessMask |= accessTable[1]; + if (mode & 00100) accessMask |= accessTable[2]; + if (accessMask && !AddAccessAllowedAce(pACL, ACL_REVISION, accessMask, + _pr_nt_sids.owner)) { + _PR_MD_MAP_DEFAULT_ERROR(GetLastError()); + goto failed; + } + accessMask = 0; + if (mode & 00040) accessMask |= accessTable[0]; + if (mode & 00020) accessMask |= accessTable[1]; + if (mode & 00010) accessMask |= accessTable[2]; + if (accessMask && !AddAccessAllowedAce(pACL, ACL_REVISION, accessMask, + _pr_nt_sids.group)) { + _PR_MD_MAP_DEFAULT_ERROR(GetLastError()); + goto failed; + } + accessMask = 0; + if (mode & 00004) accessMask |= accessTable[0]; + if (mode & 00002) accessMask |= accessTable[1]; + if (mode & 00001) accessMask |= accessTable[2]; + if (accessMask && !AddAccessAllowedAce(pACL, ACL_REVISION, accessMask, + _pr_nt_sids.everyone)) { + _PR_MD_MAP_DEFAULT_ERROR(GetLastError()); + goto failed; + } + + if (!SetSecurityDescriptorDacl(pSD, TRUE, pACL, FALSE)) { + _PR_MD_MAP_DEFAULT_ERROR(GetLastError()); + goto failed; + } + + *resultSD = pSD; + *resultACL = pACL; + return PR_SUCCESS; + +failed: + if (pSD) { + PR_Free(pSD); + } + if (pACL) { + PR_Free(pACL); + } + return PR_FAILURE; +} + +/* + * Free the specified security descriptor and access-control list + * previously created by _PR_NT_MakeSecurityDescriptorACL. + */ +void +_PR_NT_FreeSecurityDescriptorACL(PSECURITY_DESCRIPTOR pSD, PACL pACL) +{ + if (pSD) { + PR_Free(pSD); + } + if (pACL) { + PR_Free(pACL); + } +} diff --git a/pr/src/md/windows/ntthread.c b/pr/src/md/windows/ntthread.c index 37cb2e3a..03153aa3 100644 --- a/pr/src/md/windows/ntthread.c +++ b/pr/src/md/windows/ntthread.c @@ -118,6 +118,8 @@ _PR_MD_EARLY_INIT() void _PR_MD_CLEANUP_BEFORE_EXIT(void) { + _PR_NT_FreeSids(); + WSACleanup(); if (!_pr_use_static_tls) { diff --git a/pr/src/md/windows/w32ipcsem.c b/pr/src/md/windows/w32ipcsem.c index 951b1cf8..f1f71153 100644 --- a/pr/src/md/windows/w32ipcsem.c +++ b/pr/src/md/windows/w32ipcsem.c @@ -23,6 +23,22 @@ #include "primpl.h" +/* + * NSPR-to-NT access right mapping table for semaphore objects. + * + * The SYNCHRONIZE access is required by WaitForSingleObject. + * The SEMAPHORE_MODIFY_STATE access is required by ReleaseSemaphore. + * The OR of these three access masks must equal SEMAPHORE_ALL_ACCESS. + * This is because if a semaphore object with the specified name + * exists, CreateSemaphore requests SEMAPHORE_ALL_ACCESS access to + * the existing object. + */ +static DWORD semAccessTable[] = { + STANDARD_RIGHTS_REQUIRED|0x1, /* read (0x1 is "query state") */ + STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|SEMAPHORE_MODIFY_STATE, /* write */ + 0 /* execute */ +}; + #ifndef _PR_GLOBAL_THREADS_ONLY /* @@ -94,6 +110,10 @@ PRSem *_PR_MD_OPEN_SEMAPHORE( const char *osname, PRIntn flags, PRIntn mode, PRUintn value) { PRSem *sem; + SECURITY_ATTRIBUTES sa; + LPSECURITY_ATTRIBUTES lpSA = NULL; + PSECURITY_DESCRIPTOR pSD = NULL; + PACL pACL = NULL; sem = PR_NEW(PRSem); if (sem == NULL) { @@ -101,7 +121,17 @@ PRSem *_PR_MD_OPEN_SEMAPHORE( return NULL; } if (flags & PR_SEM_CREATE) { - sem->sem = CreateSemaphore(NULL, value, 0x7fffffff, osname); + if (_PR_NT_MakeSecurityDescriptorACL(mode, semAccessTable, + &pSD, &pACL) == PR_SUCCESS) { + sa.nLength = sizeof(sa); + sa.lpSecurityDescriptor = pSD; + sa.bInheritHandle = FALSE; + lpSA = &sa; + } + sem->sem = CreateSemaphore(lpSA, value, 0x7fffffff, osname); + if (lpSA != NULL) { + _PR_NT_FreeSecurityDescriptorACL(pSD, pACL); + } if (sem->sem == NULL) { _PR_MD_MAP_DEFAULT_ERROR(GetLastError()); PR_DELETE(sem); @@ -114,7 +144,8 @@ PRSem *_PR_MD_OPEN_SEMAPHORE( return NULL; } } else { - sem->sem = OpenSemaphore(SEMAPHORE_ALL_ACCESS, FALSE, osname); + sem->sem = OpenSemaphore( + SEMAPHORE_MODIFY_STATE|SYNCHRONIZE, FALSE, osname); if (sem->sem == NULL) { DWORD err = GetLastError(); diff --git a/pr/src/md/windows/w32shm.c b/pr/src/md/windows/w32shm.c index 4fb60e93..0efd8a45 100644 --- a/pr/src/md/windows/w32shm.c +++ b/pr/src/md/windows/w32shm.c @@ -26,6 +26,20 @@ extern PRLogModuleInfo *_pr_shm_lm; +/* + * NSPR-to-NT access right mapping table for file-mapping objects. + * + * The OR of these three access masks must equal FILE_MAP_ALL_ACCESS. + * This is because if a file-mapping object with the specified name + * exists, CreateFileMapping requests full access to the existing + * object. + */ +static DWORD filemapAccessTable[] = { + FILE_MAP_ALL_ACCESS & ~FILE_MAP_WRITE, /* read */ + FILE_MAP_ALL_ACCESS & ~FILE_MAP_READ, /* write */ + 0 /* execute */ +}; + extern PRSharedMemory * _MD_OpenSharedMemory( const char *name, PRSize size, @@ -38,6 +52,10 @@ extern PRSharedMemory * _MD_OpenSharedMemory( DWORD dwHi, dwLo; PRSharedMemory *shm; DWORD flProtect = ( PAGE_READWRITE ); + SECURITY_ATTRIBUTES sa; + LPSECURITY_ATTRIBUTES lpSA = NULL; + PSECURITY_DESCRIPTOR pSD = NULL; + PACL pACL = NULL; rc = _PR_MakeNativeIPCName( name, ipcname, PR_IPC_NAME_SIZE, _PRIPCShm ); if ( PR_FAILURE == rc ) @@ -72,23 +90,33 @@ extern PRSharedMemory * _MD_OpenSharedMemory( shm->ident = _PR_SHM_IDENT; if (flags & PR_SHM_CREATE ) { - /* XXX: Not 64bit safe. Fix when WinNT goes 64bit, if ever */ + /* XXX: Not 64bit safe. Fix when WinNT goes 64bit. */ dwHi = 0; dwLo = shm->size; + if (_PR_NT_MakeSecurityDescriptorACL(mode, filemapAccessTable, + &pSD, &pACL) == PR_SUCCESS) { + sa.nLength = sizeof(sa); + sa.lpSecurityDescriptor = pSD; + sa.bInheritHandle = FALSE; + lpSA = &sa; + } shm->handle = CreateFileMapping( (HANDLE)-1 , - NULL, + lpSA, flProtect, dwHi, dwLo, shm->ipcname); + if (lpSA != NULL) { + _PR_NT_FreeSecurityDescriptorACL(pSD, pACL); + } if ( NULL == shm->handle ) { PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, ( "PR_OpenSharedMemory: CreateFileMapping() failed: %s", shm->ipcname )); - PR_SetError( PR_FILE_EXISTS_ERROR, ERROR_ALREADY_EXISTS ); + _PR_MD_MAP_DEFAULT_ERROR( GetLastError()); PR_FREEIF( shm->ipcname ) PR_DELETE( shm ); return(NULL); @@ -110,7 +138,7 @@ extern PRSharedMemory * _MD_OpenSharedMemory( } } } else { - shm->handle = OpenFileMapping( FILE_MAP_ALL_ACCESS, TRUE, shm->ipcname ); + shm->handle = OpenFileMapping( FILE_MAP_WRITE, TRUE, shm->ipcname ); if ( NULL == shm->handle ) { _PR_MD_MAP_DEFAULT_ERROR( GetLastError()); PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, diff --git a/pr/src/md/windows/w95io.c b/pr/src/md/windows/w95io.c index 6e969a98..d80736fe 100644 --- a/pr/src/md/windows/w95io.c +++ b/pr/src/md/windows/w95io.c @@ -24,10 +24,30 @@ #include "primpl.h" #include <direct.h> +#include <mbstring.h> + struct _MDLock _pr_ioq_lock; /* + * NSPR-to-NT access right mapping table for files. + */ +static DWORD fileAccessTable[] = { + FILE_GENERIC_READ, + FILE_GENERIC_WRITE, + FILE_GENERIC_EXECUTE +}; + +/* + * NSPR-to-NT access right mapping table for directories. + */ +static DWORD dirAccessTable[] = { + FILE_GENERIC_READ, + FILE_GENERIC_WRITE|FILE_DELETE_CHILD, + FILE_GENERIC_EXECUTE +}; + +/* * The NSPR epoch (00:00:00 1 Jan 1970 UTC) in FILETIME. * We store the value in a PRTime variable for convenience. * This constant is used by _PR_FileTimeToPRTime(). @@ -72,6 +92,8 @@ _PR_MD_INIT_IO() PR_ASSERT(filetime.prt == _pr_filetime_offset); } #endif /* DEBUG */ + + _PR_NT_InitSids(); } PRStatus @@ -182,6 +204,67 @@ _PR_MD_OPEN(const char *name, PRIntn osflags, int mode) } PRInt32 +_PR_MD_OPEN_FILE(const char *name, PRIntn osflags, int mode) +{ + HANDLE file; + PRInt32 access = 0; + PRInt32 flags = 0; + PRInt32 flag6 = 0; + SECURITY_ATTRIBUTES sa; + LPSECURITY_ATTRIBUTES lpSA = NULL; + PSECURITY_DESCRIPTOR pSD = NULL; + PACL pACL = NULL; + + if (osflags & PR_CREATE_FILE) { + if (_PR_NT_MakeSecurityDescriptorACL(mode, fileAccessTable, + &pSD, &pACL) == PR_SUCCESS) { + sa.nLength = sizeof(sa); + sa.lpSecurityDescriptor = pSD; + sa.bInheritHandle = FALSE; + lpSA = &sa; + } + } + + if (osflags & PR_SYNC) flag6 = FILE_FLAG_WRITE_THROUGH; + + if (osflags & PR_RDONLY || osflags & PR_RDWR) + access |= GENERIC_READ; + if (osflags & PR_WRONLY || osflags & PR_RDWR) + access |= GENERIC_WRITE; + + if ( osflags & PR_CREATE_FILE && osflags & PR_EXCL ) + flags = CREATE_NEW; + else if (osflags & PR_CREATE_FILE) { + if (osflags & PR_TRUNCATE) + flags = CREATE_ALWAYS; + else + flags = OPEN_ALWAYS; + } else { + if (osflags & PR_TRUNCATE) + flags = TRUNCATE_EXISTING; + else + flags = OPEN_EXISTING; + } + + file = CreateFile(name, + access, + FILE_SHARE_READ|FILE_SHARE_WRITE, + lpSA, + flags, + flag6, + NULL); + if (lpSA != NULL) { + _PR_NT_FreeSecurityDescriptorACL(pSD, pACL); + } + if (file == INVALID_HANDLE_VALUE) { + _PR_MD_MAP_OPEN_ERROR(GetLastError()); + return -1; + } + + return (PRInt32)file; +} + +PRInt32 _PR_MD_READ(PRFileDesc *fd, void *buf, PRInt32 len) { PRUint32 bytes; @@ -353,12 +436,13 @@ _MD_CloseFile(PRInt32 osfd) void FlipSlashes(char *cp, int len) { while (--len >= 0) { - if (cp[0] == '/') { - cp[0] = PR_DIRECTORY_SEPARATOR; - } - cp++; + if (cp[0] == '/') { + cp[0] = PR_DIRECTORY_SEPARATOR; + } + cp = _mbsinc(cp); } -} +} /* end FlipSlashes() */ + /* ** @@ -661,7 +745,7 @@ _PR_MD_GETFILEINFO64(const char *fn, PRFileInfo64 *info) * FindFirstFile() expands wildcard characters. So * we make sure the pathname contains no wildcard. */ - if (NULL != strpbrk(fn, "?*")) { + if (NULL != _mbspbrk(fn, "?*")) { PR_SetError(PR_FILE_NOT_FOUND_ERROR, 0); return -1; } @@ -683,7 +767,7 @@ _PR_MD_GETFILEINFO64(const char *fn, PRFileInfo64 *info) * If the pathname does not contain ., \, and /, it cannot be * a root directory or a pathname that ends in a slash. */ - if (NULL == strpbrk(fn, ".\\/")) { + if (NULL == _mbspbrk(fn, ".\\/")) { _PR_MD_MAP_OPENDIR_ERROR(GetLastError()); return -1; } @@ -866,6 +950,34 @@ _PR_MD_MKDIR(const char *name, PRIntn mode) } PRInt32 +_PR_MD_MAKE_DIR(const char *name, PRIntn mode) +{ + BOOL rv; + SECURITY_ATTRIBUTES sa; + LPSECURITY_ATTRIBUTES lpSA = NULL; + PSECURITY_DESCRIPTOR pSD = NULL; + PACL pACL = NULL; + + if (_PR_NT_MakeSecurityDescriptorACL(mode, dirAccessTable, + &pSD, &pACL) == PR_SUCCESS) { + sa.nLength = sizeof(sa); + sa.lpSecurityDescriptor = pSD; + sa.bInheritHandle = FALSE; + lpSA = &sa; + } + rv = CreateDirectory(name, lpSA); + if (lpSA != NULL) { + _PR_NT_FreeSecurityDescriptorACL(pSD, pACL); + } + if (rv) { + return 0; + } else { + _PR_MD_MAP_MKDIR_ERROR(GetLastError()); + return -1; + } +} + +PRInt32 _PR_MD_RMDIR(const char *name) { if (RemoveDirectory(name)) { diff --git a/pr/src/md/windows/w95thred.c b/pr/src/md/windows/w95thred.c index 69ab1cd9..2625ceea 100644 --- a/pr/src/md/windows/w95thred.c +++ b/pr/src/md/windows/w95thred.c @@ -48,6 +48,8 @@ _PR_MD_EARLY_INIT() void _PR_MD_CLEANUP_BEFORE_EXIT(void) { + _PR_NT_FreeSids(); + WSACleanup(); #ifndef _PR_USE_STATIC_TLS diff --git a/pr/src/md/windows/win32_errors.c b/pr/src/md/windows/win32_errors.c index 0e73c560..99427933 100644 --- a/pr/src/md/windows/win32_errors.c +++ b/pr/src/md/windows/win32_errors.c @@ -142,6 +142,9 @@ void _MD_win32_map_default_error(PRInt32 err) case ERROR_OPEN_FILES: prError = PR_IO_ERROR; break; + case ERROR_OPERATION_ABORTED: + prError = PR_OPERATION_ABORTED_ERROR; + break; case ERROR_OUTOFMEMORY: prError = PR_INSUFFICIENT_RESOURCES_ERROR; break; diff --git a/pr/src/misc/prerr.c b/pr/src/misc/prerr.c index 7b320be7..3f366760 100644 --- a/pr/src/misc/prerr.c +++ b/pr/src/misc/prerr.c @@ -88,7 +88,7 @@ static const struct PRErrorMessage text[] = { {"PR_END_OF_FILE_ERROR", "Encountered end of file"}, {"PR_FILE_SEEK_ERROR", "Seek error"}, {"PR_FILE_IS_BUSY_ERROR", "The file is busy"}, - {"PR_RESERVED_ERROR_5935", "Reserved Error Code -5935"}, + {"PR_OPERATION_ABORTED_ERROR", "The I/O operation was aborted"}, {"PR_IN_PROGRESS_ERROR", "Operation is still in progress (probably a non-blocking connect)"}, {"PR_ALREADY_INITIATED_ERROR", "Operation has already been initiated (probably a non-blocking connect)"}, {"PR_GROUP_EMPTY_ERROR", "The wait group is empty"}, diff --git a/pr/src/misc/prerr.et b/pr/src/misc/prerr.et index 2f0a6f02..c04440f0 100644 --- a/pr/src/misc/prerr.et +++ b/pr/src/misc/prerr.et @@ -99,7 +99,7 @@ ec PR_NO_MORE_FILES_ERROR, "No more entries in the directory" ec PR_END_OF_FILE_ERROR, "Encountered end of file" ec PR_FILE_SEEK_ERROR, "Seek error" ec PR_FILE_IS_BUSY_ERROR, "The file is busy" -ec PR_RESERVED_ERROR_5935, "Reserved Error Code -5935" +ec PR_OPERATION_ABORTED_ERROR, "The I/O operation was aborted" ec PR_IN_PROGRESS_ERROR, "Operation is still in progress (probably a non-blocking connect)" ec PR_ALREADY_INITIATED_ERROR, diff --git a/pr/src/misc/prerr.properties b/pr/src/misc/prerr.properties index 07d58f08..5987967a 100644 --- a/pr/src/misc/prerr.properties +++ b/pr/src/misc/prerr.properties @@ -82,7 +82,7 @@ PR_NO_MORE_FILES_ERROR=No more entries in the directory PR_END_OF_FILE_ERROR=Encountered end of file PR_FILE_SEEK_ERROR=Seek error PR_FILE_IS_BUSY_ERROR=The file is busy -PR_RESERVED_ERROR_5935=Reserved Error Code -5935 +PR_OPERATION_ABORTED_ERROR=The I/O operation was aborted PR_IN_PROGRESS_ERROR=Operation is still in progress (probably a non-blocking connect) PR_ALREADY_INITIATED_ERROR=Operation has already been initiated (probably a non-blocking connect) PR_GROUP_EMPTY_ERROR=The wait group is empty diff --git a/pr/src/misc/prerror.c b/pr/src/misc/prerror.c index ed46c1ba..40925696 100644 --- a/pr/src/misc/prerror.c +++ b/pr/src/misc/prerror.c @@ -33,12 +33,6 @@ PR_IMPLEMENT(PRInt32) PR_GetOSError() return thread->osErrorCode; } -PR_IMPLEMENT(const char*) PR_GetErrorString() -{ - PRThread *thread = PR_GetCurrentThread(); - return thread->errorString; -} - PR_IMPLEMENT(void) PR_SetError(PRErrorCode code, PRInt32 osErr) { PRThread *thread = PR_GetCurrentThread(); diff --git a/pr/src/misc/prinit.c b/pr/src/misc/prinit.c index 57fb1c9a..3cdefe35 100644 --- a/pr/src/misc/prinit.c +++ b/pr/src/misc/prinit.c @@ -78,11 +78,11 @@ PR_IMPLEMENT(PRBool) PR_VersionCheck(const char *importedVersion) /* ** This is the secret handshake algorithm. ** - ** This release (3.1) is backward compatible with - ** all the previous releases ("2.1 19980529", "3.0", - ** "3.0.x"). It is not compatible with future - ** releases or patches. So this release has a - ** simple version compatibility check algorithm. + ** This release has a simple version compatibility + ** check algorithm. This release is not backward + ** compatible with previous major releases. It is + ** not compatible with future major, minor, or + ** patch releases. */ int vmajor = 0, vminor = 0, vpatch = 0; const char *ptr = importedVersion; @@ -106,7 +106,7 @@ PR_IMPLEMENT(PRBool) PR_VersionCheck(const char *importedVersion) } } - if (vmajor > PR_VMAJOR) { + if (vmajor != PR_VMAJOR) { return PR_FALSE; } if (vmajor == PR_VMAJOR && vminor > PR_VMINOR) { @@ -144,6 +144,10 @@ static void _pr_SetNativeThreadsOnlyMode(void) } #endif +#if !defined(_PR_INET6) || defined(_PR_INET6_PROBE) +extern PRStatus _pr_init_ipv6(); +#endif + static void _PR_InitStuff(void) { @@ -220,6 +224,10 @@ static void _PR_InitStuff(void) nspr_InitializePRErrorTable(); +#if !defined(_PR_INET6) || defined(_PR_INET6_PROBE) + _pr_init_ipv6(); +#endif + _PR_MD_FINAL_INIT(); } diff --git a/pr/src/misc/prnetdb.c b/pr/src/misc/prnetdb.c index f3e65ff2..f31374b3 100644 --- a/pr/src/misc/prnetdb.c +++ b/pr/src/misc/prnetdb.c @@ -95,13 +95,54 @@ static sigset_t timer_set; PRLock* _getproto_lock = NULL; #endif -#if defined(_PR_INET6) -PRBool _pr_ipv6_enabled = PR_FALSE; -#if defined(AIX) -const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; -const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT; -#endif /* AIX */ -#endif /* _PR_INET6 */ +#if defined(_PR_INET6_PROBE) +PR_EXTERN(PRBool) _pr_ipv6_is_present; +#endif + +#define _PR_IN6_IS_ADDR_UNSPECIFIED(a) \ + (((a)->pr_s6_addr32[0] == 0) && \ + ((a)->pr_s6_addr32[1] == 0) && \ + ((a)->pr_s6_addr32[2] == 0) && \ + ((a)->pr_s6_addr32[3] == 0)) + +#define _PR_IN6_IS_ADDR_LOOPBACK(a) \ + (((a)->pr_s6_addr32[0] == 0) && \ + ((a)->pr_s6_addr32[1] == 0) && \ + ((a)->pr_s6_addr32[2] == 0) && \ + ((a)->pr_s6_addr[12] == 0) && \ + ((a)->pr_s6_addr[13] == 0) && \ + ((a)->pr_s6_addr[14] == 0) && \ + ((a)->pr_s6_addr[15] == 0x1U)) + +const PRIPv6Addr _pr_in6addr_any = {{{ 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0 }}}; + +const PRIPv6Addr _pr_in6addr_loopback = {{{ 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0x1U }}}; +/* + * The values at bytes 10 and 11 are compared using pointers to + * 8-bit fields, and not 32-bit fields, to make the comparison work on + * both big-endian and little-endian systems + */ + +#define _PR_IN6_IS_ADDR_V4MAPPED(a) \ + (((a)->pr_s6_addr32[0] == 0) && \ + ((a)->pr_s6_addr32[1] == 0) && \ + ((a)->pr_s6_addr[8] == 0) && \ + ((a)->pr_s6_addr[9] == 0) && \ + ((a)->pr_s6_addr[10] == 0xff) && \ + ((a)->pr_s6_addr[11] == 0xff)) + +#define _PR_IN6_IS_ADDR_V4COMPAT(a) \ + (((a)->pr_s6_addr32[0] == 0) && \ + ((a)->pr_s6_addr32[1] == 0) && \ + ((a)->pr_s6_addr32[2] == 0)) + +#define _PR_IN6_V4MAPPED_TO_IPADDR(a) ((a)->pr_s6_addr32[3]) void _PR_InitNet(void) { @@ -122,31 +163,6 @@ void _PR_InitNet(void) #if !defined(_PR_HAVE_GETPROTO_R) _getproto_lock = PR_NewLock(); #endif - -} - -PR_IMPLEMENT(PRStatus) PR_SetIPv6Enable(PRBool itIs) -{ -#if defined(XP_MAC) -#pragma unused (itIs) -#endif - -#if defined(_PR_INET6) - _pr_ipv6_enabled = itIs; - return PR_SUCCESS; -#else /* defined(_PR_INET6) */ - PR_SetError(PR_PROTOCOL_NOT_SUPPORTED_ERROR, 0); - return PR_FAILURE; -#endif /* defined(_PR_INET6) */ -} /* PR_SetIPv6Enable */ - -PR_IMPLEMENT(PRStatus) PR_GetHostName(char *name, PRUint32 namelen) -{ -#if defined(DEBUG) - static PRBool warn = PR_TRUE; - if (warn) warn = _PR_Obsolete("PR_GetHostName()", "PR_GetSystemInfo()"); -#endif - return PR_GetSystemInfo(PR_SI_HOSTNAME, name, namelen); } /* @@ -174,8 +190,6 @@ static char *Alloc(PRIntn amount, char **bufp, PRIntn *buflenp, PRIntn align) return buf; } -#if defined(_PR_INET6) - typedef enum _PRIPAddrConversion { _PRIPAddrNoConversion, _PRIPAddrIPv4Mapped, @@ -190,7 +204,7 @@ static void MakeIPv4MappedAddr(const char *v4, char *v6) memset(v6, 0, 10); memset(v6 + 10, 0xff, 2); memcpy(v6 + 12, v4, 4); - PR_ASSERT(IN6_IS_ADDR_V4MAPPED((struct in6_addr *) v6)); + PR_ASSERT(_PR_IN6_IS_ADDR_V4MAPPED(((PRIPv6Addr *) v6))); } /* @@ -200,47 +214,42 @@ static void MakeIPv4CompatAddr(const char *v4, char *v6) { memset(v6, 0, 12); memcpy(v6 + 12, v4, 4); - PR_ASSERT(IN6_IS_ADDR_V4COMPAT((struct in6_addr *) v6)); + PR_ASSERT(_PR_IN6_IS_ADDR_V4COMPAT(((PRIPv6Addr *) v6))); } -#endif /* _PR_INET6 */ - /* ** Copy a hostent, and all of the memory that it refers to into ** (hopefully) stacked buffers. */ static PRStatus CopyHostent( struct hostent *from, - char *buf, - PRIntn bufsize, -#if defined(_PR_INET6) + char **buf, + PRIntn *bufsize, _PRIPAddrConversion conversion, -#endif PRHostEnt *to) { PRIntn len, na; char **ap; - /* Do the easy stuff */ -#if defined(_PR_INET6) if (conversion != _PRIPAddrNoConversion && from->h_addrtype == AF_INET) { PR_ASSERT(from->h_length == 4); - to->h_addrtype = AF_INET6; + to->h_addrtype = PR_AF_INET6; to->h_length = 16; } else { - to->h_addrtype = from->h_addrtype; +#if defined(_PR_INET6) || defined(_PR_INET6_PROBE) + if (AF_INET6 == from->h_addrtype) + to->h_addrtype = PR_AF_INET6; + else +#endif + to->h_addrtype = from->h_addrtype; to->h_length = from->h_length; } -#else - to->h_addrtype = from->h_addrtype; - to->h_length = from->h_length; -#endif /* Copy the official name */ if (!from->h_name) return PR_FAILURE; len = strlen(from->h_name) + 1; - to->h_name = Alloc(len, &buf, &bufsize, 0); + to->h_name = Alloc(len, buf, bufsize, 0); if (!to->h_name) return PR_FAILURE; memcpy(to->h_name, from->h_name, len); @@ -251,7 +260,7 @@ static PRStatus CopyHostent( for (na = 1, ap = from->h_aliases; *ap != 0; na++, ap++){;} /* nothing to execute */ } to->h_aliases = (char**)Alloc( - na * sizeof(char*), &buf, &bufsize, sizeof(char**)); + na * sizeof(char*), buf, bufsize, sizeof(char**)); if (!to->h_aliases) return PR_FAILURE; /* Copy the aliases, one at a time */ @@ -260,7 +269,7 @@ static PRStatus CopyHostent( } else { for (na = 0, ap = from->h_aliases; *ap != 0; na++, ap++) { len = strlen(*ap) + 1; - to->h_aliases[na] = Alloc(len, &buf, &bufsize, 0); + to->h_aliases[na] = Alloc(len, buf, bufsize, 0); if (!to->h_aliases[na]) return PR_FAILURE; memcpy(to->h_aliases[na], *ap, len); } @@ -270,14 +279,13 @@ static PRStatus CopyHostent( /* Count the addresses, then allocate storage for the pointers */ for (na = 1, ap = from->h_addr_list; *ap != 0; na++, ap++){;} /* nothing to execute */ to->h_addr_list = (char**)Alloc( - na * sizeof(char*), &buf, &bufsize, sizeof(char**)); + na * sizeof(char*), buf, bufsize, sizeof(char**)); if (!to->h_addr_list) return PR_FAILURE; /* Copy the addresses, one at a time */ for (na = 0, ap = from->h_addr_list; *ap != 0; na++, ap++) { - to->h_addr_list[na] = Alloc(to->h_length, &buf, &bufsize, 0); + to->h_addr_list[na] = Alloc(to->h_length, buf, bufsize, 0); if (!to->h_addr_list[na]) return PR_FAILURE; -#if defined(_PR_INET6) if (conversion != _PRIPAddrNoConversion && from->h_addrtype == AF_INET) { if (conversion == _PRIPAddrIPv4Mapped) { @@ -289,9 +297,6 @@ static PRStatus CopyHostent( } else { memcpy(to->h_addr_list[na], *ap, to->h_length); } -#else - memcpy(to->h_addr_list[na], *ap, to->h_length); -#endif } to->h_addr_list[na] = 0; return PR_SUCCESS; @@ -345,9 +350,6 @@ PR_IMPLEMENT(PRStatus) PR_GetHostByName( #ifdef XP_UNIX sigset_t oldset; #endif -#if defined(_PR_INET6) && defined(_PR_HAVE_GETIPNODEBYNAME) - int error_num; -#endif if (!_pr_initialized) _PR_ImplicitInitialization(); @@ -356,60 +358,22 @@ PR_IMPLEMENT(PRStatus) PR_GetHostByName( #endif LOCK_DNS(); -#ifdef _PR_INET6 - if (_pr_ipv6_enabled) - { -#ifdef _PR_HAVE_GETHOSTBYNAME2 - h = gethostbyname2(name, AF_INET6); - if (NULL == h) - { - h = gethostbyname2(name, AF_INET); - } -#elif defined(_PR_HAVE_GETIPNODEBYNAME) - h = getipnodebyname(name, AF_INET6, AI_DEFAULT, &error_num); -#else -#error "Unknown name-to-address translation function" -#endif - } - else - { -#ifdef XP_OS2_VACPP - h = gethostbyname((char *)name); -#else - h = gethostbyname(name); -#endif - } -#else #ifdef XP_OS2_VACPP h = gethostbyname((char *)name); #else h = gethostbyname(name); #endif -#endif /* _PR_INET6 */ if (NULL == h) { -#if defined(_PR_INET6) && defined(_PR_HAVE_GETIPNODEBYNAME) - PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, error_num); -#else PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, _MD_GETHOST_ERRNO()); -#endif } else { -#if defined(_PR_INET6) _PRIPAddrConversion conversion = _PRIPAddrNoConversion; - - if (_pr_ipv6_enabled) conversion = _PRIPAddrIPv4Mapped; - rv = CopyHostent(h, buf, bufsize, conversion, hp); -#else - rv = CopyHostent(h, buf, bufsize, hp); -#endif + rv = CopyHostent(h, &buf, &bufsize, conversion, hp); if (PR_SUCCESS != rv) PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0); -#if defined(_PR_INET6) && defined(_PR_HAVE_GETIPNODEBYNAME) - freehostent(h); -#endif } UNLOCK_DNS(); #ifdef XP_UNIX @@ -418,40 +382,40 @@ PR_IMPLEMENT(PRStatus) PR_GetHostByName( return rv; } +#if defined(_PR_INET6_PROBE) && defined(_PR_HAVE_GETIPNODEBYNAME) +typedef struct hostent * (*_pr_getipnodebyname_t)(const char *, int, + int, int *); +typedef struct hostent * (*_pr_getipnodebyaddr_t)(const void *, size_t, + int, int *); +typedef void (*_pr_freehostent_t)(struct hostent *); +extern void * _pr_getipnodebyname_fp; +extern void * _pr_getipnodebyaddr_fp; +extern void * _pr_freehostent_fp; +#endif + PR_IMPLEMENT(PRStatus) PR_GetIPNodeByName( const char *name, PRUint16 af, PRIntn flags, char *buf, PRIntn bufsize, PRHostEnt *hp) { - struct hostent *h; + struct hostent *h = 0; PRStatus rv = PR_FAILURE; #ifdef XP_UNIX sigset_t oldset; #endif -#if defined(_PR_INET6) && defined(_PR_HAVE_GETIPNODEBYNAME) +#if defined(_PR_HAVE_GETIPNODEBYNAME) + PRUint16 md_af = af; int error_num; + int tmp_flags = 0; +#endif +#if defined(_PR_HAVE_GETHOSTBYNAME2) + PRBool did_af_inet = PR_FALSE; + char **new_addr_list; #endif if (!_pr_initialized) _PR_ImplicitInitialization(); -#if defined(_PR_INET6) - PR_ASSERT(af == AF_INET || af == AF_INET6); - if (af != AF_INET && af != AF_INET6) { - PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); - return PR_FAILURE; - } -#else - PR_ASSERT(af == AF_INET); - if (af != AF_INET) { - PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); - return PR_FAILURE; - } -#endif - - /* - * Flags other than PR_AI_DEFAULT are not yet supported. - */ - PR_ASSERT(flags == PR_AI_DEFAULT); - if (flags != PR_AI_DEFAULT) { + PR_ASSERT(af == PR_AF_INET || af == PR_AF_INET6); + if (af != PR_AF_INET && af != PR_AF_INET6) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return PR_FAILURE; } @@ -461,25 +425,48 @@ PR_IMPLEMENT(PRStatus) PR_GetIPNodeByName( #endif LOCK_DNS(); +#if defined(_PR_HAVE_GETIPNODEBYNAME) + if (flags & PR_AI_V4MAPPED) + tmp_flags |= AI_V4MAPPED; + if (flags & PR_AI_ADDRCONFIG) + tmp_flags |= AI_ADDRCONFIG; + if (flags & PR_AI_ALL) + tmp_flags |= AI_ALL; + if (af == PR_AF_INET6) + md_af = AF_INET6; + else + md_af = af; +#endif + #ifdef _PR_INET6 #ifdef _PR_HAVE_GETHOSTBYNAME2 - if (af == AF_INET6) + if (af == PR_AF_INET6) { - h = gethostbyname2(name, af); - if (NULL == h) +#ifdef _PR_INET6_PROBE + if (_pr_ipv6_is_present == PR_TRUE) +#endif + h = gethostbyname2(name, AF_INET6); + if ((NULL == h) && (flags & PR_AI_V4MAPPED)) { + did_af_inet = PR_TRUE; h = gethostbyname2(name, AF_INET); } } else { + did_af_inet = PR_TRUE; h = gethostbyname2(name, af); } #elif defined(_PR_HAVE_GETIPNODEBYNAME) - h = getipnodebyname(name, af, AI_DEFAULT, &error_num); + h = getipnodebyname(name, md_af, tmp_flags, &error_num); #else #error "Unknown name-to-address translation function" -#endif +#endif /* _PR_HAVE_GETHOSTBYNAME2 */ +#elif defined(_PR_INET6_PROBE) && defined(_PR_HAVE_GETIPNODEBYNAME) + if (_pr_ipv6_is_present == PR_TRUE) + h = (*((_pr_getipnodebyname_t)_pr_getipnodebyname_fp))(name, md_af, tmp_flags, &error_num); + else + h = gethostbyname(name); #else /* _PR_INET6 */ #ifdef XP_OS2_VACPP h = gethostbyname((char *)name); @@ -492,26 +479,62 @@ PR_IMPLEMENT(PRStatus) PR_GetIPNodeByName( { #if defined(_PR_INET6) && defined(_PR_HAVE_GETIPNODEBYNAME) PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, error_num); +#elif defined(_PR_INET6_PROBE) && defined(_PR_HAVE_GETIPNODEBYNAME) + if (_pr_ipv6_is_present == PR_TRUE) + PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, error_num); + else + PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, _MD_GETHOST_ERRNO()); #else PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, _MD_GETHOST_ERRNO()); #endif } else { -#if defined(_PR_INET6) _PRIPAddrConversion conversion = _PRIPAddrNoConversion; - if (af == AF_INET6) conversion = _PRIPAddrIPv4Mapped; - rv = CopyHostent(h, buf, bufsize, conversion, hp); -#else - rv = CopyHostent(h, buf, bufsize, hp); -#endif + if (af == PR_AF_INET6) conversion = _PRIPAddrIPv4Mapped; + rv = CopyHostent(h, &buf, &bufsize, conversion, hp); if (PR_SUCCESS != rv) PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0); #if defined(_PR_INET6) && defined(_PR_HAVE_GETIPNODEBYNAME) freehostent(h); +#elif defined(_PR_INET6_PROBE) && defined(_PR_HAVE_GETIPNODEBYNAME) + if (_pr_ipv6_is_present == PR_TRUE) + (*((_pr_freehostent_t)_pr_freehostent_fp))(h); +#endif +#if defined(_PR_INET6) && defined(_PR_HAVE_GETHOSTBYNAME2) + if ((flags & PR_AI_V4MAPPED) && (flags & (PR_AI_ALL|PR_AI_ADDRCONFIG)) + && !did_af_inet && (h = gethostbyname2(name, AF_INET)) != 0) { + /* Append the V4 addresses to the end of the list */ + PRIntn na, na_old; + char **ap; + + /* Count the addresses, then grow storage for the pointers */ + for (na_old = 0, ap = hp->h_addr_list; *ap != 0; na_old++, ap++) + {;} /* nothing to execute */ + for (na = na_old + 1, ap = h->h_addr_list; *ap != 0; na++, ap++) + {;} /* nothing to execute */ + new_addr_list = (char**)Alloc( + na * sizeof(char*), &buf, &bufsize, sizeof(char**)); + if (!new_addr_list) return PR_FAILURE; + + /* Copy the V6 addresses, one at a time */ + for (na = 0, ap = hp->h_addr_list; *ap != 0; na++, ap++) { + new_addr_list[na] = hp->h_addr_list[na]; + } + hp->h_addr_list = new_addr_list; + + /* Copy the V4 addresses, one at a time */ + for (ap = h->h_addr_list; *ap != 0; na++, ap++) { + hp->h_addr_list[na] = Alloc(hp->h_length, &buf, &bufsize, 0); + if (!hp->h_addr_list[na]) return PR_FAILURE; + MakeIPv4MappedAddr(*ap, hp->h_addr_list[na]); + } + hp->h_addr_list[na] = 0; + } #endif } + UNLOCK_DNS(); #ifdef XP_UNIX ENABLECLOCK(&oldset); @@ -525,11 +548,13 @@ PR_IMPLEMENT(PRStatus) PR_GetHostByAddr( struct hostent *h; PRStatus rv = PR_FAILURE; const void *addr; + PRUint32 tmp_ip; int addrlen; + PRInt32 af; #ifdef XP_UNIX sigset_t oldset; #endif -#if defined(_PR_INET6) && defined(_PR_HAVE_GETIPNODEBYADDR) +#if defined(_PR_HAVE_GETIPNODEBYADDR) int error_num; #endif @@ -539,56 +564,101 @@ PR_IMPLEMENT(PRStatus) PR_GetHostByAddr( DISABLECLOCK(&oldset); #endif LOCK_DNS(); -#if defined(_PR_INET6) - if (hostaddr->raw.family == AF_INET6) + if (hostaddr->raw.family == PR_AF_INET6) { - addr = &hostaddr->ipv6.ip; - addrlen = sizeof(hostaddr->ipv6.ip); +#if defined(_PR_INET6_PROBE) + if (_pr_ipv6_is_present == PR_TRUE) + af = AF_INET6; + else + af = AF_INET; +#elif defined(_PR_INET6) + af = AF_INET6; +#else + af = AF_INET; +#endif } else -#endif /* defined(_PR_INET6) */ { PR_ASSERT(hostaddr->raw.family == AF_INET); + af = AF_INET; + } + if (hostaddr->raw.family == PR_AF_INET6) { +#if defined(_PR_INET6) || defined(_PR_INET6_PROBE) + if (af == AF_INET6) { + addr = &hostaddr->ipv6.ip; + addrlen = sizeof(hostaddr->ipv6.ip); + } + else +#endif + { + PR_ASSERT(af == AF_INET); + if (!_PR_IN6_IS_ADDR_V4MAPPED(&hostaddr->ipv6.ip)) { + PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); + return rv; + } + tmp_ip = _PR_IN6_V4MAPPED_TO_IPADDR((PRIPv6Addr *) + &hostaddr->ipv6.ip); + addr = &tmp_ip; + addrlen = sizeof(tmp_ip); + } + } else { + PR_ASSERT(hostaddr->raw.family == AF_INET); + PR_ASSERT(af == AF_INET); addr = &hostaddr->inet.ip; addrlen = sizeof(hostaddr->inet.ip); } -#if defined(_PR_INET6) && defined(_PR_HAVE_GETIPNODEBYADDR) - h = getipnodebyaddr(addr, addrlen, hostaddr->raw.family, &error_num); -#else + +#if defined(_PR_HAVE_GETIPNODEBYADDR) && defined(_PR_INET6) + h = getipnodebyaddr(addr, addrlen, af, &error_num); +#elif defined(_PR_HAVE_GETIPNODEBYADDR) && defined(_PR_INET6_PROBE) + if (_pr_ipv6_is_present == PR_TRUE) + h = (*((_pr_getipnodebyaddr_t)_pr_getipnodebyaddr_fp))(addr, addrlen, + af, &error_num); + else + h = gethostbyaddr(addr, addrlen, af); +#else /* _PR_HAVE_GETIPNODEBYADDR */ #ifdef XP_OS2_VACPP - h = gethostbyaddr((char *)addr, addrlen, hostaddr->raw.family); + h = gethostbyaddr((char *)addr, addrlen, af); #else - h = gethostbyaddr(addr, addrlen, hostaddr->raw.family); + h = gethostbyaddr(addr, addrlen, af); #endif -#endif /* _PR_INET6 && _PR_HAVE_GETIPNODEBYADDR */ +#endif /* _PR_HAVE_GETIPNODEBYADDR */ if (NULL == h) { #if defined(_PR_INET6) && defined(_PR_HAVE_GETIPNODEBYADDR) PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, error_num); +#elif defined(_PR_INET6_PROBE) && defined(_PR_HAVE_GETIPNODEBYADDR) + if (_pr_ipv6_is_present == PR_TRUE) + PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, error_num); + else + PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, _MD_GETHOST_ERRNO()); #else PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, _MD_GETHOST_ERRNO()); #endif } else { -#if defined(_PR_INET6) _PRIPAddrConversion conversion = _PRIPAddrNoConversion; - if (hostaddr->raw.family == AF_INET6) { - if (IN6_IS_ADDR_V4MAPPED((struct in6_addr*)addr)) { - conversion = _PRIPAddrIPv4Mapped; - } else if (IN6_IS_ADDR_V4COMPAT((struct in6_addr*)addr)) { - conversion = _PRIPAddrIPv4Compat; + if (hostaddr->raw.family == PR_AF_INET6) { + if (af == AF_INET) { + if (_PR_IN6_IS_ADDR_V4MAPPED((PRIPv6Addr*) + &hostaddr->ipv6.ip)) { + conversion = _PRIPAddrIPv4Mapped; + } else if (_PR_IN6_IS_ADDR_V4COMPAT((PRIPv6Addr *) + &hostaddr->ipv6.ip)) { + conversion = _PRIPAddrIPv4Compat; + } } } - rv = CopyHostent(h, buf, bufsize, conversion, hostentry); -#else - rv = CopyHostent(h, buf, bufsize, hostentry); -#endif + rv = CopyHostent(h, &buf, &bufsize, conversion, hostentry); if (PR_SUCCESS != rv) { PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0); } #if defined(_PR_INET6) && defined(_PR_HAVE_GETIPNODEBYADDR) freehostent(h); +#elif defined(_PR_INET6_PROBE) && defined(_PR_HAVE_GETIPNODEBYADDR) + if (_pr_ipv6_is_present == PR_TRUE) + (*((_pr_freehostent_t)_pr_freehostent_fp))(h); #endif } UNLOCK_DNS(); @@ -807,9 +877,11 @@ PR_IMPLEMENT(PRUintn) PR_NetAddrSize(const PRNetAddr* addr) */ if (AF_INET == addr->raw.family) addrsize = sizeof(addr->inet); + else if (PR_AF_INET6 == addr->raw.family) #if defined(_PR_INET6) - else if (AF_INET6 == addr->raw.family) addrsize = sizeof(struct sockaddr_in6); +#else + addrsize = sizeof(addr->ipv6); #endif #if defined(XP_UNIX) else if (AF_UNIX == addr->raw.family) @@ -829,14 +901,14 @@ PR_IMPLEMENT(PRIntn) PR_EnumerateHostEnt( else { address->raw.family = hostEnt->h_addrtype; -#if defined(_PR_INET6) - if (AF_INET6 == hostEnt->h_addrtype) + if (PR_AF_INET6 == hostEnt->h_addrtype) { address->ipv6.port = htons(port); + address->ipv6.flowinfo = 0; + address->ipv6.scope_id = 0; memcpy(&address->ipv6.ip, addr, hostEnt->h_length); } else -#endif /* defined(_PR_INET6) */ { PR_ASSERT(AF_INET == hostEnt->h_addrtype); address->inet.port = htons(port); @@ -852,46 +924,22 @@ PR_IMPLEMENT(PRStatus) PR_InitializeNetAddr( PRStatus rv = PR_SUCCESS; if (!_pr_initialized) _PR_ImplicitInitialization(); -#if defined(_PR_INET6) - if (_pr_ipv6_enabled) - { - addr->ipv6.family = AF_INET6; - addr->ipv6.port = htons(port); - switch (val) - { - case PR_IpAddrNull: - break; /* don't overwrite the address */ - case PR_IpAddrAny: - addr->ipv6.ip = in6addr_any; - break; - case PR_IpAddrLoopback: - addr->ipv6.ip = in6addr_loopback; - break; - default: - PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); - rv = PR_FAILURE; - } - } - else -#endif /* defined(_PR_INET6) */ - { - addr->inet.family = AF_INET; - addr->inet.port = htons(port); - switch (val) - { - case PR_IpAddrNull: - break; /* don't overwrite the address */ - case PR_IpAddrAny: - addr->inet.ip = htonl(INADDR_ANY); - break; - case PR_IpAddrLoopback: - addr->inet.ip = htonl(INADDR_LOOPBACK); - break; - default: - PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); - rv = PR_FAILURE; - } - } + addr->inet.family = AF_INET; + addr->inet.port = htons(port); + switch (val) + { + case PR_IpAddrNull: + break; /* don't overwrite the address */ + case PR_IpAddrAny: + addr->inet.ip = htonl(INADDR_ANY); + break; + case PR_IpAddrLoopback: + addr->inet.ip = htonl(INADDR_LOOPBACK); + break; + default: + PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); + rv = PR_FAILURE; + } return rv; } /* PR_InitializeNetAddr */ @@ -902,19 +950,20 @@ PR_IMPLEMENT(PRStatus) PR_SetNetAddr( if (!_pr_initialized) _PR_ImplicitInitialization(); addr->raw.family = af; -#if defined(_PR_INET6) - if (af == AF_INET6) + if (af == PR_AF_INET6) { addr->ipv6.port = htons(port); + addr->ipv6.flowinfo = 0; + addr->ipv6.scope_id = 0; switch (val) { case PR_IpAddrNull: break; /* don't overwrite the address */ case PR_IpAddrAny: - addr->ipv6.ip = in6addr_any; + addr->ipv6.ip = _pr_in6addr_any; break; case PR_IpAddrLoopback: - addr->ipv6.ip = in6addr_loopback; + addr->ipv6.ip = _pr_in6addr_loopback; break; default: PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); @@ -922,7 +971,6 @@ PR_IMPLEMENT(PRStatus) PR_SetNetAddr( } } else -#endif /* defined(_PR_INET6) */ { addr->inet.port = htons(port); switch (val) @@ -946,19 +994,28 @@ PR_IMPLEMENT(PRStatus) PR_SetNetAddr( PR_IMPLEMENT(PRBool) PR_IsNetAddrType(const PRNetAddr *addr, PRNetAddrValue val) { -#if defined(_PR_INET6) - if (addr->raw.family == AF_INET6) { - if (val == PR_IpAddrAny - && IN6_IS_ADDR_UNSPECIFIED((struct in6_addr*)&addr->ipv6.ip)) { - return PR_TRUE; - } else if (val == PR_IpAddrLoopback - && IN6_IS_ADDR_LOOPBACK((struct in6_addr*)&addr->ipv6.ip)) { + if (addr->raw.family == PR_AF_INET6) { + if (val == PR_IpAddrAny) { + if (_PR_IN6_IS_ADDR_UNSPECIFIED((PRIPv6Addr *)&addr->ipv6.ip)) { + return PR_TRUE; + } else if (_PR_IN6_IS_ADDR_V4MAPPED((PRIPv6Addr *)&addr->ipv6.ip) + && _PR_IN6_V4MAPPED_TO_IPADDR((PRIPv6Addr *)&addr->ipv6.ip) + == htonl(INADDR_ANY)) { + return PR_TRUE; + } + } else if (val == PR_IpAddrLoopback) { + if (_PR_IN6_IS_ADDR_LOOPBACK((PRIPv6Addr *)&addr->ipv6.ip)) { + return PR_TRUE; + } else if (_PR_IN6_IS_ADDR_V4MAPPED((PRIPv6Addr *)&addr->ipv6.ip) + && _PR_IN6_V4MAPPED_TO_IPADDR((PRIPv6Addr *)&addr->ipv6.ip) + == htonl(INADDR_LOOPBACK)) { + return PR_TRUE; + } + } else if (val == PR_IpAddrV4Mapped + && _PR_IN6_IS_ADDR_V4MAPPED((PRIPv6Addr *)&addr->ipv6.ip)) { return PR_TRUE; } - } - else -#endif - { + } else { if (addr->raw.family == AF_INET) { if (val == PR_IpAddrAny && addr->inet.ip == htonl(INADDR_ANY)) { return PR_TRUE; @@ -971,40 +1028,258 @@ PR_IsNetAddrType(const PRNetAddr *addr, PRNetAddrValue val) return PR_FALSE; } -PR_IMPLEMENT(PRNetAddr*) PR_CreateNetAddr(PRNetAddrValue val, PRUint16 port) +#ifndef _PR_INET6 +#define XX 127 +static const unsigned char index_hex[256] = { + XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, + XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, + XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,XX,XX, XX,XX,XX,XX, + XX,10,11,12, 13,14,15,XX, XX,XX,XX,XX, XX,XX,XX,XX, + XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, + XX,10,11,12, 13,14,15,XX, XX,XX,XX,XX, XX,XX,XX,XX, + XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, + XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, + XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, + XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, + XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, + XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, + XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, + XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, + XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, +}; + +/* + * StringToV6Addr() returns 1 if the conversion succeeds, + * or 0 if the input is not a valid IPv6 address string. + * (Same as inet_pton(AF_INET6, string, addr).) + */ +static int StringToV6Addr(const char *string, PRIPv6Addr *addr) { - PRNetAddr *addr = NULL; - if ((PR_IpAddrAny == val) || (PR_IpAddrLoopback == val)) - { - addr = PR_NEWZAP(PRNetAddr); - if (NULL == addr) - PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); - else - if (PR_FAILURE == PR_InitializeNetAddr(val, port, addr)) - PR_DELETE(addr); /* and that will make 'addr' == NULL */ + const unsigned char *s = (const unsigned char *)string; + int section = 0; /* index of the current section (a 16-bit + * piece of the address */ + int double_colon = -1; /* index of the section after the first + * 16-bit group of zeros represented by + * the double colon */ + unsigned int val; + int len; + + /* Handle initial (double) colon */ + if (*s == ':') { + if (s[1] != ':') return 0; + s += 2; + addr->pr_s6_addr16[0] = 0; + section = double_colon = 1; } - else - PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); - return addr; -} /* PR_CreateNetAddr */ -PR_IMPLEMENT(PRStatus) PR_DestroyNetAddr(PRNetAddr *addr) + while (*s) { + if (section == 8) return 0; /* too long */ + if (*s == ':') { + if (double_colon != -1) return 0; /* two double colons */ + addr->pr_s6_addr16[section++] = 0; + double_colon = section; + s++; + continue; + } + for (len = val = 0; len < 4 && index_hex[*s] != XX; len++) { + val = (val << 4) + index_hex[*s++]; + } + if (*s == '.') { + if (len == 0) return 0; /* nothing between : and . */ + break; + } + if (*s == ':') { + s++; + if (!*s) return 0; /* cannot end with single colon */ + } else if (*s) { + return 0; /* bad character */ + } + addr->pr_s6_addr16[section++] = htons((unsigned short)val); + } + + if (*s == '.') { + /* Have a trailing v4 format address */ + if (section > 6) return 0; /* not enough room */ + + /* + * The number before the '.' is decimal, but we parsed it + * as hex. That means it is in BCD. Check it for validity + * and convert it to binary. + */ + if (val > 0x0255 || (val & 0xf0) > 0x90 || (val & 0xf) > 9) return 0; + val = (val >> 8) * 100 + ((val >> 4) & 0xf) * 10 + (val & 0xf); + addr->pr_s6_addr[2 * section] = val; + + s++; + val = index_hex[*s++]; + if (val > 9) return 0; + while (*s >= '0' && *s <= '9') { + val = val * 10 + *s++ - '0'; + if (val > 255) return 0; + } + if (*s != '.') return 0; /* must have exactly 4 decimal numbers */ + addr->pr_s6_addr[2 * section + 1] = val; + section++; + + s++; + val = index_hex[*s++]; + if (val > 9) return 0; + while (*s >= '0' && *s <= '9') { + val = val * 10 + *s++ - '0'; + if (val > 255) return 0; + } + if (*s != '.') return 0; /* must have exactly 4 decimal numbers */ + addr->pr_s6_addr[2 * section] = val; + + s++; + val = index_hex[*s++]; + if (val > 9) return 0; + while (*s >= '0' && *s <= '9') { + val = val * 10 + *s++ - '0'; + if (val > 255) return 0; + } + if (*s) return 0; /* must have exactly 4 decimal numbers */ + addr->pr_s6_addr[2 * section + 1] = val; + section++; + } + + if (double_colon != -1) { + /* Stretch the double colon */ + int tosection; + int ncopy = section - double_colon; + for (tosection = 7; ncopy--; tosection--) { + addr->pr_s6_addr16[tosection] = + addr->pr_s6_addr16[double_colon + ncopy]; + } + while (tosection >= double_colon) { + addr->pr_s6_addr16[tosection--] = 0; + } + } else if (section != 8) { + return 0; /* too short */ + } + return 1; +} +#undef XX + +static const char *basis_hex = "0123456789abcdef"; + +/* + * V6AddrToString() returns a pointer to the buffer containing + * the text string if the conversion succeeds, and NULL otherwise. + * (Same as inet_ntop(AF_INET6, addr, buf, size), except that errno + * is not set on failure.) + */ +static const char *V6AddrToString( + const PRIPv6Addr *addr, char *buf, PRUint32 size) { - PR_Free(addr); - return PR_SUCCESS; -} /* PR_DestroyNetAddr */ +#define STUFF(c) do { \ + if (!size--) return NULL; \ + *buf++ = (c); \ +} while (0) + + int double_colon = -1; /* index of the first 16-bit + * group of zeros represented + * by the double colon */ + int double_colon_length = 1; /* use double colon only if + * there are two or more 16-bit + * groups of zeros */ + int zero_length; + int section; + unsigned int val; + const char *bufcopy = buf; + + /* Scan to find the placement of the double colon */ + for (section = 0; section < 8; section++) { + if (addr->pr_s6_addr16[section] == 0) { + zero_length = 1; + section++; + while (section < 8 && addr->pr_s6_addr16[section] == 0) { + zero_length++; + section++; + } + /* Select the longest sequence of zeros */ + if (zero_length > double_colon_length) { + double_colon = section - zero_length; + double_colon_length = zero_length; + } + } + } + + /* Now start converting to a string */ + section = 0; + + if (double_colon == 0) { + if (double_colon_length == 6 || + (double_colon_length == 5 && addr->pr_s6_addr16[5] == 0xffff)) { + /* ipv4 format address */ + STUFF(':'); + STUFF(':'); + if (double_colon_length == 5) { + STUFF('f'); + STUFF('f'); + STUFF('f'); + STUFF('f'); + STUFF(':'); + } + if (addr->pr_s6_addr[12] > 99) STUFF(addr->pr_s6_addr[12]/100 + '0'); + if (addr->pr_s6_addr[12] > 9) STUFF((addr->pr_s6_addr[12]%100)/10 + '0'); + STUFF(addr->pr_s6_addr[12]%10 + '0'); + STUFF('.'); + if (addr->pr_s6_addr[13] > 99) STUFF(addr->pr_s6_addr[13]/100 + '0'); + if (addr->pr_s6_addr[13] > 9) STUFF((addr->pr_s6_addr[13]%100)/10 + '0'); + STUFF(addr->pr_s6_addr[13]%10 + '0'); + STUFF('.'); + if (addr->pr_s6_addr[14] > 99) STUFF(addr->pr_s6_addr[14]/100 + '0'); + if (addr->pr_s6_addr[14] > 9) STUFF((addr->pr_s6_addr[14]%100)/10 + '0'); + STUFF(addr->pr_s6_addr[14]%10 + '0'); + STUFF('.'); + if (addr->pr_s6_addr[15] > 99) STUFF(addr->pr_s6_addr[15]/100 + '0'); + if (addr->pr_s6_addr[15] > 9) STUFF((addr->pr_s6_addr[15]%100)/10 + '0'); + STUFF(addr->pr_s6_addr[15]%10 + '0'); + STUFF('\0'); + return bufcopy; + } + } + + while (section < 8) { + if (section == double_colon) { + STUFF(':'); + STUFF(':'); + section += double_colon_length; + continue; + } + val = ntohs(addr->pr_s6_addr16[section]); + if (val > 0xfff) { + STUFF(basis_hex[val >> 12]); + } + if (val > 0xff) { + STUFF(basis_hex[(val >> 8) & 0xf]); + } + if (val > 0xf) { + STUFF(basis_hex[(val >> 4) & 0xf]); + } + STUFF(basis_hex[val & 0xf]); + section++; + if (section < 8 && section != double_colon) STUFF(':'); + } + STUFF('\0'); + return bufcopy; +#undef STUFF +} + +#endif /* !_PR_INET6 */ PR_IMPLEMENT(PRStatus) PR_StringToNetAddr(const char *string, PRNetAddr *addr) { PRStatus status = PR_SUCCESS; - -#if defined(_PR_INET6) PRIntn rv; +#if defined(_PR_INET6) rv = inet_pton(AF_INET6, string, &addr->ipv6.ip); if (1 == rv) { - addr->raw.family = AF_INET6; + addr->raw.family = PR_AF_INET6; } else { @@ -1022,6 +1297,13 @@ PR_IMPLEMENT(PRStatus) PR_StringToNetAddr(const char *string, PRNetAddr *addr) } } #else /* _PR_INET6 */ + rv = StringToV6Addr(string, &addr->ipv6.ip); + if (1 == rv) { + addr->raw.family = PR_AF_INET6; + return PR_SUCCESS; + } + PR_ASSERT(0 == rv); + addr->inet.family = AF_INET; #ifdef XP_OS2_VACPP addr->inet.ip = inet_addr((char *)string); @@ -1044,17 +1326,20 @@ PR_IMPLEMENT(PRStatus) PR_StringToNetAddr(const char *string, PRNetAddr *addr) PR_IMPLEMENT(PRStatus) PR_NetAddrToString( const PRNetAddr *addr, char *string, PRUint32 size) { -#if defined(_PR_INET6) - if (AF_INET6 == addr->raw.family) + if (PR_AF_INET6 == addr->raw.family) { +#if defined(_PR_INET6) if (NULL == inet_ntop(AF_INET6, &addr->ipv6.ip, string, size)) +#else + if (NULL == V6AddrToString(&addr->ipv6.ip, string, size)) +#endif { - PR_SetError(PR_INVALID_ARGUMENT_ERROR, errno); + /* the size of the result buffer is inadequate */ + PR_SetError(PR_BUFFER_OVERFLOW_ERROR, 0); return PR_FAILURE; } } else -#endif /* defined(_PR_INET6) */ { PR_ASSERT(AF_INET == addr->raw.family); PR_ASSERT(size >= 16); @@ -1076,17 +1361,27 @@ failed: } /* PR_NetAddrToString */ +/* + * Convert an IPv4 addr to an (IPv4-mapped) IPv6 addr + */ +PR_IMPLEMENT(void) PR_ConvertIPv4AddrToIPv6(PRUint32 v4addr, PRIPv6Addr *v6addr) +{ + PRUint8 *dstp; + dstp = v6addr->pr_s6_addr; + memset(dstp, 0, 10); + memset(dstp + 10, 0xff, 2); + memcpy(dstp + 12,(char *) &v4addr, 4); +} + PR_IMPLEMENT(PRUint16) PR_ntohs(PRUint16 n) { return ntohs(n); } PR_IMPLEMENT(PRUint32) PR_ntohl(PRUint32 n) { return ntohl(n); } PR_IMPLEMENT(PRUint16) PR_htons(PRUint16 n) { return htons(n); } PR_IMPLEMENT(PRUint32) PR_htonl(PRUint32 n) { return htonl(n); } PR_IMPLEMENT(PRUint64) PR_ntohll(PRUint64 n) { - /* - ** There is currently no attempt to optomize out depending - ** on the host' byte order. That would be easy enough to - ** do. - */ +#ifdef IS_BIG_ENDIAN + return n; +#else PRUint64 tmp; PRUint32 hi, lo; LL_L2UI(lo, n); @@ -1094,20 +1389,19 @@ PR_IMPLEMENT(PRUint64) PR_ntohll(PRUint64 n) LL_L2UI(hi, tmp); hi = PR_ntohl(hi); lo = PR_ntohl(lo); - LL_UI2L(n, hi); + LL_UI2L(n, lo); LL_SHL(n, n, 32); - LL_UI2L(tmp, lo); + LL_UI2L(tmp, hi); LL_ADD(n, n, tmp); return n; +#endif } /* ntohll */ PR_IMPLEMENT(PRUint64) PR_htonll(PRUint64 n) { - /* - ** There is currently no attempt to optomize out depending - ** on the host' byte order. That would be easy enough to - ** do. - */ +#ifdef IS_BIG_ENDIAN + return n; +#else PRUint64 tmp; PRUint32 hi, lo; LL_L2UI(lo, n); @@ -1115,18 +1409,10 @@ PR_IMPLEMENT(PRUint64) PR_htonll(PRUint64 n) LL_L2UI(hi, tmp); hi = htonl(hi); lo = htonl(lo); - LL_UI2L(n, hi); + LL_UI2L(n, lo); LL_SHL(n, n, 32); - LL_UI2L(tmp, lo); + LL_UI2L(tmp, hi); LL_ADD(n, n, tmp); return n; -} /* htonll */ - -PR_IMPLEMENT(PRUint16) PR_FamilyInet(void) -{ -#ifdef _PR_INET6 - return (_pr_ipv6_enabled ? AF_INET6 : AF_INET); -#else - return AF_INET; #endif -} +} /* htonll */ diff --git a/pr/src/misc/prtpool.c b/pr/src/misc/prtpool.c index 64aa8426..b694b94a 100644 --- a/pr/src/misc/prtpool.c +++ b/pr/src/misc/prtpool.c @@ -16,7 +16,6 @@ * Reserved. */ -#include "prtpool.h" #include "nspr.h" /* @@ -84,10 +83,11 @@ struct PRThreadPool { PRInt32 max_threads; PRInt32 current_threads; PRInt32 idle_threads; - PRInt32 stacksize; + PRUint32 stacksize; tp_jobq jobq; io_jobq ioq; timer_jobq timerq; + PRLock *join_lock; /* used with jobp->join_cv */ PRCondVar *shutdown_cv; PRBool shutdown; }; @@ -95,12 +95,6 @@ struct PRThreadPool { typedef enum io_op_type { JOB_IO_READ, JOB_IO_WRITE, JOB_IO_CONNECT, JOB_IO_ACCEPT } io_op_type; -typedef enum _PRJobStatus - { JOB_ON_TIMERQ, JOB_ON_IOQ, JOB_QUEUED, JOB_RUNNING, JOB_COMPLETED, - JOB_CANCELED, JOB_FREED } _PRJobStatus; - -typedef void (* Jobfn)(void *arg); - #ifdef OPT_WINNT typedef struct NT_notifier { OVERLAPPED overlapped; /* must be first */ @@ -110,12 +104,14 @@ typedef struct NT_notifier { struct PRJob { PRCList links; /* for linking jobs */ - _PRJobStatus status; - PRBool joinable; - Jobfn job_func; + PRBool on_ioq; /* job on ioq */ + PRBool on_timerq; /* job on timerq */ + PRJobFn job_func; void *job_arg; - PRLock *jlock; PRCondVar *join_cv; + PRBool join_wait; /* == PR_TRUE, when waiting to join */ + PRCondVar *cancel_cv; /* for cancelling IO jobs */ + PRBool cancel_io; /* for cancelling IO jobs */ PRThreadPool *tpool; /* back pointer to thread pool */ PRJobIoDesc *iod; io_op_type io_op; @@ -134,13 +130,41 @@ struct PRJob { #define WTHREAD_LINKS_PTR(_qp) \ ((wthread *) ((char *) (_qp) - offsetof(wthread, links))) +#define JOINABLE_JOB(_jobp) (NULL != (_jobp)->join_cv) + +#define JOIN_NOTIFY(_jobp) \ + PR_BEGIN_MACRO \ + PR_Lock(_jobp->tpool->join_lock); \ + _jobp->join_wait = PR_FALSE; \ + PR_NotifyCondVar(_jobp->join_cv); \ + PR_Unlock(_jobp->tpool->join_lock); \ + PR_END_MACRO + +#define CANCEL_IO_JOB(jobp) \ + PR_BEGIN_MACRO \ + jobp->cancel_io = PR_FALSE; \ + jobp->on_ioq = PR_FALSE; \ + PR_REMOVE_AND_INIT_LINK(&jobp->links); \ + tp->ioq.cnt--; \ + PR_NotifyCondVar(jobp->cancel_cv); \ + PR_END_MACRO + static void delete_job(PRJob *jobp); static PRThreadPool * alloc_threadpool(); -static PRJob * alloc_job(PRBool joinable); +static PRJob * alloc_job(PRBool joinable, PRThreadPool *tp); static void notify_ioq(PRThreadPool *tp); static void notify_timerq(PRThreadPool *tp); /* + * locks are acquired in the following order + * + * tp->ioq.lock,tp->timerq.lock + * | + * V + * tp->jobq->lock + */ + +/* * worker thread function */ static void wstart(void *arg) @@ -172,17 +196,14 @@ PRCList *head; tp->idle_threads--; tp->jobq.cnt--; PR_Unlock(tp->jobq.lock); - PR_Lock(jobp->jlock); - jobp->status = JOB_RUNNING; - PR_Unlock(jobp->jlock); #else PR_Lock(tp->jobq.lock); while (PR_CLIST_IS_EMPTY(&tp->jobq.list) && (!tp->shutdown)) { tp->idle_threads++; PR_WaitCondVar(tp->jobq.cv, PR_INTERVAL_NO_TIMEOUT); + tp->idle_threads--; } - tp->idle_threads--; if (tp->shutdown) { PR_Unlock(tp->jobq.lock); break; @@ -194,20 +215,14 @@ PRCList *head; PR_REMOVE_AND_INIT_LINK(head); tp->jobq.cnt--; jobp = JOB_LINKS_PTR(head); - PR_Lock(jobp->jlock); - jobp->status = JOB_RUNNING; - PR_Unlock(jobp->jlock); PR_Unlock(tp->jobq.lock); #endif jobp->job_func(jobp->job_arg); - if (!jobp->joinable) { + if (!JOINABLE_JOB(jobp)) { delete_job(jobp); } else { - PR_Lock(jobp->jlock); - jobp->status = JOB_COMPLETED; - PR_NotifyCondVar(jobp->join_cv); - PR_Unlock(jobp->jlock); + JOIN_NOTIFY(jobp); } } PR_Lock(tp->jobq.lock); @@ -236,11 +251,9 @@ add_to_jobq(PRThreadPool *tp, PRJob *jobp) #else PR_Lock(tp->jobq.lock); PR_APPEND_LINK(&jobp->links,&tp->jobq.list); - jobp->status = JOB_QUEUED; tp->jobq.cnt++; if ((tp->idle_threads < tp->jobq.cnt) && (tp->current_threads < tp->max_threads)) { - PRThread *thr; wthread *wthrp; /* * increment thread count and unlock the jobq lock @@ -248,15 +261,19 @@ add_to_jobq(PRThreadPool *tp, PRJob *jobp) tp->current_threads++; PR_Unlock(tp->jobq.lock); /* create new worker thread */ - thr = PR_CreateThread(PR_USER_THREAD, wstart, + wthrp = PR_NEWZAP(wthread); + if (wthrp) { + wthrp->thread = PR_CreateThread(PR_USER_THREAD, wstart, tp, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,PR_JOINABLE_THREAD,tp->stacksize); + if (NULL == wthrp->thread) { + PR_DELETE(wthrp); /* this sets wthrp to NULL */ + } + } PR_Lock(tp->jobq.lock); - if (NULL == thr) { + if (NULL == wthrp) { tp->current_threads--; } else { - wthrp = PR_NEWZAP(wthread); - wthrp->thread = thr; PR_APPEND_LINK(&wthrp->links, &tp->jobq.wthreads); } } @@ -331,6 +348,10 @@ PRIntervalTime now; PR_Lock(tp->ioq.lock); for (qp = tp->ioq.list.next; qp != &tp->ioq.list; qp = qp->next) { jobp = JOB_LINKS_PTR(qp); + if (jobp->cancel_io) { + CANCEL_IO_JOB(jobp); + continue; + } if (pollfds_used == (pollfd_cnt)) break; pollfds[pollfds_used].fd = jobp->iod->socket; @@ -391,11 +412,18 @@ PRIntervalTime now; jobp = polljobs[index]; if ((revents & PR_POLL_NVAL) || /* busted in all cases */ + (revents & PR_POLL_ERR) || ((events & PR_POLL_WRITE) && (revents & PR_POLL_HUP))) { /* write op & hup */ PR_Lock(tp->ioq.lock); + if (jobp->cancel_io) { + CANCEL_IO_JOB(jobp); + PR_Unlock(tp->ioq.lock); + continue; + } PR_REMOVE_AND_INIT_LINK(&jobp->links); tp->ioq.cnt--; + jobp->on_ioq = PR_FALSE; PR_Unlock(tp->ioq.lock); /* set error */ @@ -403,21 +431,36 @@ PRIntervalTime now; jobp->iod->error = PR_BAD_DESCRIPTOR_ERROR; else if (PR_POLL_HUP & revents) jobp->iod->error = PR_CONNECT_RESET_ERROR; + else + jobp->iod->error = PR_IO_ERROR; /* * add to jobq */ add_to_jobq(tp, jobp); - } else if (revents & events) { + } else if (revents) { /* * add to jobq */ PR_Lock(tp->ioq.lock); + if (jobp->cancel_io) { + CANCEL_IO_JOB(jobp); + PR_Unlock(tp->ioq.lock); + continue; + } PR_REMOVE_AND_INIT_LINK(&jobp->links); tp->ioq.cnt--; + jobp->on_ioq = PR_FALSE; PR_Unlock(tp->ioq.lock); - jobp->iod->error = 0; + if (jobp->io_op == JOB_IO_CONNECT) { + if (PR_GetConnectStatus(&pollfds[index]) == PR_SUCCESS) + jobp->iod->error = 0; + else + jobp->iod->error = PR_GetError(); + } else + jobp->iod->error = 0; + add_to_jobq(tp, jobp); } } @@ -429,6 +472,10 @@ PRIntervalTime now; PR_Lock(tp->ioq.lock); for (qp = tp->ioq.list.next; qp != &tp->ioq.list; qp = qp->next) { jobp = JOB_LINKS_PTR(qp); + if (jobp->cancel_io) { + CANCEL_IO_JOB(jobp); + continue; + } if (PR_INTERVAL_NO_TIMEOUT == jobp->timeout) break; if ((PR_INTERVAL_NO_WAIT != jobp->timeout) && @@ -436,6 +483,7 @@ PRIntervalTime now; break; PR_REMOVE_AND_INIT_LINK(&jobp->links); tp->ioq.cnt--; + jobp->on_ioq = PR_FALSE; jobp->iod->error = PR_IO_TIMEOUT_ERROR; add_to_jobq(tp, jobp); } @@ -494,6 +542,7 @@ PRIntervalTime now; */ PR_REMOVE_AND_INIT_LINK(&jobp->links); tp->timerq.cnt--; + jobp->on_timerq = PR_FALSE; add_to_jobq(tp, jobp); } PR_Unlock(tp->timerq.lock); @@ -510,6 +559,8 @@ delete_threadpool(PRThreadPool *tp) PR_DestroyCondVar(tp->jobq.cv); if (NULL != tp->jobq.lock) PR_DestroyLock(tp->jobq.lock); + if (NULL != tp->join_lock) + PR_DestroyLock(tp->join_lock); #ifdef OPT_WINNT if (NULL != tp->jobq.nt_completion_port) CloseHandle(tp->jobq.nt_completion_port); @@ -545,6 +596,9 @@ PRThreadPool *tp; tp->jobq.cv = PR_NewCondVar(tp->jobq.lock); if (NULL == tp->jobq.cv) goto failed; + tp->join_lock = PR_NewLock(); + if (NULL == tp->join_lock) + goto failed; #ifdef OPT_WINNT tp->jobq.nt_completion_port = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); @@ -581,7 +635,7 @@ failed: /* Create thread pool */ PR_IMPLEMENT(PRThreadPool *) PR_CreateThreadPool(PRInt32 initial_threads, PRInt32 max_threads, - PRSize stacksize) + PRUint32 stacksize) { PRThreadPool *tp; PRThread *thr; @@ -643,32 +697,29 @@ static void delete_job(PRJob *jobp) { if (NULL != jobp) { - if (NULL != jobp->jlock) { - PR_DestroyLock(jobp->jlock); - jobp->jlock = NULL; - } if (NULL != jobp->join_cv) { PR_DestroyCondVar(jobp->join_cv); jobp->join_cv = NULL; } - jobp->status = JOB_FREED; + if (NULL != jobp->cancel_cv) { + PR_DestroyCondVar(jobp->cancel_cv); + jobp->cancel_cv = NULL; + } PR_DELETE(jobp); } } static PRJob * -alloc_job(PRBool joinable) +alloc_job(PRBool joinable, PRThreadPool *tp) { PRJob *jobp; jobp = PR_NEWZAP(PRJob); if (NULL == jobp) goto failed; - jobp->jlock = PR_NewLock(); - if (NULL == jobp->jlock) - goto failed; if (joinable) { - jobp->join_cv = PR_NewCondVar(jobp->jlock); + jobp->join_cv = PR_NewCondVar(tp->join_lock); + jobp->join_wait = PR_TRUE; if (NULL == jobp->join_cv) goto failed; } else { @@ -686,32 +737,31 @@ failed: /* queue a job */ PR_IMPLEMENT(PRJob *) -PR_QueueJob(PRThreadPool *tpool, JobFn fn, void *arg, PRBool joinable) +PR_QueueJob(PRThreadPool *tpool, PRJobFn fn, void *arg, PRBool joinable) { PRJob *jobp; - jobp = alloc_job(joinable); + jobp = alloc_job(joinable, tpool); if (NULL == jobp) return NULL; jobp->job_func = fn; jobp->job_arg = arg; jobp->tpool = tpool; - jobp->joinable = joinable; add_to_jobq(tpool, jobp); return jobp; } -/* queue a job, when a socket is readable */ +/* queue a job, when a socket is readable or writeable */ static PRJob * -queue_io_job(PRThreadPool *tpool, PRJobIoDesc *iod, JobFn fn, void * arg, +queue_io_job(PRThreadPool *tpool, PRJobIoDesc *iod, PRJobFn fn, void * arg, PRBool joinable, io_op_type op) { PRJob *jobp; PRIntervalTime now; - jobp = alloc_job(joinable); + jobp = alloc_job(joinable, tpool); if (NULL == jobp) { return NULL; } @@ -723,9 +773,7 @@ queue_io_job(PRThreadPool *tpool, PRJobIoDesc *iod, JobFn fn, void * arg, jobp->job_func = fn; jobp->job_arg = arg; - jobp->status = JOB_ON_IOQ; jobp->tpool = tpool; - jobp->joinable = joinable; jobp->iod = iod; if (JOB_IO_READ == op) { jobp->io_op = JOB_IO_READ; @@ -738,7 +786,7 @@ queue_io_job(PRThreadPool *tpool, PRJobIoDesc *iod, JobFn fn, void * arg, jobp->io_poll_flags = PR_POLL_READ; } else if (JOB_IO_CONNECT == op) { jobp->io_op = JOB_IO_CONNECT; - jobp->io_poll_flags = PR_POLL_WRITE; + jobp->io_poll_flags = PR_POLL_WRITE|PR_POLL_EXCEPT; } else { delete_job(jobp); PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); @@ -778,6 +826,7 @@ queue_io_job(PRThreadPool *tpool, PRJobIoDesc *iod, JobFn fn, void * arg, PR_INSERT_AFTER(&jobp->links,qp); } + jobp->on_ioq = PR_TRUE; tpool->ioq.cnt++; /* * notify io worker thread(s) @@ -789,7 +838,7 @@ queue_io_job(PRThreadPool *tpool, PRJobIoDesc *iod, JobFn fn, void * arg, /* queue a job, when a socket is readable */ PR_IMPLEMENT(PRJob *) -PR_QueueJob_Read(PRThreadPool *tpool, PRJobIoDesc *iod, JobFn fn, void * arg, +PR_QueueJob_Read(PRThreadPool *tpool, PRJobIoDesc *iod, PRJobFn fn, void * arg, PRBool joinable) { return (queue_io_job(tpool, iod, fn, arg, joinable, JOB_IO_READ)); @@ -797,7 +846,7 @@ PR_QueueJob_Read(PRThreadPool *tpool, PRJobIoDesc *iod, JobFn fn, void * arg, /* queue a job, when a socket is writeable */ PR_IMPLEMENT(PRJob *) -PR_QueueJob_Write(PRThreadPool *tpool, PRJobIoDesc *iod, JobFn fn,void * arg, +PR_QueueJob_Write(PRThreadPool *tpool, PRJobIoDesc *iod, PRJobFn fn,void * arg, PRBool joinable) { return (queue_io_job(tpool, iod, fn, arg, joinable, JOB_IO_WRITE)); @@ -806,27 +855,40 @@ PR_QueueJob_Write(PRThreadPool *tpool, PRJobIoDesc *iod, JobFn fn,void * arg, /* queue a job, when a socket has a pending connection */ PR_IMPLEMENT(PRJob *) -PR_QueueJob_Accept(PRThreadPool *tpool, PRJobIoDesc *iod, JobFn fn, void * arg, - PRBool joinable) +PR_QueueJob_Accept(PRThreadPool *tpool, PRJobIoDesc *iod, PRJobFn fn, + void * arg, PRBool joinable) { return (queue_io_job(tpool, iod, fn, arg, joinable, JOB_IO_ACCEPT)); } /* queue a job, when a socket can be connected */ PR_IMPLEMENT(PRJob *) -PR_QueueJob_Connect(PRThreadPool *tpool, PRJobIoDesc *iod, PRNetAddr *addr, - JobFn fn, void * arg, PRBool joinable) +PR_QueueJob_Connect(PRThreadPool *tpool, PRJobIoDesc *iod, + const PRNetAddr *addr, PRJobFn fn, void * arg, PRBool joinable) { - /* - * not implemented - */ - return NULL; + PRStatus rv; + PRErrorCode err; + + rv = PR_Connect(iod->socket, addr, PR_INTERVAL_NO_WAIT); + if ((rv == PR_FAILURE) && ((err = PR_GetError()) == PR_IN_PROGRESS_ERROR)){ + /* connection pending */ + return(queue_io_job(tpool, iod, fn, arg, joinable, JOB_IO_CONNECT)); + } else { + /* + * connection succeeded or failed; add to jobq right away + */ + if (rv == PR_FAILURE) + iod->error = err; + else + iod->error = 0; + return(PR_QueueJob(tpool, fn, arg, joinable)); + } } /* queue a job, when a timer expires */ PR_IMPLEMENT(PRJob *) PR_QueueJob_Timer(PRThreadPool *tpool, PRIntervalTime timeout, - JobFn fn, void * arg, PRBool joinable) + PRJobFn fn, void * arg, PRBool joinable) { PRIntervalTime now; PRJob *jobp; @@ -841,7 +903,7 @@ PR_QueueJob_Timer(PRThreadPool *tpool, PRIntervalTime timeout, */ return(PR_QueueJob(tpool, fn, arg, joinable)); } - jobp = alloc_job(joinable); + jobp = alloc_job(joinable, tpool); if (NULL == jobp) { return NULL; } @@ -853,9 +915,7 @@ PR_QueueJob_Timer(PRThreadPool *tpool, PRIntervalTime timeout, jobp->job_func = fn; jobp->job_arg = arg; - jobp->status = JOB_ON_TIMERQ; jobp->tpool = tpool; - jobp->joinable = joinable; jobp->timeout = timeout; now = PR_IntervalNow(); @@ -863,6 +923,7 @@ PR_QueueJob_Timer(PRThreadPool *tpool, PRIntervalTime timeout, PR_Lock(tpool->timerq.lock); + jobp->on_timerq = PR_TRUE; if (PR_CLIST_IS_EMPTY(&tpool->timerq.list)) PR_APPEND_LINK(&jobp->links,&tpool->timerq.list); else { @@ -921,27 +982,64 @@ PR_CancelJob(PRJob *jobp) { PRStatus rval = PR_FAILURE; PRThreadPool *tp; - if (JOB_QUEUED == jobp->status) { + if (jobp->on_timerq) { /* - * now, check again while holding thread pool lock + * now, check again while holding the timerq lock */ tp = jobp->tpool; - PR_Lock(tp->jobq.lock); - PR_Lock(jobp->jlock); - if (JOB_QUEUED == jobp->status) { + PR_Lock(tp->timerq.lock); + if (jobp->on_timerq) { + jobp->on_timerq = PR_FALSE; PR_REMOVE_AND_INIT_LINK(&jobp->links); - if (!jobp->joinable) { - PR_Unlock(jobp->jlock); + tp->timerq.cnt--; + PR_Unlock(tp->timerq.lock); + if (!JOINABLE_JOB(jobp)) { delete_job(jobp); } else { - jobp->status = JOB_CANCELED; - PR_NotifyCondVar(jobp->join_cv); - PR_Unlock(jobp->jlock); + JOIN_NOTIFY(jobp); } rval = PR_SUCCESS; - } - PR_Unlock(tp->jobq.lock); + } else + PR_Unlock(tp->timerq.lock); + } else if (jobp->on_ioq) { + /* + * now, check again while holding the ioq lock + */ + tp = jobp->tpool; + PR_Lock(tp->ioq.lock); + if (jobp->on_ioq) { + jobp->cancel_cv = PR_NewCondVar(tp->ioq.lock); + if (NULL == jobp->cancel_cv) { + PR_Unlock(tp->ioq.lock); + PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0); + return PR_FAILURE; + } + /* + * mark job 'cancelled' and notify io thread(s) + * XXXX: + * this assumes there is only one io thread; when there + * are multiple threads, the io thread processing this job + * must be notified. + */ + jobp->cancel_io = PR_TRUE; + PR_Unlock(tp->ioq.lock); /* release, reacquire ioq lock */ + notify_ioq(tp); + PR_Lock(tp->ioq.lock); + while (jobp->cancel_io) + PR_WaitCondVar(jobp->cancel_cv, PR_INTERVAL_NO_TIMEOUT); + PR_Unlock(tp->ioq.lock); + PR_ASSERT(!jobp->on_ioq); + if (!JOINABLE_JOB(jobp)) { + delete_job(jobp); + } else { + JOIN_NOTIFY(jobp); + } + rval = PR_SUCCESS; + } else + PR_Unlock(tp->ioq.lock); } + if (PR_FAILURE == rval) + PR_SetError(PR_INVALID_STATE_ERROR, 0); return rval; } @@ -949,19 +1047,14 @@ PR_CancelJob(PRJob *jobp) { PR_IMPLEMENT(PRStatus) PR_JoinJob(PRJob *jobp) { - /* - * No references to the thread pool - */ - if (!jobp->joinable) { + if (!JOINABLE_JOB(jobp)) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return PR_FAILURE; } - PR_Lock(jobp->jlock); - while((JOB_COMPLETED != jobp->status) && - (JOB_CANCELED != jobp->status)) + PR_Lock(jobp->tpool->join_lock); + while(jobp->join_wait) PR_WaitCondVar(jobp->join_cv, PR_INTERVAL_NO_TIMEOUT); - - PR_Unlock(jobp->jlock); + PR_Unlock(jobp->tpool->join_lock); delete_job(jobp); return PR_SUCCESS; } @@ -1017,9 +1110,7 @@ PRStatus rval_status; /* * wakeup io thread(s) */ - PR_Lock(tpool->ioq.lock); notify_ioq(tpool); - PR_Unlock(tpool->ioq.lock); /* * wakeup timer thread(s) @@ -1064,7 +1155,7 @@ PRStatus rval_status; } /* - * Delete unjoinable jobs; joinable jobs must be reclaimed by the user + * Delete queued jobs */ while (!PR_CLIST_IS_EMPTY(&tpool->jobq.list)) { PRJob *jobp; @@ -1073,17 +1164,10 @@ PRStatus rval_status; PR_REMOVE_AND_INIT_LINK(head); jobp = JOB_LINKS_PTR(head); tpool->jobq.cnt--; - - if (!jobp->joinable) { - delete_job(jobp); - } else { - PR_Lock(jobp->jlock); - jobp->status = JOB_CANCELED; - PR_NotifyCondVar(jobp->join_cv); - PR_Unlock(jobp->jlock); - } + delete_job(jobp); } + /* delete io jobs */ while (!PR_CLIST_IS_EMPTY(&tpool->ioq.list)) { PRJob *jobp; @@ -1091,16 +1175,10 @@ PRStatus rval_status; PR_REMOVE_AND_INIT_LINK(head); tpool->ioq.cnt--; jobp = JOB_LINKS_PTR(head); - if (!jobp->joinable) { - delete_job(jobp); - } else { - PR_Lock(jobp->jlock); - jobp->status = JOB_CANCELED; - PR_NotifyCondVar(jobp->join_cv); - PR_Unlock(jobp->jlock); - } + delete_job(jobp); } + /* delete timer jobs */ while (!PR_CLIST_IS_EMPTY(&tpool->timerq.list)) { PRJob *jobp; @@ -1108,14 +1186,7 @@ PRStatus rval_status; PR_REMOVE_AND_INIT_LINK(head); tpool->timerq.cnt--; jobp = JOB_LINKS_PTR(head); - if (!jobp->joinable) { - delete_job(jobp); - } else { - PR_Lock(jobp->jlock); - jobp->status = JOB_CANCELED; - PR_NotifyCondVar(jobp->join_cv); - PR_Unlock(jobp->jlock); - } + delete_job(jobp); } PR_ASSERT(0 == tpool->jobq.cnt); diff --git a/pr/src/nspr.rc b/pr/src/nspr.rc index 147b670b..ae4bf876 100644 --- a/pr/src/nspr.rc +++ b/pr/src/nspr.rc @@ -22,6 +22,10 @@ #define MY_LIBNAME "nspr" #define MY_FILEDESCRIPTION "NSPR Library" +#define STRINGIZE(x) #x +#define STRINGIZE2(x) STRINGIZE(x) +#define PR_VMAJOR_STR STRINGIZE2(PR_VMAJOR) + #ifdef _DEBUG #define MY_DEBUG_STR " (debug)" #define MY_FILEFLAGS_1 VS_FF_DEBUG @@ -66,7 +70,7 @@ BEGIN VALUE "FileDescription", MY_FILEDESCRIPTION MY_DEBUG_STR "\0" VALUE "FileVersion", PR_VERSION "\0" VALUE "InternalName", MY_INTERNAL_NAME "\0" - VALUE "LegalCopyright", "Copyright \251 1996-1999 Netscape Communications Corporation\0" + VALUE "LegalCopyright", "Copyright \251 1996-2000 Netscape Communications Corporation\0" VALUE "OriginalFilename", MY_INTERNAL_NAME ".dll\0" VALUE "ProductName", "Netscape Portable Runtime\0" VALUE "ProductVersion", PR_VERSION "\0" diff --git a/pr/src/prvrsion.c b/pr/src/prvrsion.c index 54a292f2..c694a34e 100644 --- a/pr/src/prvrsion.c +++ b/pr/src/prvrsion.c @@ -42,7 +42,14 @@ #define _DEBUG_STRING "" #endif -PRVersionDescription prVersionDescription_libnspr3 = +/* + * A trick to expand the PR_VMAJOR macro before concatenation. + */ +#define CONCAT(x, y) x ## y +#define CONCAT2(x, y) CONCAT(x, y) +#define VERSION_DESC_NAME CONCAT2(prVersionDescription_libnspr, PR_VMAJOR) + +PRVersionDescription VERSION_DESC_NAME = { /* version */ 2, /* this is the only one supported */ /* buildTime */ _BUILD_TIME, /* usecs since midnight 1/1/1970 GMT */ @@ -92,7 +99,7 @@ PR_IMPLEMENT(const PRVersionDescription*) libVersionPoint(void) dummy = rcsid; dummy = sccsid; #endif - return &prVersionDescription_libnspr3; + return &VERSION_DESC_NAME; } /* versionEntryPointType */ /* prvrsion.c */ diff --git a/pr/src/pthreads/ptio.c b/pr/src/pthreads/ptio.c index f65dbdcc..b301ebd5 100644 --- a/pr/src/pthreads/ptio.c +++ b/pr/src/pthreads/ptio.c @@ -143,7 +143,8 @@ static ssize_t (*pt_aix_sendfile_fptr)() = NULL; #error "Cannot determine architecture" #endif -static PRFileDesc *pt_SetMethods(PRIntn osfd, PRDescType type); +static PRFileDesc *pt_SetMethods( + PRIntn osfd, PRDescType type, PRBool isAcceptedSocket); static PRLock *_pr_flock_lock; /* For PR_LockFile() etc. */ static PRLock *_pr_rename_lock; /* For PR_Rename() */ @@ -153,13 +154,11 @@ static PRLock *_pr_rename_lock; /* For PR_Rename() */ /* These two functions are only used in assertions. */ #if defined(DEBUG) -static PRBool IsValidNetAddr(const PRNetAddr *addr) +PRBool IsValidNetAddr(const PRNetAddr *addr) { if ((addr != NULL) && (addr->raw.family != AF_UNIX) -#ifdef _PR_INET6 - && (addr->raw.family != AF_INET6) -#endif + && (addr->raw.family != PR_AF_INET6) && (addr->raw.family != AF_INET)) { return PR_FALSE; } @@ -190,7 +189,7 @@ static PRBool IsValidNetAddrLen(const PRNetAddr *addr, PRInt32 addr_len) * The polling interval defines the maximum amount of time that a thread * might hang up before an interrupt is noticed. */ -#define PT_DEFAULT_POLL_MSEC 100 +#define PT_DEFAULT_POLL_MSEC 5000 /* * pt_SockLen is the type for the length of a socket address @@ -217,17 +216,11 @@ typedef PRBool (*ContinuationFn)(pt_Continuation *op, PRInt16 revents); typedef enum pr_ContuationStatus { pt_continuation_pending, - pt_continuation_recycle, - pt_continuation_abort, pt_continuation_done } pr_ContuationStatus; struct pt_Continuation { - /* These objects are linked in ascending timeout order */ - pt_Continuation *next, *prev; /* self linked list of these things */ - - PRFileDesc *fd; /* The building of the continuation operation */ ContinuationFn function; /* what function to continue */ union { PRIntn osfd; } arg1; /* #1 - the op's fd */ @@ -258,7 +251,6 @@ struct pt_Continuation #endif /* HPUX11 */ PRIntervalTime timeout; /* client (relative) timeout */ - PRIntervalTime absolute; /* internal (absolute) timeout */ PRInt16 event; /* flags for poll()'s events */ @@ -271,27 +263,8 @@ struct pt_Continuation PRIntn syserrno; /* in case it failed, why (errno) */ pr_ContuationStatus status; /* the status of the operation */ - PRCondVar *complete; /* to notify the initiating thread */ - PRIntn io_tq_index; /* io-queue index */ }; -static struct pt_TimedQueue -{ - PRLock *ml; /* a little protection */ - PRThread *thread; /* internal thread's identification */ - PRUintn op_count; /* number of operations in the list */ - pt_Continuation *head, *tail; /* head/tail of list of operations */ - - pt_Continuation *op; /* timed operation furthest in future */ - struct pollfd *pollingList; /* list built for polling */ - PRIntn pollingSlotsAllocated; /* # entries available in list */ - pt_Continuation **pollingOps; /* list paralleling polling list */ -} *pt_tqp; /* an array */ - -static PRIntn _pt_num_cpus; -PRIntn _pt_tq_count; /* size of the pt_tqp array */ -static PRInt32 _pt_tq_index; /* atomically incremented */ - #if defined(DEBUG) PTDebug pt_debug; /* this is shared between several modules */ @@ -316,16 +289,6 @@ PR_IMPLEMENT(void) PT_FPrintStats(PRFileDesc *debug_out, const char *msg) PR_fprintf( debug_out, "\tstarted: %s[%lld]\n", buffer, elapsed); PR_fprintf( - debug_out, "\tmissed predictions: %u\n", stats.predictionsFoiled); - PR_fprintf( - debug_out, "\tpollingList max: %u\n", stats.pollingListMax); - PR_fprintf( - debug_out, "\tcontinuations served: %u\n", stats.continuationsServed); - PR_fprintf( - debug_out, "\trecycles needed: %u\n", stats.recyclesNeeded); - PR_fprintf( - debug_out, "\tquiescent IO: %u\n", stats.quiescentIO); - PR_fprintf( debug_out, "\tlocks [created: %u, destroyed: %u]\n", stats.locks_created, stats.locks_destroyed); PR_fprintf( @@ -341,647 +304,143 @@ PR_IMPLEMENT(void) PT_FPrintStats(PRFileDesc *debug_out, const char *msg) #endif /* DEBUG */ -/* - * The following two functions, pt_InsertTimedInternal and - * pt_FinishTimedInternal, are always called with the tqp->ml - * lock held. The "internal" in the functions' names come from - * the Mesa programming language. Internal functions are always - * called from inside a monitor. - */ - -static void pt_InsertTimedInternal(pt_Continuation *op) -{ - pt_Continuation *t_op = NULL; - PRIntervalTime now = PR_IntervalNow(); - struct pt_TimedQueue *tqp = &pt_tqp[op->io_tq_index]; - -#if defined(DEBUG) - { - PRIntn count; - pt_Continuation *tmp; - PRThread *self = PR_GetCurrentThread(); - - PR_ASSERT(tqp == &pt_tqp[self->io_tq_index]); - PR_ASSERT((tqp->head == NULL) == (tqp->tail == NULL)); - PR_ASSERT((tqp->head == NULL) == (tqp->op_count == 0)); - for (tmp = tqp->head, count = 0; tmp != NULL; tmp = tmp->next) count += 1; - PR_ASSERT(count == tqp->op_count); - for (tmp = tqp->tail, count = 0; tmp != NULL; tmp = tmp->prev) count += 1; - PR_ASSERT(count == tqp->op_count); - for (tmp = tqp->head; tmp != NULL; tmp = tmp->next) - PR_ASSERT(tmp->io_tq_index == op->io_tq_index); - } -#endif /* defined(DEBUG) */ - - /* - * If this element operation isn't timed, it gets queued at the - * end of the list (just after tqp->tail) and we're - * finishd early. - */ - if (PR_INTERVAL_NO_TIMEOUT == op->timeout) - { - t_op = tqp->tail; /* put it at the end */ - goto done; - } - - /* - * The portion of this routine deals with timed ops. - */ - op->absolute = now + op->timeout; /* absolute ticks */ - if (NULL == tqp->op) tqp->op = op; - else - { - /* - * To find where in the list to put the new operation, based - * on the absolute time the operation in question will expire. - * - * The new operation ('op') will expire at now() + op->timeout. - * - * This should be easy! - */ - - for (t_op = tqp->op; NULL != t_op; t_op = t_op->prev) - { - /* - * If 'op' expires later than t_op, then insert 'op' just - * ahead of t_op. Otherwise, compute when operation[n-1] - * expires and try again. - * - * The actual difference between the expiriation of 'op' - * and the current operation what becomes the new operaton's - * timeout interval. That interval is also subtracted from - * the interval of the operation immediately following where - * we stick 'op' (unless the next one isn't timed). The new - * timeout assigned to 'op' takes into account the values of - * now() and when the previous intervals were computed. - */ - if ((PRInt32)(op->absolute - t_op->absolute) >= 0) - { - if (t_op == tqp->op) tqp->op = op; - break; - } - } - } - -done: - - /* - * Insert 'op' into the queue just after t_op or if t_op is null, - * at the head of the list. - * - * We need to set up the 'next' and 'prev' pointers of 'op' - * correctly before inserting 'op' into the queue. Also, we insert - * 'op' by updating tqp->head or op->prev->next first, and then - * updating op->next->prev. We want to make sure that the 'next' - * pointers are linked up correctly at all times so that we can - * traverse the queue by starting with tqp->head and following - * the 'next' pointers, without having to acquire the tqp->ml lock. - * (we do that in pt_ContinuationThreadInternal). We traverse the 'prev' - * pointers only in this function, which is called with the lock held. - * - * Similar care is taken in pt_FinishTimedInternal where we remove - * an op from the queue. - */ - if (NULL == t_op) - { - op->prev = NULL; - op->next = tqp->head; - tqp->head = op; - if (NULL == tqp->tail) tqp->tail = op; - else op->next->prev = op; - } - else - { - op->prev = t_op; - op->next = t_op->next; - if (NULL != op->prev) - op->prev->next = op; - if (NULL != op->next) - op->next->prev = op; - if (t_op == tqp->tail) - tqp->tail = op; - } - - tqp->op_count += 1; - -#if defined(DEBUG) - { - PRIntn count; - pt_Continuation *tmp; - PR_ASSERT(tqp->head != NULL); - PR_ASSERT(tqp->tail != NULL); - PR_ASSERT(tqp->op_count != 0); - PR_ASSERT(tqp->head->prev == NULL); - PR_ASSERT(tqp->tail->next == NULL); - if (tqp->op_count > 1) - { - PR_ASSERT(tqp->head->next != NULL); - PR_ASSERT(tqp->tail->prev != NULL); - } - else - { - PR_ASSERT(tqp->head->next == NULL); - PR_ASSERT(tqp->tail->prev == NULL); - } - for (tmp = tqp->head, count = 0; tmp != NULL; tmp = tmp->next) count += 1; - PR_ASSERT(count == tqp->op_count); - for (tmp = tqp->tail, count = 0; tmp != NULL; tmp = tmp->prev) count += 1; - PR_ASSERT(count == tqp->op_count); - } -#endif /* defined(DEBUG) */ - -} /* pt_InsertTimedInternal */ - -/* - * function: pt_FinishTimedInternal - * - * Takes the finished operation out of the timed queue. It - * notifies the initiating thread that the opertions is - * complete and returns to the caller the value of the next - * operation in the list (or NULL). - */ -static pt_Continuation *pt_FinishTimedInternal(pt_Continuation *op) +static void pt_poll_now(pt_Continuation *op) { - pt_Continuation *next; - struct pt_TimedQueue *tqp = &pt_tqp[op->io_tq_index]; - -#if defined(DEBUG) - { - PRIntn count; - pt_Continuation *tmp; - PR_ASSERT(tqp->head != NULL); - PR_ASSERT(tqp->tail != NULL); - PR_ASSERT(tqp->op_count != 0); - PR_ASSERT(tqp->head->prev == NULL); - PR_ASSERT(tqp->tail->next == NULL); - if (tqp->op_count > 1) - { - PR_ASSERT(tqp->head->next != NULL); - PR_ASSERT(tqp->tail->prev != NULL); - } - else - { - PR_ASSERT(tqp->head->next == NULL); - PR_ASSERT(tqp->tail->prev == NULL); - } - for (tmp = tqp->head, count = 0; tmp != NULL; tmp = tmp->next) count += 1; - PR_ASSERT(count == tqp->op_count); - for (tmp = tqp->tail, count = 0; tmp != NULL; tmp = tmp->prev) count += 1; - PR_ASSERT(count == tqp->op_count); - } -#endif /* defined(DEBUG) */ - - /* remove this one from the list */ - if (NULL == op->prev) tqp->head = op->next; - else op->prev->next = op->next; - if (NULL == op->next) tqp->tail = op->prev; - else op->next->prev = op->prev; - - /* did we happen to hit the timed op? */ - if (op == tqp->op) tqp->op = op->prev; - - next = op->next; - op->next = op->prev = NULL; - op->status = pt_continuation_done; - - tqp->op_count -= 1; - -#if defined(DEBUG) - pt_debug.continuationsServed += 1; -#endif - PR_NotifyCondVar(op->complete); - -#if defined(DEBUG) - { - PRIntn count; - pt_Continuation *tmp; - PR_ASSERT((tqp->head == NULL) == (tqp->tail == NULL)); - PR_ASSERT((tqp->head == NULL) == (tqp->op_count == 0)); - for (tmp = tqp->head, count = 0; tmp != NULL; tmp = tmp->next) count += 1; - PR_ASSERT(count == tqp->op_count); - for (tmp = tqp->tail, count = 0; tmp != NULL; tmp = tmp->prev) count += 1; - PR_ASSERT(count == tqp->op_count); - } -#endif /* defined(DEBUG) */ - - return next; -} /* pt_FinishTimedInternal */ - -static void pt_ContinuationThreadInternal(pt_Continuation *my_op) -{ - /* initialization */ - PRInt32 msecs, mx_poll_ticks; - PRThreadPriority priority; /* used to save caller's prio */ - PRIntn pollingListUsed; /* # entries used in the list */ - PRIntn pollingListNeeded; /* # entries needed this time */ - PRIntn io_tq_index = my_op->io_tq_index; - struct pt_TimedQueue *tqp = &pt_tqp[my_op->io_tq_index]; - struct pollfd *pollingList = tqp->pollingList; - PRIntn pollingSlotsAllocated = tqp->pollingSlotsAllocated; - pt_Continuation **pollingOps = tqp->pollingOps; - - PR_Unlock(tqp->ml); /* don't need that silly lock for a bit */ - - priority = PR_GetThreadPriority(tqp->thread); - PR_SetThreadPriority(tqp->thread, PR_PRIORITY_HIGH); - - mx_poll_ticks = (PRInt32)PR_MillisecondsToInterval(PT_DEFAULT_POLL_MSEC); - - /* do some real work */ - while (PR_TRUE) - { - PRIntn rv; - PRInt32 timeout; - PRIntn pollIndex; - PRIntervalTime now; - pt_Continuation *op, *next_op; - - PR_ASSERT(NULL != tqp->head); - - pollingListNeeded = tqp->op_count; - - /* - * We are not holding the tqp->ml lock now, so more items may - * get added to pt_tq during this window of time. We hope - * that 10 more spaces in the polling list should be enough. - * - * The space allocated is for both a vector that parallels the - * polling list, providing pointers directly into the operation's - * table and the polling list itself. There is a guard element - * between the two structures. - */ - pollingListNeeded += 10; - if (pollingListNeeded > pollingSlotsAllocated) - { - if (NULL != pollingOps) PR_Free(pollingOps); - pollingOps = (pt_Continuation**)PR_Malloc( - sizeof(pt_Continuation**) + pollingListNeeded * - (sizeof(struct pollfd) + sizeof(pt_Continuation*))); - PR_ASSERT(NULL != pollingOps); - tqp->pollingOps = pollingOps; - pollingSlotsAllocated = pollingListNeeded; - tqp->pollingSlotsAllocated = pollingSlotsAllocated; - pollingOps[pollingSlotsAllocated] = (pt_Continuation*)-1; - pollingList = (struct pollfd*)(&pollingOps[pollingSlotsAllocated + 1]); - tqp->pollingList = pollingList; - - } - -#if defined(DEBUG) - if (pollingListNeeded > pt_debug.pollingListMax) - pt_debug.pollingListMax = pollingListNeeded; -#endif - - /* - ** This is interrupt processing. If this thread was interrupted, - ** the thread state will have the PT_THREAD_ABORTED bit set. This - ** overrides good completions as well as timeouts. - ** - ** BTW, it does no good to hold the lock here. This lock doesn't - ** protect the thread structure in any way. Testing the bit and - ** (perhaps) resetting it are safe 'cause it's the only modifiable - ** bit in that word. - */ - if (_PT_THREAD_INTERRUPTED(tqp->thread)) - { - my_op->status = pt_continuation_abort; - tqp->thread->state &= ~PT_THREAD_ABORTED; - } - - - /* - * Build up a polling list. - * This list is sorted on time. Operations that have been - * interrupted are completed and not included in the list. - * There is an assertion that the operation is in progress. - */ - pollingListUsed = 0; - PR_Lock(tqp->ml); - - for (op = tqp->head; NULL != op;) - { - if (pt_continuation_abort == op->status) - { - op->result.code = -1; - op->syserrno = EINTR; - next_op = pt_FinishTimedInternal(op); - if (op == my_op) goto recycle; - else op = next_op; - PR_ASSERT(NULL != tqp->head); - } - else - { - op->status = pt_continuation_pending; - if (pollingListUsed >= pollingSlotsAllocated) - { -#if defined(DEBUG) - pt_debug.predictionsFoiled += 1; -#endif - break; - } - PR_ASSERT((pt_Continuation*)-1 == pollingOps[pollingSlotsAllocated]); - /* - * eventMask bitmasks are declared as PRIntn so that - * each bitmask can be updated individually without - * disturbing adjacent memory, but only the lower 16 - * bits of a bitmask are used. - */ - op->fd->secret->eventMask[io_tq_index] = 0xffff; - pollingOps[pollingListUsed] = op; - pollingList[pollingListUsed].revents = 0; - pollingList[pollingListUsed].fd = op->arg1.osfd; - pollingList[pollingListUsed].events = op->event; - pollingListUsed += 1; - op = op->next; - } - } - - /* - * We don't want to wait forever on this poll. So keep - * the interval down. The operations, if they are timed, - * still have to timeout, while those that are not timed - * should persist forever. But they may be aborted. That's - * what this anxiety is all about. - */ - if (PR_INTERVAL_NO_TIMEOUT == tqp->head->timeout) - msecs = PT_DEFAULT_POLL_MSEC; - else - { - timeout = tqp->head->absolute - PR_IntervalNow(); - if (timeout <= 0) msecs = 0; /* already timed out */ - else if (timeout >= mx_poll_ticks) msecs = PT_DEFAULT_POLL_MSEC; - else msecs = (PRInt32)PR_IntervalToMilliseconds(timeout); - } - - PR_Unlock(tqp->ml); - - /* - * If 'op' isn't NULL at this point, then we didn't get to - * the end of the list. That means that more items got added - * to the list than we anticipated. So, forget this iteration, - * go around the horn again. - * - * One would hope this doesn't happen all that often. - */ - if (NULL != op) continue; /* make it rethink things */ - - PR_ASSERT((pt_Continuation*)-1 == pollingOps[pollingSlotsAllocated]); - - rv = poll(pollingList, pollingListUsed, msecs); - - if ((-1 == rv) && ((errno == EINTR) || (errno == EAGAIN))) - continue; /* go around the loop again */ - - if (rv > 0) - { - /* - * poll() says that something in our list is ready for some more - * action. Find it, load up the operation and see what happens. - */ - - /* - * This may work out okay. The rule is that only this thread, - * the continuation thread, can remove elements from the list. - * Therefore, the list is at worst, longer than when we built - * the polling list. - */ - - for (pollIndex = 0; pollIndex < pollingListUsed; ++pollIndex) - { - PRInt16 events = pollingList[pollIndex].events; - PRInt16 revents = pollingList[pollIndex].revents; - - op = pollingOps[pollIndex]; /* this is the operation */ - - /* (ref: Bug #153459) - ** In case of POLLERR we let the operation retry in hope - ** of getting a more definitive OS error. - */ - if ((revents & POLLNVAL) /* busted in all cases */ - || ((events & POLLOUT) && (revents & POLLHUP))) /* write op & hup */ - { - PR_Lock(tqp->ml); - op->result.code = -1; - if (POLLNVAL & revents) op->syserrno = EBADF; - else if (POLLHUP & revents) op->syserrno = EPIPE; - (void)pt_FinishTimedInternal(op); - if (op == my_op) goto recycle; - PR_Unlock(tqp->ml); - } - else if ((0 != (revents & op->fd->secret->eventMask[io_tq_index])) - && (pt_continuation_pending == op->status)) - { - /* - * Only good?(?) revents left. Operations not pending - * will be pruned next time we build a list. This operation - * will be pruned if the continuation indicates it is - * finished. - */ - - if (op->function(op, revents)) - { - PR_Lock(tqp->ml); - (void)pt_FinishTimedInternal(op); - if (op == my_op) goto recycle; - PR_Unlock(tqp->ml); - } - else - { - /* - * If the continuation function returns - * PR_FALSE, it means available data have - * been read, output buffer space has been - * filled, or pending connections have been - * accepted by prior calls. If the - * continuation function is immediately - * invoked again, it will most likely - * return PR_FALSE. So turn off these - * events in the event mask for this fd so - * that if this fd is encountered again in - * the polling list with these events on, - * we won't invoke the continuation - * function again. - */ - op->fd->secret->eventMask[io_tq_index] &= ~revents; - } - } - } - } - - /* - * This is timeout processing. It is done after checking - * for good completions. Those that just made it under the - * wire are lucky, but none the less, valid. - */ - now = PR_IntervalNow(); - PR_Lock(tqp->ml); - while ((NULL != tqp->head) - && (PR_INTERVAL_NO_TIMEOUT != tqp->head->timeout)) - { - op = tqp->head; /* get a copy of this before finishing it */ - if ((PRInt32)(op->absolute - now) > 0) break; - /* - * The head element of the timed queue has timed out. Record - * the reason for completion and take it out of the list. - */ - op->result.code = -1; - op->syserrno = ETIMEDOUT; - (void)pt_FinishTimedInternal(op); - - /* - * If it's 'my_op' then we have to switch threads. Exit w/o - * finishing the scan. The scan will be completed when another - * thread calls in acting as the continuation thread. - */ - if (op == my_op) goto recycle; /* exit w/o unlocking */ - } - PR_Unlock(tqp->ml); - } - - PR_NOT_REACHED("This is a while(true) loop /w no breaks"); - -recycle: - /* - ** Recycling the continuation thread. - ** - ** The thread we were using for I/O continuations just completed - ** the I/O it submitted. It has to return to it's caller. We need - ** another thread to act in the continuation role. We can do that - ** by taking any operation off the timed queue, setting its state - ** to 'recycle' and notifying the condition. - ** - ** Selecting a likely thread seems like magic. I'm going to try - ** using one that has the longest (or no) timeout, tqp->tail. - ** If that slot's empty, then there's no outstanding I/O and we - ** don't need a thread at all. - ** - ** BTW, we're locked right now, and we'll be returning with the - ** the lock held as well. Seems odd, doesn't it? - */ - - /* $$$ should this be called with the lock held? $$$ */ - PR_SetThreadPriority(tqp->thread, priority); /* reset back to caller's */ - - PR_ASSERT((NULL == tqp->head) == (0 == tqp->op_count)); - PR_ASSERT((NULL == tqp->head) == (NULL == tqp->tail)); - PR_ASSERT(pt_continuation_done == my_op->status); + PRInt32 msecs; + PRIntervalTime epoch, now, elapsed, remaining; + PRThread *self = PR_GetCurrentThread(); - if (NULL != tqp->tail) - { - if (tqp->tail->status != pt_continuation_abort) - { - tqp->tail->status = pt_continuation_recycle; - } - PR_NotifyCondVar(tqp->tail->complete); -#if defined(DEBUG) - pt_debug.recyclesNeeded += 1; -#endif - } -#if defined(DEBUG) - else pt_debug.quiescentIO += 1; -#endif - -} /* pt_ContinuationThreadInternal */ + PR_ASSERT(PR_INTERVAL_NO_WAIT != op->timeout); + + switch (op->timeout) { + case PR_INTERVAL_NO_TIMEOUT: + msecs = PT_DEFAULT_POLL_MSEC; + do + { + PRIntn rv; + struct pollfd tmp_pfd; + + tmp_pfd.revents = 0; + tmp_pfd.fd = op->arg1.osfd; + tmp_pfd.events = op->event; + + rv = poll(&tmp_pfd, 1, msecs); + + if (self->state & PT_THREAD_ABORTED) + { + self->state &= ~PT_THREAD_ABORTED; + op->result.code = -1; + op->syserrno = EINTR; + op->status = pt_continuation_done; + return; + } + + if ((-1 == rv) && ((errno == EINTR) || (errno == EAGAIN))) + continue; /* go around the loop again */ + + if (rv > 0) + { + PRInt16 events = tmp_pfd.events; + PRInt16 revents = tmp_pfd.revents; + + if ((revents & POLLNVAL) /* busted in all cases */ + || ((events & POLLOUT) && (revents & POLLHUP))) + /* write op & hup */ + { + op->result.code = -1; + if (POLLNVAL & revents) op->syserrno = EBADF; + else if (POLLHUP & revents) op->syserrno = EPIPE; + op->status = pt_continuation_done; + } else { + if (op->function(op, revents)) + op->status = pt_continuation_done; + } + } else if (rv == -1) { + op->result.code = -1; + op->syserrno = errno; + op->status = pt_continuation_done; + } + /* else, poll timed out */ + } while (pt_continuation_done != op->status); + break; + default: + now = epoch = PR_IntervalNow(); + remaining = op->timeout; + do + { + PRIntn rv; + struct pollfd tmp_pfd; + + tmp_pfd.revents = 0; + tmp_pfd.fd = op->arg1.osfd; + tmp_pfd.events = op->event; + + msecs = (PRInt32)PR_IntervalToMilliseconds(remaining); + if (msecs > PT_DEFAULT_POLL_MSEC) + msecs = PT_DEFAULT_POLL_MSEC; + rv = poll(&tmp_pfd, 1, msecs); + + if (self->state & PT_THREAD_ABORTED) + { + self->state &= ~PT_THREAD_ABORTED; + op->result.code = -1; + op->syserrno = EINTR; + op->status = pt_continuation_done; + return; + } + + if (rv > 0) + { + PRInt16 events = tmp_pfd.events; + PRInt16 revents = tmp_pfd.revents; + + if ((revents & POLLNVAL) /* busted in all cases */ + || ((events & POLLOUT) && (revents & POLLHUP))) + /* write op & hup */ + { + op->result.code = -1; + if (POLLNVAL & revents) op->syserrno = EBADF; + else if (POLLHUP & revents) op->syserrno = EPIPE; + op->status = pt_continuation_done; + } else { + if (op->function(op, revents)) + { + op->status = pt_continuation_done; + } + } + } else if ((rv == 0) || + ((errno == EINTR) || (errno == EAGAIN))) { + if (rv == 0) /* poll timed out */ + now += PR_MillisecondsToInterval(msecs); + else + now = PR_IntervalNow(); + elapsed = (PRIntervalTime) (now - epoch); + if (elapsed >= op->timeout) { + op->result.code = -1; + op->syserrno = ETIMEDOUT; + op->status = pt_continuation_done; + } else + remaining = op->timeout - elapsed; + } else { + op->result.code = -1; + op->syserrno = errno; + op->status = pt_continuation_done; + } + } while (pt_continuation_done != op->status); + break; + } + +} /* pt_poll_now */ static PRIntn pt_Continue(pt_Continuation *op) { - PRStatus rv; - PRThread *self = PR_GetCurrentThread(); - struct pt_TimedQueue *tqp; - - /* lazy assignment of the thread's ioq */ - if (-1 == self->io_tq_index) - { - self->io_tq_index = (PR_AtomicIncrement(&_pt_tq_index)-1) % _pt_tq_count; - } - - PR_ASSERT(self->io_tq_index >= 0); - tqp = &pt_tqp[self->io_tq_index]; - - /* lazy allocation of the thread's cv */ - if (NULL == self->io_cv) - self->io_cv = PR_NewCondVar(tqp->ml); - /* Finish filling in the blank slots */ - op->complete = self->io_cv; op->status = pt_continuation_pending; /* set default value */ - op->io_tq_index = self->io_tq_index; - PR_Lock(tqp->ml); /* we provide the locking */ - - pt_InsertTimedInternal(op); /* insert in the structure */ - - /* - ** At this point, we try to decide whether there is a continuation - ** thread, or whether we should assign this one to serve in that role. - */ - do - { - if (NULL == tqp->thread) - { - /* - ** We're the one. Call the processing function with the lock - ** held. It will return with it held as well, though there - ** will certainly be times within the function when it gets - ** released. - */ - tqp->thread = self; /* I'm taking control */ - pt_ContinuationThreadInternal(op); /* go slash and burn */ - PR_ASSERT(pt_continuation_done == op->status); - tqp->thread = NULL; /* I'm abdicating my rule */ - } - else - { - rv = PR_WaitCondVar(op->complete, PR_INTERVAL_NO_TIMEOUT); - /* - * If we get interrupted, we set state the continuation thread will - * see and allow it to finish the I/O operation w/ error. That way - * the rule that only the continuation thread is removing elements - * from the list is still valid. - * - * Don't call interrupt on the continuation thread. That'll just - * irritate him. He's cycling around at least every mx_poll_ticks - * anyhow and should notice the request in there. When he does - * notice, this operation will be finished and the op's status - * marked as pt_continuation_done. - */ - if ((PR_FAILURE == rv) /* the wait was interrupted */ - && (PR_PENDING_INTERRUPT_ERROR == PR_GetError())) - { - if (pt_continuation_done == op->status) - { - /* - * The op is done and has been removed - * from the timed queue. We must not - * change op->status, otherwise this - * thread will go around the loop again. - * - * It's harsh to mark the op failed with - * interrupt error when the io is already - * done, but we should indicate the fact - * that the thread was interrupted. So - * we set the aborted flag to abort the - * thread's next blocking call. Is this - * the right thing to do? - */ - self->state |= PT_THREAD_ABORTED; - } - else - { - /* go around the loop again */ - op->status = pt_continuation_abort; - } - } - /* - * If we're to recycle, continue within this loop. This will - * cause this thread to become the continuation thread. - */ - - } - } while (pt_continuation_done != op->status); - - - PR_Unlock(tqp->ml); /* we provided the locking */ - - return op->result.code; /* and the primary answer */ + /* + * let each thread call poll directly + */ + pt_poll_now(op); + PR_ASSERT(pt_continuation_done == op->status); + return op->result.code; } /* pt_Continue */ /*****************************************************************************/ @@ -1290,52 +749,8 @@ static PRBool pt_hpux_sendfile_cont(pt_Continuation *op, PRInt16 revents) } #endif /* HPUX11 */ -#define _MD_CPUS_ONLINE 2 - void _PR_InitIO() { - PRIntn index; - char *num_io_queues; - - if (NULL != (num_io_queues = getenv("NSPR_NUM_IO_QUEUES"))) - { - _pt_tq_count = atoi(num_io_queues); - } - else - { - /* - * Get the number of CPUs if the pthread - * library has kernel-scheduled entities that - * can run on multiple CPUs. - */ -#ifdef HPUX11 - _pt_num_cpus = pthread_num_processors_np(); -#elif defined(IRIX) || defined(OSF1) - _pt_num_cpus = sysconf(_SC_NPROC_ONLN); -#elif defined(AIX) || defined(LINUX) || defined(SOLARIS) - _pt_num_cpus = sysconf(_SC_NPROCESSORS_ONLN); -#else - /* - * A pure user-level (Mx1) pthread library can - * only use one CPU, even on a multiprocessor. - */ - _pt_num_cpus = 1; -#endif - if (_pt_num_cpus < 0) - _pt_num_cpus = _MD_CPUS_ONLINE; - _pt_tq_count = _pt_num_cpus; - } - - pt_tqp = (struct pt_TimedQueue *) - PR_CALLOC(_pt_tq_count * sizeof(struct pt_TimedQueue)); - PR_ASSERT(NULL != pt_tqp); - - for (index = 0; index < _pt_tq_count; index++) - { - pt_tqp[index].ml = PR_NewLock(); - PR_ASSERT(NULL != pt_tqp[index].ml); - } - #if defined(DEBUG) memset(&pt_debug, 0, sizeof(PTDebug)); pt_debug.timeStarted = PR_Now(); @@ -1348,10 +763,11 @@ void _PR_InitIO() _PR_InitFdCache(); /* do that */ - _pr_stdin = pt_SetMethods(0, PR_DESC_FILE); - _pr_stdout = pt_SetMethods(1, PR_DESC_FILE); - _pr_stderr = pt_SetMethods(2, PR_DESC_FILE); + _pr_stdin = pt_SetMethods(0, PR_DESC_FILE, PR_FALSE); + _pr_stdout = pt_SetMethods(1, PR_DESC_FILE, PR_FALSE); + _pr_stderr = pt_SetMethods(2, PR_DESC_FILE, PR_FALSE); PR_ASSERT(_pr_stdin && _pr_stdout && _pr_stderr); + } /* _PR_InitIO */ PR_IMPLEMENT(PRFileDesc*) PR_GetSpecialFD(PRSpecialFD osfd) @@ -1438,7 +854,6 @@ static PRInt32 pt_Read(PRFileDesc *fd, void *buf, PRInt32 amount) && (!fd->secret->nonblocking)) { pt_Continuation op; - op.fd = fd; op.arg1.osfd = fd->secret->md.osfd; op.arg2.buffer = buf; op.arg3.amount = amount; @@ -1479,7 +894,6 @@ static PRInt32 pt_Write(PRFileDesc *fd, const void *buf, PRInt32 amount) if (fNeedContinue == PR_TRUE) { pt_Continuation op; - op.fd = fd; op.arg1.osfd = fd->secret->md.osfd; op.arg2.buffer = (void*)buf; op.arg3.amount = amount; @@ -1573,7 +987,6 @@ static PRInt32 pt_Writev( { pt_Continuation op; - op.fd = fd; op.arg1.osfd = fd->secret->md.osfd; op.arg2.buffer = (void*)osiov; op.arg3.amount = osiov_len; @@ -1690,7 +1103,9 @@ static PRStatus pt_Connect( { PRIntn rv = -1, syserrno; pt_SockLen addr_len; -#ifdef _PR_HAVE_SOCKADDR_LEN + const PRNetAddr *addrp = addr; +#if defined(_PR_HAVE_SOCKADDR_LEN) || defined(_PR_INET6) + PRUint16 md_af = addr->raw.family; PRNetAddr addrCopy; #endif @@ -1698,13 +1113,24 @@ static PRStatus pt_Connect( PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE); addr_len = PR_NETADDR_SIZE(addr); +#if defined(_PR_INET6) + if (addr->raw.family == PR_AF_INET6) { + md_af = AF_INET6; +#ifndef _PR_HAVE_SOCKADDR_LEN + addrCopy = *addr; + addrCopy.raw.family = AF_INET6; + addrp = &addrCopy; +#endif + } +#endif + #ifdef _PR_HAVE_SOCKADDR_LEN addrCopy = *addr; ((struct sockaddr*)&addrCopy)->sa_len = addr_len; - ((struct sockaddr*)&addrCopy)->sa_family = addr->raw.family; + ((struct sockaddr*)&addrCopy)->sa_family = md_af; rv = connect(fd->secret->md.osfd, (struct sockaddr*)&addrCopy, addr_len); #else - rv = connect(fd->secret->md.osfd, (struct sockaddr*)addr, addr_len); + rv = connect(fd->secret->md.osfd, (struct sockaddr*)addrp, addr_len); #endif syserrno = errno; if ((-1 == rv) && (EINPROGRESS == syserrno) && (!fd->secret->nonblocking)) @@ -1713,7 +1139,6 @@ static PRStatus pt_Connect( else { pt_Continuation op; - op.fd = fd; op.arg1.osfd = fd->secret->md.osfd; #ifdef _PR_HAVE_SOCKADDR_LEN op.arg2.buffer = (void*)&addrCopy; @@ -1788,7 +1213,6 @@ static PRFileDesc* pt_Accept( else { pt_Continuation op; - op.fd = fd; op.arg1.osfd = fd->secret->md.osfd; op.arg2.buffer = addr; op.arg3.addr_len = &addr_len; @@ -1808,7 +1232,11 @@ static PRFileDesc* pt_Accept( addr->raw.family = ((struct sockaddr*)addr)->sa_family; } #endif /* _PR_HAVE_SOCKADDR_LEN */ - newfd = pt_SetMethods(osfd, PR_DESC_SOCKET_TCP); +#ifdef _PR_INET6 + if (addr && (AF_INET6 == addr->raw.family)) + addr->raw.family = PR_AF_INET6; +#endif + newfd = pt_SetMethods(osfd, PR_DESC_SOCKET_TCP, PR_TRUE); if (newfd == NULL) close(osfd); /* $$$ whoops! this doesn't work $$$ */ else { @@ -1826,14 +1254,15 @@ static PRStatus pt_Bind(PRFileDesc *fd, const PRNetAddr *addr) { PRIntn rv; pt_SockLen addr_len; -#ifdef _PR_HAVE_SOCKADDR_LEN + const PRNetAddr *addrp = addr; +#if defined(_PR_HAVE_SOCKADDR_LEN) || defined(_PR_INET6) + PRUint16 md_af = addr->raw.family; PRNetAddr addrCopy; #endif if (pt_TestAbort()) return PR_FAILURE; PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE); - if (addr->raw.family == AF_UNIX) { /* Disallow relative pathnames */ @@ -1844,14 +1273,25 @@ static PRStatus pt_Bind(PRFileDesc *fd, const PRNetAddr *addr) } } +#if defined(_PR_INET6) + if (addr->raw.family == PR_AF_INET6) { + md_af = AF_INET6; +#ifndef _PR_HAVE_SOCKADDR_LEN + addrCopy = *addr; + addrCopy.raw.family = AF_INET6; + addrp = &addrCopy; +#endif + } +#endif + addr_len = PR_NETADDR_SIZE(addr); #ifdef _PR_HAVE_SOCKADDR_LEN addrCopy = *addr; ((struct sockaddr*)&addrCopy)->sa_len = addr_len; - ((struct sockaddr*)&addrCopy)->sa_family = addr->raw.family; + ((struct sockaddr*)&addrCopy)->sa_family = md_af; rv = bind(fd->secret->md.osfd, (struct sockaddr*)&addrCopy, addr_len); #else - rv = bind(fd->secret->md.osfd, (struct sockaddr*)addr, addr_len); + rv = bind(fd->secret->md.osfd, (struct sockaddr*)addrp, addr_len); #endif if (rv == -1) { @@ -1919,7 +1359,6 @@ static PRInt32 pt_Recv( else { pt_Continuation op; - op.fd = fd; op.arg1.osfd = fd->secret->md.osfd; op.arg2.buffer = buf; op.arg3.amount = amount; @@ -2004,7 +1443,6 @@ static PRInt32 pt_Send( if (fNeedContinue == PR_TRUE) { pt_Continuation op; - op.fd = fd; op.arg1.osfd = fd->secret->md.osfd; op.arg2.buffer = (void*)buf; op.arg3.amount = amount; @@ -2034,25 +1472,38 @@ static PRInt32 pt_SendTo( PRInt32 syserrno, bytes = -1; PRBool fNeedContinue = PR_FALSE; pt_SockLen addr_len; -#ifdef _PR_HAVE_SOCKADDR_LEN + const PRNetAddr *addrp = addr; +#if defined(_PR_HAVE_SOCKADDR_LEN) || defined(_PR_INET6) + PRUint16 md_af = addr->raw.family; PRNetAddr addrCopy; #endif if (pt_TestAbort()) return bytes; PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE); +#if defined(_PR_INET6) + if (addr->raw.family == PR_AF_INET6) { + md_af = AF_INET6; +#ifndef _PR_HAVE_SOCKADDR_LEN + addrCopy = *addr; + addrCopy.raw.family = AF_INET6; + addrp = &addrCopy; +#endif + } +#endif + addr_len = PR_NETADDR_SIZE(addr); #ifdef _PR_HAVE_SOCKADDR_LEN addrCopy = *addr; ((struct sockaddr*)&addrCopy)->sa_len = addr_len; - ((struct sockaddr*)&addrCopy)->sa_family = addr->raw.family; + ((struct sockaddr*)&addrCopy)->sa_family = md_af; bytes = sendto( fd->secret->md.osfd, buf, amount, flags, (struct sockaddr*)&addrCopy, addr_len); #else bytes = sendto( fd->secret->md.osfd, buf, amount, flags, - (struct sockaddr*)addr, addr_len); + (struct sockaddr*)addrp, addr_len); #endif syserrno = errno; if ( (bytes == -1) && (syserrno == EWOULDBLOCK || syserrno == EAGAIN) @@ -2064,7 +1515,6 @@ static PRInt32 pt_SendTo( if (fNeedContinue == PR_TRUE) { pt_Continuation op; - op.fd = fd; op.arg1.osfd = fd->secret->md.osfd; op.arg2.buffer = (void*)buf; op.arg3.amount = amount; @@ -2110,7 +1560,6 @@ static PRInt32 pt_RecvFrom(PRFileDesc *fd, void *buf, PRInt32 amount, if (fNeedContinue == PR_TRUE) { pt_Continuation op; - op.fd = fd; op.arg1.osfd = fd->secret->md.osfd; op.arg2.buffer = buf; op.arg3.amount = amount; @@ -2132,6 +1581,10 @@ static PRInt32 pt_RecvFrom(PRFileDesc *fd, void *buf, PRInt32 amount, } } #endif /* _PR_HAVE_SOCKADDR_LEN */ +#ifdef _PR_INET6 + if (addr && (AF_INET6 == addr->raw.family)) + addr->raw.family = PR_AF_INET6; +#endif if (bytes < 0) pt_MapError(_PR_MD_MAP_RECVFROM_ERROR, syserrno); return bytes; @@ -2238,7 +1691,6 @@ static PRInt32 pt_AIXSendFile(PRFileDesc *sd, PRSendFileData *sfd, if ((rv == 1) || ((rv == -1) && (count == 0))) { pt_Continuation op; - op.fd = sd; op.arg1.osfd = sd->secret->md.osfd; op.arg2.buffer = &sf_struct; op.arg4.flags = send_flags; @@ -2357,7 +1809,6 @@ static PRInt32 pt_HPUXSendFile(PRFileDesc *sd, PRSendFileData *sfd, hdtrl[1].iov_len = sfd->tlen - trailer_nbytes_sent; } - op.fd = sd; op.arg1.osfd = sd->secret->md.osfd; op.filedesc = sfd->fd->secret->md.osfd; op.arg2.buffer = hdtrl; @@ -2503,6 +1954,10 @@ static PRStatus pt_GetSockName(PRFileDesc *fd, PRNetAddr *addr) addr->raw.family = ((struct sockaddr*)addr)->sa_family; } #endif /* _PR_HAVE_SOCKADDR_LEN */ +#ifdef _PR_INET6 + if (AF_INET6 == addr->raw.family) + addr->raw.family = PR_AF_INET6; +#endif PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE); PR_ASSERT(IsValidNetAddrLen(addr, addr_len) == PR_TRUE); return PR_SUCCESS; @@ -2530,113 +1985,16 @@ static PRStatus pt_GetPeerName(PRFileDesc *fd, PRNetAddr *addr) addr->raw.family = ((struct sockaddr*)addr)->sa_family; } #endif /* _PR_HAVE_SOCKADDR_LEN */ +#ifdef _PR_INET6 + if (AF_INET6 == addr->raw.family) + addr->raw.family = PR_AF_INET6; +#endif PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE); PR_ASSERT(IsValidNetAddrLen(addr, addr_len) == PR_TRUE); return PR_SUCCESS; } } /* pt_GetPeerName */ -static PRStatus pt_GetSockOpt( - PRFileDesc *fd, PRSockOption optname, void* optval, PRInt32* optlen) -{ - PRIntn rv = -1; - PRInt32 level, name; - - if (pt_TestAbort()) return PR_FAILURE; - - /* - * PR_SockOpt_Nonblocking is a special case that does not - * translate to a getsockopt() call. - */ - if (PR_SockOpt_Nonblocking == optname) - { - PR_ASSERT(sizeof(PRIntn) <= *optlen); - *((PRIntn *) optval) = (PRIntn) fd->secret->nonblocking; - *optlen = sizeof(PRIntn); - return PR_SUCCESS; - } - - rv = _PR_MapOptionName(optname, &level, &name); - if (0 == rv) - { - if (PR_SockOpt_Linger == optname) - { - struct linger linger; - pt_SockLen len = sizeof(linger); - rv = getsockopt(fd->secret->md.osfd, level, name, - (char *) &linger, &len); - if (0 == rv) - { - ((PRLinger*)(optval))->polarity = linger.l_onoff - ? PR_TRUE : PR_FALSE; - ((PRLinger*)(optval))->linger = PR_SecondsToInterval( - linger.l_linger); - *optlen = sizeof(PRLinger); - } - } - else - { - /* Make sure the pointer type cast below is safe */ - PR_ASSERT(sizeof(PRInt32) == sizeof(PRIntn)); - rv = getsockopt(fd->secret->md.osfd, level, name, - optval, (pt_SockLen*)optlen); - } - } - - if (rv == -1) { - pt_MapError(_PR_MD_MAP_GETSOCKOPT_ERROR, errno); - return PR_FAILURE; - } else { - return PR_SUCCESS; - } -} /* pt_GetSockOpt */ - -static PRStatus pt_SetSockOpt( - PRFileDesc *fd, PRSockOption optname, const void* optval, PRInt32 optlen) -{ - PRIntn rv = -1; - PRInt32 level, name; - - if (pt_TestAbort()) return PR_FAILURE; - - /* - * PR_SockOpt_Nonblocking is a special case that does not - * translate to a setsockopt() call. - */ - if (PR_SockOpt_Nonblocking == optname) - { - PR_ASSERT(sizeof(PRIntn) == optlen); - fd->secret->nonblocking = *((PRIntn *) optval) ? PR_TRUE : PR_FALSE; - return PR_SUCCESS; - } - - rv = _PR_MapOptionName(optname, &level, &name); - if (0 == rv) - { - if (PR_SockOpt_Linger == optname) - { - struct linger linger; - linger.l_onoff = ((PRLinger*)(optval))->polarity; - linger.l_linger = PR_IntervalToSeconds( - ((PRLinger*)(optval))->linger); - rv = setsockopt(fd->secret->md.osfd, level, name, - (char *) &linger, sizeof(linger)); - } - else - { - rv = setsockopt(fd->secret->md.osfd, level, name, - optval, optlen); - } - } - - if (rv == -1) { - pt_MapError(_PR_MD_MAP_SETSOCKOPT_ERROR, errno); - return PR_FAILURE; - } else { - return PR_SUCCESS; - } -} /* pt_SetSockOpt */ - static PRStatus pt_GetSocketOption(PRFileDesc *fd, PRSocketOptionData *data) { PRIntn rv; @@ -2896,8 +2254,8 @@ static PRIOMethods _pr_file_methods = { (PRTransmitfileFN)_PR_InvalidInt, (PRGetsocknameFN)_PR_InvalidStatus, (PRGetpeernameFN)_PR_InvalidStatus, - (PRGetsockoptFN)_PR_InvalidStatus, - (PRSetsockoptFN)_PR_InvalidStatus, + (PRReservedFN)_PR_InvalidInt, + (PRReservedFN)_PR_InvalidInt, (PRGetsocketoptionFN)_PR_InvalidStatus, (PRSetsocketoptionFN)_PR_InvalidStatus, (PRSendfileFN)_PR_InvalidInt, @@ -2935,8 +2293,8 @@ static PRIOMethods _pr_pipe_methods = { (PRTransmitfileFN)_PR_InvalidInt, (PRGetsocknameFN)_PR_InvalidStatus, (PRGetpeernameFN)_PR_InvalidStatus, - (PRGetsockoptFN)_PR_InvalidStatus, - (PRSetsockoptFN)_PR_InvalidStatus, + (PRReservedFN)_PR_InvalidInt, + (PRReservedFN)_PR_InvalidInt, (PRGetsocketoptionFN)_PR_InvalidStatus, (PRSetsocketoptionFN)_PR_InvalidStatus, (PRSendfileFN)_PR_InvalidInt, @@ -2974,8 +2332,8 @@ static PRIOMethods _pr_tcp_methods = { pt_TransmitFile, pt_GetSockName, pt_GetPeerName, - pt_GetSockOpt, - pt_SetSockOpt, + (PRReservedFN)_PR_InvalidInt, + (PRReservedFN)_PR_InvalidInt, pt_GetSocketOption, pt_SetSocketOption, pt_SendFile, @@ -3013,8 +2371,8 @@ static PRIOMethods _pr_udp_methods = { (PRTransmitfileFN)_PR_InvalidInt, pt_GetSockName, pt_GetPeerName, - pt_GetSockOpt, - pt_SetSockOpt, + (PRReservedFN)_PR_InvalidInt, + (PRReservedFN)_PR_InvalidInt, pt_GetSocketOption, pt_SetSocketOption, (PRSendfileFN)_PR_InvalidInt, @@ -3025,7 +2383,6 @@ static PRIOMethods _pr_udp_methods = { (PRReservedFN)_PR_InvalidInt }; - static PRIOMethods _pr_socketpollfd_methods = { (PRDescType) 0, (PRCloseFN)_PR_InvalidStatus, @@ -3053,8 +2410,8 @@ static PRIOMethods _pr_socketpollfd_methods = { (PRTransmitfileFN)_PR_InvalidInt, (PRGetsocknameFN)_PR_InvalidStatus, (PRGetpeernameFN)_PR_InvalidStatus, - (PRGetsockoptFN)_PR_InvalidStatus, - (PRSetsockoptFN)_PR_InvalidStatus, + (PRReservedFN)_PR_InvalidInt, + (PRReservedFN)_PR_InvalidInt, (PRGetsocketoptionFN)_PR_InvalidStatus, (PRSetsocketoptionFN)_PR_InvalidStatus, (PRSendfileFN)_PR_InvalidInt, @@ -3065,10 +2422,6 @@ static PRIOMethods _pr_socketpollfd_methods = { (PRReservedFN)_PR_InvalidInt }; -#if defined(_PR_FCNTL_FLAGS) -#undef _PR_FCNTL_FLAGS -#endif - #if defined(HPUX) || defined(OSF1) || defined(SOLARIS) || defined (IRIX) \ || defined(AIX) || defined(LINUX) || defined(FREEBSD) || defined(NETBSD) \ || defined(OPENBSD) || defined(BSDI) || defined(VMS) || defined(NTO) @@ -3077,9 +2430,58 @@ static PRIOMethods _pr_socketpollfd_methods = { #error "Can't determine architecture" #endif -static PRFileDesc *pt_SetMethods(PRIntn osfd, PRDescType type) +/* + * Put a Unix file descriptor in non-blocking mode. + */ +static void pt_MakeFdNonblock(PRIntn osfd) +{ + PRIntn flags; + flags = fcntl(osfd, F_GETFL, 0); + flags |= _PR_FCNTL_FLAGS; + (void)fcntl(osfd, F_SETFL, flags); +} + +/* + * Put a Unix socket fd in non-blocking mode that can + * ideally be inherited by an accepted socket. + * + * Why doesn't pt_MakeFdNonblock do? This is to deal with + * the special case of HP-UX. HP-UX has three kinds of + * non-blocking modes for sockets: the fcntl() O_NONBLOCK + * and O_NDELAY flags and ioctl() FIOSNBIO request. Only + * the ioctl() FIOSNBIO form of non-blocking mode is + * inherited by an accepted socket. + * + * Other platforms just use the generic pt_MakeFdNonblock + * to put a socket in non-blocking mode. + */ +#ifdef HPUX +static void pt_MakeSocketNonblock(PRIntn osfd) +{ + PRIntn one = 1; + (void)ioctl(osfd, FIOSNBIO, &one); +} +#else +#define pt_MakeSocketNonblock pt_MakeFdNonblock +#endif + +#ifdef DEBUG +static void pt_AssertCloseOnExecIsCleared(PRIntn osfd) +{ + /* + * Ignore EBADF error on fd's 0, 1, 2 because they are + * not open in all processes. + */ + PRIntn flags; + flags = fcntl(osfd, F_GETFD, 0); + PR_ASSERT((0 == flags) || (-1 == flags + && (0 <= osfd && osfd <= 2) && errno == EBADF)); +} +#endif + +static PRFileDesc *pt_SetMethods( + PRIntn osfd, PRDescType type, PRBool isAcceptedSocket) { - PRInt32 flags; PRFileDesc *fd = _PR_Getfd(); if (fd == NULL) PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); @@ -3089,13 +2491,7 @@ static PRFileDesc *pt_SetMethods(PRIntn osfd, PRDescType type) fd->secret->state = _PR_FILEDESC_OPEN; /* By default, a Unix fd is not closed on exec. */ #ifdef DEBUG - /* - * Ignore EBADF error on fd's 0, 1, 2 because they are - * not open in all processes. - */ - flags = fcntl(osfd, F_GETFD, 0); - PR_ASSERT((0 == flags) || (-1 == flags - && (0 <= osfd && osfd <= 2) && errno == EBADF)); + pt_AssertCloseOnExecIsCleared(osfd); #endif fd->secret->inheritable = PR_TRUE; switch (type) @@ -3105,18 +2501,19 @@ static PRFileDesc *pt_SetMethods(PRIntn osfd, PRDescType type) break; case PR_DESC_SOCKET_TCP: fd->methods = PR_GetTCPMethods(); - flags = fcntl(osfd, F_GETFL, 0); - flags |= _PR_FCNTL_FLAGS; - (void)fcntl(osfd, F_SETFL, flags); +#ifdef _PR_ACCEPT_INHERIT_NONBLOCK + if (!isAcceptedSocket) pt_MakeSocketNonblock(osfd); +#else + pt_MakeSocketNonblock(osfd); +#endif break; case PR_DESC_SOCKET_UDP: fd->methods = PR_GetUDPMethods(); - flags = fcntl(osfd, F_GETFL, 0); - flags |= _PR_FCNTL_FLAGS; - (void)fcntl(osfd, F_SETFL, flags); + pt_MakeFdNonblock(osfd); break; case PR_DESC_PIPE: fd->methods = PR_GetPipeMethods(); + pt_MakeFdNonblock(osfd); break; default: break; @@ -3168,13 +2565,14 @@ PR_IMPLEMENT(PRFileDesc*) PR_AllocFileDesc( if (osfd > 2) { /* Don't mess around with stdin, stdout or stderr */ - PRIntn flags; - flags = fcntl(osfd, F_GETFL, 0); - fcntl(osfd, F_SETFL, flags | _PR_FCNTL_FLAGS); + if (&_pr_tcp_methods == methods) pt_MakeSocketNonblock(osfd); + else pt_MakeFdNonblock(osfd); } fd->secret->state = _PR_FILEDESC_OPEN; /* By default, a Unix fd is not closed on exec. */ - PR_ASSERT(0 == fcntl(osfd, F_GETFD, 0)); +#ifdef DEBUG + pt_AssertCloseOnExecIsCleared(osfd); +#endif fd->secret->inheritable = PR_TRUE; return fd; @@ -3183,40 +2581,91 @@ failed: return fd; } /* PR_AllocFileDesc */ +#if !defined(_PR_INET6) || defined(_PR_INET6_PROBE) +PR_EXTERN(PRStatus) _pr_push_ipv6toipv4_layer(PRFileDesc *fd); +#if defined(_PR_INET6_PROBE) +PR_EXTERN(PRBool) _pr_ipv6_is_present; +PR_IMPLEMENT(PRBool) _pr_test_ipv6_socket() +{ +PRInt32 osfd; + + osfd = socket(AF_INET6, SOCK_STREAM, 0); + if (osfd != -1) { + close(osfd); + return PR_TRUE; + } + return PR_FALSE; +} +#endif /* _PR_INET6_PROBE */ +#endif + PR_IMPLEMENT(PRFileDesc*) PR_Socket(PRInt32 domain, PRInt32 type, PRInt32 proto) { PRIntn osfd; PRDescType ftype; PRFileDesc *fd = NULL; + PRInt32 tmp_domain = domain; if (!_pr_initialized) _PR_ImplicitInitialization(); if (pt_TestAbort()) return NULL; if (PF_INET != domain -#if defined(_PR_INET6) - && PF_INET6 != domain -#endif + && PR_AF_INET6 != domain && PF_UNIX != domain) { PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, 0); return fd; } - if (type == SOCK_STREAM) ftype = PR_DESC_SOCKET_TCP; - else if (type == SOCK_DGRAM) ftype = PR_DESC_SOCKET_UDP; - else - { - (void)PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, 0); - return fd; - } + if (type == SOCK_STREAM) ftype = PR_DESC_SOCKET_TCP; + else if (type == SOCK_DGRAM) ftype = PR_DESC_SOCKET_UDP; + else + { + (void)PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, 0); + return fd; + } +#if defined(_PR_INET6) + if (PR_AF_INET6 == domain) { +#if defined(_PR_INET6_PROBE) + if (_pr_ipv6_is_present == PR_FALSE) + domain = AF_INET; + else +#endif + domain = AF_INET6; + } +#elif defined(_PR_INET6_PROBE) + if (PR_AF_INET6 == domain) { + if (_pr_ipv6_is_present == PR_FALSE) + domain = AF_INET; + else + domain = AF_INET6; + } +#else + if (PR_AF_INET6 == domain) + domain = AF_INET; +#endif osfd = socket(domain, type, proto); if (osfd == -1) pt_MapError(_PR_MD_MAP_SOCKET_ERROR, errno); else { - fd = pt_SetMethods(osfd, ftype); + fd = pt_SetMethods(osfd, ftype, PR_FALSE); if (fd == NULL) close(osfd); } +#if !defined(_PR_INET6) || defined(_PR_INET6_PROBE) + if (fd != NULL) { + /* + * For platforms with no support for IPv6 + * create layered socket for IPv4-mapped IPv6 addresses + */ + if (PR_AF_INET6 == tmp_domain && PR_AF_INET == domain) { + if (PR_FAILURE == _pr_push_ipv6toipv4_layer(fd)) { + PR_Close(fd); + fd = NULL; + } + } + } +#endif return fd; } /* PR_Socket */ @@ -3224,7 +2673,8 @@ PR_IMPLEMENT(PRFileDesc*) PR_Socket(PRInt32 domain, PRInt32 type, PRInt32 proto) /****************************** I/O public methods ***************************/ /*****************************************************************************/ -PR_IMPLEMENT(PRFileDesc*) PR_Open(const char *name, PRIntn flags, PRIntn mode) +PR_IMPLEMENT(PRFileDesc*) PR_OpenFile( + const char *name, PRIntn flags, PRIntn mode) { PRFileDesc *fd = NULL; PRIntn syserrno, osfd = -1, osflags = 0;; @@ -3238,6 +2688,17 @@ PR_IMPLEMENT(PRFileDesc*) PR_Open(const char *name, PRIntn flags, PRIntn mode) if (flags & PR_RDWR) osflags |= O_RDWR; if (flags & PR_APPEND) osflags |= O_APPEND; if (flags & PR_TRUNCATE) osflags |= O_TRUNC; + if (flags & PR_EXCL) osflags |= O_EXCL; + if (flags & PR_SYNC) + { +#if defined(O_SYNC) + osflags |= O_SYNC; +#elif defined(O_FSYNC) + osflags |= O_FSYNC; +#else +#error "Neither O_SYNC nor O_FSYNC is defined on this platform" +#endif + } /* ** We have to hold the lock across the creation in order to @@ -3261,10 +2722,15 @@ PR_IMPLEMENT(PRFileDesc*) PR_Open(const char *name, PRIntn flags, PRIntn mode) pt_MapError(_PR_MD_MAP_OPEN_ERROR, syserrno); else { - fd = pt_SetMethods(osfd, PR_DESC_FILE); + fd = pt_SetMethods(osfd, PR_DESC_FILE, PR_FALSE); if (fd == NULL) close(osfd); /* $$$ whoops! this is bad $$$ */ } return fd; +} /* PR_OpenFile */ + +PR_IMPLEMENT(PRFileDesc*) PR_Open(const char *name, PRIntn flags, PRIntn mode) +{ + return PR_OpenFile(name, flags, mode); } /* PR_Open */ PR_IMPLEMENT(PRStatus) PR_Delete(const char *name) @@ -3371,7 +2837,7 @@ PR_IMPLEMENT(PRStatus) PR_CloseDir(PRDir *dir) return PR_SUCCESS; } /* PR_CloseDir */ -PR_IMPLEMENT(PRStatus) PR_MkDir(const char *name, PRIntn mode) +PR_IMPLEMENT(PRStatus) PR_MakeDir(const char *name, PRIntn mode) { PRInt32 rv = -1; @@ -3390,6 +2856,11 @@ PR_IMPLEMENT(PRStatus) PR_MkDir(const char *name, PRIntn mode) PR_Unlock(_pr_rename_lock); return (-1 == rv) ? PR_FAILURE : PR_SUCCESS; +} /* PR_Makedir */ + +PR_IMPLEMENT(PRStatus) PR_MkDir(const char *name, PRIntn mode) +{ + return PR_MakeDir(name, mode); } /* PR_Mkdir */ PR_IMPLEMENT(PRStatus) PR_RmDir(const char *name) @@ -3694,10 +3165,6 @@ PR_IMPLEMENT(PRFileDesc*) PR_NewUDPSocket() { PRIntn domain = PF_INET; -#if defined(_PR_INET6) - if (_pr_ipv6_enabled) - domain = PF_INET6; -#endif return PR_Socket(domain, SOCK_DGRAM, 0); } /* PR_NewUDPSocket */ @@ -3705,10 +3172,6 @@ PR_IMPLEMENT(PRFileDesc*) PR_NewTCPSocket() { PRIntn domain = PF_INET; -#if defined(_PR_INET6) - if (_pr_ipv6_enabled) - domain = PF_INET6; -#endif return PR_Socket(domain, SOCK_STREAM, 0); } /* PR_NewTCPSocket */ @@ -3733,13 +3196,13 @@ PR_IMPLEMENT(PRStatus) PR_NewTCPSocketPair(PRFileDesc *fds[2]) return PR_FAILURE; } - fds[0] = pt_SetMethods(osfd[0], PR_DESC_SOCKET_TCP); + fds[0] = pt_SetMethods(osfd[0], PR_DESC_SOCKET_TCP, PR_FALSE); if (fds[0] == NULL) { close(osfd[0]); close(osfd[1]); return PR_FAILURE; } - fds[1] = pt_SetMethods(osfd[1], PR_DESC_SOCKET_TCP); + fds[1] = pt_SetMethods(osfd[1], PR_DESC_SOCKET_TCP, PR_FALSE); if (fds[1] == NULL) { PR_Close(fds[0]); close(osfd[1]); @@ -3754,7 +3217,6 @@ PR_IMPLEMENT(PRStatus) PR_CreatePipe( ) { int pipefd[2]; - int flags; if (pt_TestAbort()) return PR_FAILURE; @@ -3764,26 +3226,20 @@ PR_IMPLEMENT(PRStatus) PR_CreatePipe( PR_SetError(PR_UNKNOWN_ERROR, errno); return PR_FAILURE; } - *readPipe = pt_SetMethods(pipefd[0], PR_DESC_PIPE); + *readPipe = pt_SetMethods(pipefd[0], PR_DESC_PIPE, PR_FALSE); if (NULL == *readPipe) { close(pipefd[0]); close(pipefd[1]); return PR_FAILURE; } - flags = fcntl(pipefd[0], F_GETFL, 0); - flags |= _PR_FCNTL_FLAGS; - (void)fcntl(pipefd[0], F_SETFL, flags); - *writePipe = pt_SetMethods(pipefd[1], PR_DESC_PIPE); + *writePipe = pt_SetMethods(pipefd[1], PR_DESC_PIPE, PR_FALSE); if (NULL == *writePipe) { PR_Close(*readPipe); close(pipefd[1]); return PR_FAILURE; } - flags = fcntl(pipefd[1], F_GETFL, 0); - flags |= _PR_FCNTL_FLAGS; - (void)fcntl(pipefd[1], F_SETFL, flags); return PR_SUCCESS; } @@ -3824,7 +3280,7 @@ PR_IMPLEMENT(PRFileDesc*) PR_ImportFile(PRInt32 osfd) PRFileDesc *fd; if (!_pr_initialized) _PR_ImplicitInitialization(); - fd = pt_SetMethods(osfd, PR_DESC_FILE); + fd = pt_SetMethods(osfd, PR_DESC_FILE, PR_FALSE); if (NULL == fd) close(osfd); return fd; } /* PR_ImportFile */ @@ -3834,7 +3290,7 @@ PR_IMPLEMENT(PRFileDesc*) PR_ImportTCPSocket(PRInt32 osfd) PRFileDesc *fd; if (!_pr_initialized) _PR_ImplicitInitialization(); - fd = pt_SetMethods(osfd, PR_DESC_SOCKET_TCP); + fd = pt_SetMethods(osfd, PR_DESC_SOCKET_TCP, PR_FALSE); if (NULL == fd) close(osfd); return fd; } /* PR_ImportTCPSocket */ @@ -3844,7 +3300,7 @@ PR_IMPLEMENT(PRFileDesc*) PR_ImportUDPSocket(PRInt32 osfd) PRFileDesc *fd; if (!_pr_initialized) _PR_ImplicitInitialization(); - fd = pt_SetMethods(osfd, PR_DESC_SOCKET_UDP); + fd = pt_SetMethods(osfd, PR_DESC_SOCKET_UDP, PR_FALSE); if (NULL != fd) close(osfd); return fd; } /* PR_ImportUDPSocket */ diff --git a/pr/src/pthreads/ptsynch.c b/pr/src/pthreads/ptsynch.c index 0731786e..b3ff68da 100644 --- a/pr/src/pthreads/ptsynch.c +++ b/pr/src/pthreads/ptsynch.c @@ -761,7 +761,7 @@ PR_IMPLEMENT(PRStatus) PR_DeleteSemaphore(const char *name) * From the semctl(2) man page in glibc 2.0 */ #if (defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)) \ - || defined(FREEBSD) || defined(OPENBSD) + || defined(FREEBSD) || defined(OPENBSD) || defined(BSDI) /* union semun is defined by including <sys/sem.h> */ #else /* according to X/OPEN we have to define it ourselves */ diff --git a/pr/src/pthreads/ptthread.c b/pr/src/pthreads/ptthread.c index 8e81c202..23189c53 100644 --- a/pr/src/pthreads/ptthread.c +++ b/pr/src/pthreads/ptthread.c @@ -158,16 +158,6 @@ static void *_pt_root(void *arg) /* unhook the thread from the runtime */ PR_Lock(pt_book.ml); - if (thred->state & PT_THREAD_SYSTEM) - pt_book.system -= 1; - else if (--pt_book.user == pt_book.this_many) - PR_NotifyAllCondVar(pt_book.cv); - thred->prev->next = thred->next; - if (NULL == thred->next) - pt_book.last = thred->prev; - else - thred->next->prev = thred->prev; - /* * At this moment, PR_CreateThread() may not have set thred->id yet. * It is safe for a detached thread to free thred only after @@ -178,6 +168,16 @@ static void *_pt_root(void *arg) while (!thred->okToDelete) PR_WaitCondVar(pt_book.cv, PR_INTERVAL_NO_TIMEOUT); } + + if (thred->state & PT_THREAD_SYSTEM) + pt_book.system -= 1; + else if (--pt_book.user == pt_book.this_many) + PR_NotifyAllCondVar(pt_book.cv); + thred->prev->next = thred->next; + if (NULL == thred->next) + pt_book.last = thred->prev; + else + thred->next->prev = thred->prev; PR_Unlock(pt_book.ml); /* @@ -224,7 +224,6 @@ static PRThread* pt_AttachThread(void) PR_ASSERT(0 == rv); thred->state = PT_THREAD_GLOBAL | PT_THREAD_FOREIGN; - thred->io_tq_index = -1; PR_Lock(pt_book.ml); /* then put it into the list */ @@ -363,8 +362,6 @@ static PRThread* _PR_CreateThread( thred->stack->stackSize = stackSize; thred->stack->thr = thred; - thred->io_tq_index = -1; - #ifdef PT_NO_SIGTIMEDWAIT pthread_mutex_init(&thred->suspendResumeMutex,NULL); pthread_cond_init(&thred->suspendResumeCV,NULL); @@ -740,8 +737,6 @@ static void _pt_thread_death(void *arg) PR_Free(thred->privateData); if (NULL != thred->errorString) PR_Free(thred->errorString); - if (NULL != thred->io_cv) - PR_DestroyCondVar(thred->io_cv); PR_Free(thred->stack); #if defined(DEBUG) memset(thred, 0xaf, sizeof(PRThread)); @@ -807,8 +802,6 @@ void _PR_InitThreads( thred->stack->thr = thred; _PR_InitializeStack(thred->stack); - thred->io_tq_index = -1; - /* * Create a key for our use to store a backpointer in the pthread * to our PRThread object. This object gets deleted when the thread diff --git a/pr/tests/Makefile b/pr/tests/Makefile index 7bf967f6..d1851723 100644 --- a/pr/tests/Makefile +++ b/pr/tests/Makefile @@ -39,6 +39,7 @@ endif CSRCS = \ accept.c \ acceptread.c \ + addrstr.c \ affinity.c \ alarm.c \ anonfm.c \ @@ -83,6 +84,8 @@ CSRCS = \ lock.c \ lockfile.c \ logger.c \ + makedir.c \ + mbcs.c \ multiacc.c \ multiwait.c \ many_cv.c \ @@ -91,12 +94,14 @@ CSRCS = \ nblayer.c \ nonblock.c \ ntioto.c \ + ntoh.c \ op_2long.c \ op_excl.c \ op_filnf.c \ op_filok.c \ op_noacc.c \ op_nofil.c \ + openfile.c \ parent.c \ perf.c \ pipeping.c \ diff --git a/pr/tests/Makefile.in b/pr/tests/Makefile.in index 9d6a0de9..30dad6d7 100644 --- a/pr/tests/Makefile.in +++ b/pr/tests/Makefile.in @@ -44,6 +44,7 @@ endif CSRCS = \ accept.c \ acceptread.c \ + addrstr.c \ affinity.c \ alarm.c \ anonfm.c \ @@ -88,6 +89,7 @@ CSRCS = \ lock.c \ lockfile.c \ logger.c \ + makedir.c \ multiacc.c \ multiwait.c \ many_cv.c \ @@ -96,12 +98,14 @@ CSRCS = \ nblayer.c \ nonblock.c \ ntioto.c \ + ntoh.c \ op_2long.c \ op_excl.c \ op_filnf.c \ op_filok.c \ op_noacc.c \ op_nofil.c \ + openfile.c \ parent.c \ perf.c \ pipeping.c \ @@ -439,7 +443,11 @@ endif # !USE_AUTOCONF include $(topsrcdir)/config/rules.mk -ifndef USE_AUTOCONF +ifdef USE_AUTOCONF +$(OBJDIR)/%$(PROG_SUFFIX): %.c + $(CC) $< -o $@ $(CFLAGS) $(LDOPTS) $(LIBPLC) $(LIBPR) $(OS_LIBS) + +else AIX_PRE_4_2 = 0 ifeq ($(OS_ARCH),AIX) ifeq ($(OS_RELEASE),4.1) @@ -508,6 +516,7 @@ install:: export clean:: rm -f $(TARGETS) +ifndef USE_AUTOCONF # The prpoll test calls BSD socket functions, so it needs to link # with -lsocket on some platforms. ifeq ($(OS_ARCH),SunOS) @@ -530,6 +539,8 @@ $(OBJDIR)/testfile: $(OBJDIR)/testfile.o $(PURE) $(CC) $(XCFLAGS) $< $(LDOPTS) $(LIBPLC) $(LIBPR) $(LIBPTHREAD) $(EXTRA_LIBS) -o $@ endif +endif # !USE_AUTOCONF + # # Run the test programs with no arguments # diff --git a/pr/tests/accept.c b/pr/tests/accept.c index e2fb0a05..1b64b5bd 100644 --- a/pr/tests/accept.c +++ b/pr/tests/accept.c @@ -84,7 +84,7 @@ static PRNetAddr listenAddr; static PRNetAddr clientAddr; static PRThread *clientThread; static PRNetAddr *raddr; -static char buf[4096 + 64]; +static char buf[4096 + 2*sizeof(PRNetAddr) + 32]; static PRInt32 status; static PRInt32 bytesRead; diff --git a/pr/tests/acceptread.c b/pr/tests/acceptread.c index d24e93c1..a6b257db 100644 --- a/pr/tests/acceptread.c +++ b/pr/tests/acceptread.c @@ -105,7 +105,7 @@ static void AcceptingThread(void *arg) PRStatus rv; PRInt32 bytes; PRSize buf_size = BUF_SIZE; - PRUint8 buf[BUF_SIZE + (20 * sizeof(PRNetAddr))]; + PRUint8 buf[BUF_SIZE + (2 * sizeof(PRNetAddr)) + 32]; PRNetAddr *accept_addr, *listen_addr = (PRNetAddr*)arg; PRFileDesc *accept_sock, *listen_sock = PR_NewTCPSocket(); PRSocketOptionData sock_opt; diff --git a/pr/tests/addrstr.c b/pr/tests/addrstr.c new file mode 100644 index 00000000..a20065e2 --- /dev/null +++ b/pr/tests/addrstr.c @@ -0,0 +1,95 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 2000 Netscape Communications Corporation. All Rights + * Reserved. + */ + +#include "prnetdb.h" + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +const char *testaddrs[] = { + "::", "::", + "::1", "::1", + "::ffff", "::ffff", + "::1:0", "::0.1.0.0", + "::127.0.0.1", "::127.0.0.1", + "::FFFF:127.0.0.1", "::ffff:127.0.0.1", + "::FFFE:9504:3501", "::fffe:9504:3501", + "0:0:1:0:35c:0:0:0", "0:0:1:0:35c::", + "0:0:3f4c:0:0:4552:0:0", "::3f4c:0:0:4552:0:0", + "0:0:1245:0:0:0:0567:0", "0:0:1245::567:0", + "0:1:2:3:4:5:6:7", "0:1:2:3:4:5:6:7", + "1:2:3:0:4:5:6:7", "1:2:3:0:4:5:6:7", + "1:2:3:4:5:6:7:0", "1:2:3:4:5:6:7:0", + "1:2:3:4:5:6:7:8", "1:2:3:4:5:6:7:8", + "1:2:3:4:5:6::7", "1:2:3:4:5:6:0:7", + 0 +}; + +const char *badaddrs[] = { + "::.1.2.3", + "ffff::.1.2.3", + "1:2:3:4:5:6:7::8", + "1:2:3:4:5:6::7:8", + "::ff99.2.3.4", + 0 +}; + +int failed_already = 0; + +int main() +{ + const char **nexttestaddr = testaddrs; + const char **nextbadaddr = badaddrs; + const char *in, *expected_out; + PRNetAddr addr; + char buf[256]; + PRStatus rv; + + while ((in = *nexttestaddr++) != 0) { + expected_out = *nexttestaddr++; + rv = PR_StringToNetAddr(in, &addr); + if (rv) { + printf("cannot convert %s to addr: %d\n", in, rv); + failed_already = 1; + continue; + } + rv = PR_NetAddrToString(&addr, buf, sizeof(buf)); + if (rv) { + printf("cannot convert %s back to string: %d\n", in, rv); + failed_already = 1; + continue; + } + if (strcmp(buf, expected_out)) { + /* This is not necessarily an error */ + printf("%s expected %s got %s\n", in, expected_out, buf); + } + } + while ((in = *nextbadaddr++) != 0) { + if (PR_StringToNetAddr(in, &addr) == PR_SUCCESS) { + printf("converted bad addr %s\n", in); + failed_already = 1; + } + } + if (failed_already) { + printf("FAIL\n"); + return 1; + } + printf("PASS\n"); + return 0; +} diff --git a/pr/tests/affinity.c b/pr/tests/affinity.c index fa0f5acb..c0609b19 100644 --- a/pr/tests/affinity.c +++ b/pr/tests/affinity.c @@ -17,6 +17,7 @@ */ #include "nspr.h" +#include "pprthred.h" #include "plgetopt.h" #include <stdio.h> diff --git a/pr/tests/cltsrv.c b/pr/tests/cltsrv.c index f19995c7..7c5becc0 100644 --- a/pr/tests/cltsrv.c +++ b/pr/tests/cltsrv.c @@ -83,7 +83,7 @@ #define DEFAULT_HIGH 0 #define BUFFER_SIZE 1024 #define DEFAULT_BACKLOG 5 -#define DEFAULT_PORT 12848 +#define DEFAULT_PORT 12849 #define DEFAULT_CLIENTS 1 #define ALLOWED_IN_ACCEPT 1 #define DEFAULT_CLIPPING 1000 @@ -773,8 +773,11 @@ static void PR_CALLBACK Server(void *arg) TEST_ASSERT(PR_SUCCESS == rv); memset(&serverAddress, 0, sizeof(serverAddress)); - rv = PR_InitializeNetAddr(PR_IpAddrAny, DEFAULT_PORT, &serverAddress); - + if (PR_AF_INET6 != domain) + rv = PR_InitializeNetAddr(PR_IpAddrAny, DEFAULT_PORT, &serverAddress); + else + rv = PR_SetNetAddr(PR_IpAddrAny, PR_AF_INET6, DEFAULT_PORT, + &serverAddress); rv = PR_Bind(server->listener, &serverAddress); TEST_ASSERT(PR_SUCCESS == rv); @@ -888,9 +891,7 @@ static void Help(void) PR_fprintf(debug_out, "\t-s <string> dsn name of server (localhost)\n"); PR_fprintf(debug_out, "\t-G use GLOBAL threads (LOCAL)\n"); PR_fprintf(debug_out, "\t-X use XTP as transport (TCP)\n"); -#ifdef _PR_INET6 PR_fprintf(debug_out, "\t-6 Use IPv6 (IPv4)\n"); -#endif /* _PR_INET6 */ PR_fprintf(debug_out, "\t-v verbosity (accumulative) (0)\n"); PR_fprintf(debug_out, "\t-p pthread statistics (FALSE)\n"); PR_fprintf(debug_out, "\t-d debug mode (FALSE)\n"); @@ -951,12 +952,9 @@ PRIntn main(PRIntn argc, char** argv) case 'X': /* use XTP as transport */ protocol = 36; break; -#ifdef _PR_INET6 - case '6': /* Use IPv6 */ - domain = AF_INET6; - PR_SetIPv6Enable(PR_TRUE); + case '6': /* Use IPv6 */ + domain = PR_AF_INET6; break; -#endif /* _PR_INET6 */ case 'a': /* the value for accepting */ accepting = atoi(opt->value); break; @@ -1097,9 +1095,13 @@ PRIntn main(PRIntn argc, char** argv) client[index].ml = PR_NewLock(); if (serverIsLocal) { - (void)PR_InitializeNetAddr( - PR_IpAddrLoopback, DEFAULT_PORT, - &client[index].serverAddress); + if (PR_AF_INET6 != domain) + (void)PR_InitializeNetAddr( + PR_IpAddrLoopback, DEFAULT_PORT, + &client[index].serverAddress); + else + rv = PR_SetNetAddr(PR_IpAddrLoopback, PR_AF_INET6, + DEFAULT_PORT, &client[index].serverAddress); } else { diff --git a/pr/tests/gethost.c b/pr/tests/gethost.c index 9b13b9c7..7a611981 100644 --- a/pr/tests/gethost.c +++ b/pr/tests/gethost.c @@ -35,8 +35,7 @@ static void Help(void) { - fprintf(stderr, "Usage: gethost [-6h] [hostname]\n"); - fprintf(stderr, "\t-6 IPv6 mode (default: FALSE)\n"); + fprintf(stderr, "Usage: gethost [-h] [hostname]\n"); fprintf(stderr, "\t-h help\n"); fprintf(stderr, "\thostname Name of host (default: %s)\n", DEFAULT_HOST_NAME); @@ -75,17 +74,11 @@ int main(int argc, char **argv) PRIntn idx; PRNetAddr addr; PLOptStatus os; - PLOptState *opt = PL_CreateOptState(argc, argv, "6h"); + PLOptState *opt = PL_CreateOptState(argc, argv, "h"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { - case '6': /* Enable IPv6 */ - if (PR_SetIPv6Enable(PR_TRUE) == PR_FAILURE) { - fprintf(stderr, "PR_SetIPv6Enable failed\n"); - exit(1); - } - break; case 0: /* naked */ hostName = opt->value; break; @@ -126,7 +119,6 @@ int main(int argc, char **argv) exit(1); } PrintHostent(&he); -#ifdef _PR_INET6 printf("PR_GetIPNodeByName with PR_AF_INET6\n"); if (PR_GetIPNodeByName(hostName, PR_AF_INET6, PR_AI_DEFAULT, buf, sizeof(buf), &he) == PR_FAILURE) { @@ -134,10 +126,49 @@ int main(int argc, char **argv) exit(1); } PrintHostent(&he); -#endif - + idx = 0; + printf("PR_GetHostByAddr with PR_AF_INET6\n"); + while (1) { + idx = PR_EnumerateHostEnt(idx, &he, 0, &addr); + if (idx == -1) { + fprintf(stderr, "PR_EnumerateHostEnt failed\n"); + exit(1); + } + if (idx == 0) break; /* normal loop termination */ + printf("reverse lookup\n"); + if (PR_GetHostByAddr(&addr, reversebuf, sizeof(reversebuf), + &reversehe) == PR_FAILURE) { + fprintf(stderr, "PR_GetHostByAddr failed\n"); + exit(1); + } + PrintHostent(&reversehe); + } + printf("PR_GetHostByAddr with PR_AF_INET6 done\n"); + PR_StringToNetAddr("::1", &addr); + if (PR_IsNetAddrType(&addr, PR_IpAddrV4Mapped) == PR_TRUE) { + fprintf(stderr, "addr should not be ipv4 mapped address\n"); + exit(1); + } + if (PR_IsNetAddrType(&addr, PR_IpAddrLoopback) == PR_FALSE) { + fprintf(stderr, "addr should be loopback address\n"); + exit(1); + } + PR_StringToNetAddr("127.0.0.1", &addr); + if (PR_IsNetAddrType(&addr, PR_IpAddrLoopback) == PR_FALSE) { + fprintf(stderr, "addr should be loopback address\n"); + exit(1); + } + PR_StringToNetAddr("::FFFF:127.0.0.1", &addr); + if (PR_IsNetAddrType(&addr, PR_IpAddrV4Mapped) == PR_FALSE) { + fprintf(stderr, "addr should be ipv4 mapped address\n"); + exit(1); + } + if (PR_IsNetAddrType(&addr, PR_IpAddrLoopback) == PR_FALSE) { + fprintf(stderr, "addr should be loopback address\n"); + exit(1); + } if (PR_InitializeNetAddr(PR_IpAddrAny, 0, &addr) == PR_FAILURE) { fprintf(stderr, "PR_InitializeNetAddr failed\n"); @@ -180,6 +211,11 @@ int main(int argc, char **argv) fprintf(stderr, "addr should be unspecified address\n"); exit(1); } + { + char buf[256]; + PR_NetAddrToString(&addr, buf, 256); + printf("IPv4 INADDRANY: %s\n", buf); + } addr.inet.family = PR_AF_INET; addr.inet.port = 0; addr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK); @@ -187,8 +223,12 @@ int main(int argc, char **argv) fprintf(stderr, "addr should be loopback address\n"); exit(1); } + { + char buf[256]; + PR_NetAddrToString(&addr, buf, 256); + printf("IPv4 LOOPBACK: %s\n", buf); + } -#if defined(_PR_INET6) if (PR_SetNetAddr(PR_IpAddrAny, PR_AF_INET6, 0, &addr) == PR_FAILURE) { fprintf(stderr, "PR_SetNetAddr failed\n"); exit(1); @@ -197,6 +237,11 @@ int main(int argc, char **argv) fprintf(stderr, "addr should be unspecified address\n"); exit(1); } + { + char buf[256]; + PR_NetAddrToString(&addr, buf, 256); + printf("IPv6 INADDRANY: %s\n", buf); + } if (PR_SetNetAddr(PR_IpAddrLoopback, PR_AF_INET6, 0, &addr) == PR_FAILURE) { fprintf(stderr, "PR_SetNetAddr failed\n"); exit(1); @@ -205,23 +250,23 @@ int main(int argc, char **argv) fprintf(stderr, "addr should be loopback address\n"); exit(1); } + { + char buf[256]; + PR_NetAddrToString(&addr, buf, 256); + printf("IPv6 LOOPBACK: %s\n", buf); + } + { + PRIPv6Addr v6addr; + char tmp_buf[256]; - addr.ipv6.family = PR_AF_INET6; - addr.ipv6.port = 0; - addr.ipv6.ip = in6addr_any; - if (PR_IsNetAddrType(&addr, PR_IpAddrAny) == PR_FALSE) { - fprintf(stderr, "addr should be unspecified address\n"); - exit(1); - } - addr.ipv6.family = PR_AF_INET6; - addr.ipv6.port = 0; - addr.ipv6.ip = in6addr_loopback; - if (PR_IsNetAddrType(&addr, PR_IpAddrLoopback) == PR_FALSE) { - fprintf(stderr, "addr should be loopback address\n"); - exit(1); - } -#endif /* _PR_INET6 */ + PR_SetNetAddr(PR_IpAddrLoopback, PR_AF_INET, 0, &addr); + PR_ConvertIPv4AddrToIPv6(addr.inet.ip, &v6addr); + PR_SetNetAddr(PR_IpAddrAny, PR_AF_INET6, 0, &addr); + addr.ipv6.ip = v6addr; + PR_NetAddrToString(&addr, tmp_buf, 256); + printf("IPv4-mapped IPv6 LOOPBACK: %s\n", tmp_buf); + } printf("PASS\n"); return 0; } diff --git a/pr/tests/ipv6.c b/pr/tests/ipv6.c index 7e92f3e2..4029fedd 100644 --- a/pr/tests/ipv6.c +++ b/pr/tests/ipv6.c @@ -49,10 +49,9 @@ static PRFileDesc *err = NULL; static void Help(void) { - PR_fprintf(err, "Usage: [-V] [-6] [-h]\n"); + PR_fprintf(err, "Usage: [-V] [-h]\n"); PR_fprintf(err, "\t<nul> Name of host to lookup (default: self)\n"); PR_fprintf(err, "\t-V Display runtime version info (default: FALSE)\n"); - PR_fprintf(err, "\t-6 First turn on IPv6 capability (default: FALSE)\n"); PR_fprintf(err, "\t-h This message and nothing else\n"); } /* Help */ @@ -106,7 +105,7 @@ PRIntn main(PRIntn argc, char **argv) PRBool ipv6 = PR_FALSE; const char *name = NULL; PRBool failed = PR_FALSE, version = PR_FALSE; - PLOptState *opt = PL_CreateOptState(argc, argv, "Vh6"); + PLOptState *opt = PL_CreateOptState(argc, argv, "Vh"); err = PR_GetSpecialFD(PR_StandardError); @@ -118,9 +117,6 @@ PRIntn main(PRIntn argc, char **argv) case 0: /* Name of host to lookup */ name = opt->value; break; - case '6': /* Turn on IPv6 mode */ - ipv6 = PR_TRUE; - break; case 'V': /* Do version discovery */ version = PR_TRUE; break; @@ -184,16 +180,6 @@ PRIntn main(PRIntn argc, char **argv) if (NULL != nspr_name) PR_FreeLibraryName(nspr_name); } - if (ipv6) - { - rv = PR_SetIPv6Enable(ipv6); - if (PR_FAILURE == rv) - { - failed = PR_TRUE; - PL_FPrintError(err, "PR_SetIPv6Enable"); - } - } - { if (NULL == name) { @@ -202,7 +188,7 @@ PRIntn main(PRIntn argc, char **argv) if (PR_FAILURE == rv) { failed = PR_TRUE; - PL_FPrintError(err, "PR_GetHostName"); + PL_FPrintError(err, "PR_GetSystemInfo"); return 2; } name = me; /* just leak the storage */ diff --git a/pr/tests/lltest.c b/pr/tests/lltest.c index 64e8c3ca..ce0abd89 100644 --- a/pr/tests/lltest.c +++ b/pr/tests/lltest.c @@ -80,6 +80,18 @@ const PRUint64 bigFoxFox = LL_INIT( 0xffffffff, 0xffffffff ); const PRUint64 bigFoxZero = LL_INIT( 0xffffffff, 0x00000000 ); const PRUint64 bigEightZero = LL_INIT( 0x80000000, 0x00000000 ); const PRUint64 big64K = LL_INIT( 0x00000000, 0x00010000 ); +const PRInt64 bigInt0 = LL_INIT( 0x01a00000, 0x00001000 ); +const PRInt64 bigInt1 = LL_INIT( 0x01a00000, 0x00001100 ); +const PRInt64 bigInt2 = LL_INIT( 0x01a00000, 0x00000100 ); +const PRInt64 bigInt3 = LL_INIT( 0x01a00001, 0x00001000 ); +const PRInt64 bigInt4 = LL_INIT( 0x01a00001, 0x00001100 ); +const PRInt64 bigInt5 = LL_INIT( 0x01a00001, 0x00000100 ); +const PRInt64 bigInt6 = LL_INIT( 0xb1a00000, 0x00001000 ); +const PRInt64 bigInt7 = LL_INIT( 0xb1a00000, 0x00001100 ); +const PRInt64 bigInt8 = LL_INIT( 0xb1a00000, 0x00000100 ); +const PRInt64 bigInt9 = LL_INIT( 0xb1a00001, 0x00001000 ); +const PRInt64 bigInt10 = LL_INIT( 0xb1a00001, 0x00001100 ); +const PRInt64 bigInt11 = LL_INIT( 0xb1a00001, 0x00000100 ); const PRInt32 one = 1l; const PRInt32 minusOne = -1l; const PRInt32 sixteen = 16l; @@ -236,7 +248,55 @@ TestComparisons( void ) if ( !LL_CMP( bigMaxInt32, <, big2To31 )) SetFailed( "LL_CMP", "Max 32-bit signed int >= 2^31"); - + + /* Two positive numbers */ + if ( !LL_CMP( bigInt0, <=, bigInt0 )) + SetFailed( "LL_CMP", "LL_CMP(<=) failed"); + + if ( !LL_CMP( bigInt0, <=, bigInt1 )) + SetFailed( "LL_CMP", "LL_CMP(<=) failed"); + + if ( LL_CMP( bigInt0, <=, bigInt2 )) + SetFailed( "LL_CMP", "LL_CMP(<=) failed"); + + if ( !LL_CMP( bigInt0, <=, bigInt3 )) + SetFailed( "LL_CMP", "LL_CMP(<=) failed"); + + if ( !LL_CMP( bigInt0, <=, bigInt4 )) + SetFailed( "LL_CMP", "LL_CMP(<=) failed"); + + if ( !LL_CMP( bigInt0, <=, bigInt5 )) + SetFailed( "LL_CMP", "LL_CMP(<=) failed"); + + /* Two negative numbers */ + if ( !LL_CMP( bigInt6, <=, bigInt6 )) + SetFailed( "LL_CMP", "LL_CMP(<=) failed"); + + if ( !LL_CMP( bigInt6, <=, bigInt7 )) + SetFailed( "LL_CMP", "LL_CMP(<=) failed"); + + if ( LL_CMP( bigInt6, <=, bigInt8 )) + SetFailed( "LL_CMP", "LL_CMP(<=) failed"); + + if ( !LL_CMP( bigInt6, <=, bigInt9 )) + SetFailed( "LL_CMP", "LL_CMP(<=) failed"); + + if ( !LL_CMP( bigInt6, <=, bigInt10 )) + SetFailed( "LL_CMP", "LL_CMP(<=) failed"); + + if ( !LL_CMP( bigInt6, <=, bigInt11 )) + SetFailed( "LL_CMP", "LL_CMP(<=) failed"); + + /* One positive, one negative */ + if ( LL_CMP( bigInt0, <=, bigInt6 )) + SetFailed( "LL_CMP", "LL_CMP(<=) failed"); + + if ( LL_CMP( bigInt0, <=, bigInt7 )) + SetFailed( "LL_CMP", "LL_CMP(<=) failed"); + + if ( LL_CMP( bigInt0, <=, bigInt8 )) + SetFailed( "LL_CMP", "LL_CMP(<=) failed"); + /* Bitwise Compare two numbers */ if ( !LL_UCMP( bigZero, ==, bigZero )) SetFailed( "LL_UCMP", "0 == 0"); @@ -258,7 +318,55 @@ TestComparisons( void ) if ( LL_UCMP( bigMinusNumber, <, bigNumber )) SetFailed( "LL_UCMP", "-n < n"); - + + /* Two positive numbers */ + if ( !LL_UCMP( bigInt0, <=, bigInt0 )) + SetFailed( "LL_UCMP", "LL_UCMP(<=) failed"); + + if ( !LL_UCMP( bigInt0, <=, bigInt1 )) + SetFailed( "LL_UCMP", "LL_UCMP(<=) failed"); + + if ( LL_UCMP( bigInt0, <=, bigInt2 )) + SetFailed( "LL_UCMP", "LL_UCMP(<=) failed"); + + if ( !LL_UCMP( bigInt0, <=, bigInt3 )) + SetFailed( "LL_UCMP", "LL_UCMP(<=) failed"); + + if ( !LL_UCMP( bigInt0, <=, bigInt4 )) + SetFailed( "LL_UCMP", "LL_UCMP(<=) failed"); + + if ( !LL_UCMP( bigInt0, <=, bigInt5 )) + SetFailed( "LL_UCMP", "LL_UCMP(<=) failed"); + + /* Two negative numbers */ + if ( !LL_UCMP( bigInt6, <=, bigInt6 )) + SetFailed( "LL_UCMP", "LL_UCMP(<=) failed"); + + if ( !LL_UCMP( bigInt6, <=, bigInt7 )) + SetFailed( "LL_UCMP", "LL_UCMP(<=) failed"); + + if ( LL_UCMP( bigInt6, <=, bigInt8 )) + SetFailed( "LL_UCMP", "LL_UCMP(<=) failed"); + + if ( !LL_UCMP( bigInt6, <=, bigInt9 )) + SetFailed( "LL_UCMP", "LL_UCMP(<=) failed"); + + if ( !LL_UCMP( bigInt6, <=, bigInt10 )) + SetFailed( "LL_UCMP", "LL_UCMP(<=) failed"); + + if ( !LL_UCMP( bigInt6, <=, bigInt11 )) + SetFailed( "LL_UCMP", "LL_UCMP(<=) failed"); + + /* One positive, one negative */ + if ( !LL_UCMP( bigInt0, <=, bigInt6 )) + SetFailed( "LL_UCMP", "LL_UCMP(<=) failed"); + + if ( !LL_UCMP( bigInt0, <=, bigInt7 )) + SetFailed( "LL_UCMP", "LL_UCMP(<=) failed"); + + if ( !LL_UCMP( bigInt0, <=, bigInt8 )) + SetFailed( "LL_UCMP", "LL_UCMP(<=) failed"); + return; } diff --git a/pr/tests/makedir.c b/pr/tests/makedir.c new file mode 100644 index 00000000..800d5b41 --- /dev/null +++ b/pr/tests/makedir.c @@ -0,0 +1,80 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 2000 Netscape Communications Corporation. All Rights + * Reserved. + */ + +/* + * This test calls PR_MakeDir to create a bunch of directories + * with various mode bits. + */ + +#include "prio.h" + +#include <stdio.h> +#include <stdlib.h> + +int main() +{ + if (PR_MakeDir("tdir0400", 0400) == PR_FAILURE) { + fprintf(stderr, "PR_MakeDir failed\n"); + exit(1); + } + if (PR_MakeDir("tdir0200", 0200) == PR_FAILURE) { + fprintf(stderr, "PR_MakeDir failed\n"); + exit(1); + } + if (PR_MakeDir("tdir0100", 0100) == PR_FAILURE) { + fprintf(stderr, "PR_MakeDir failed\n"); + exit(1); + } + if (PR_MakeDir("tdir0500", 0500) == PR_FAILURE) { + fprintf(stderr, "PR_MakeDir failed\n"); + exit(1); + } + if (PR_MakeDir("tdir0600", 0600) == PR_FAILURE) { + fprintf(stderr, "PR_MakeDir failed\n"); + exit(1); + } + if (PR_MakeDir("tdir0300", 0300) == PR_FAILURE) { + fprintf(stderr, "PR_MakeDir failed\n"); + exit(1); + } + if (PR_MakeDir("tdir0700", 0700) == PR_FAILURE) { + fprintf(stderr, "PR_MakeDir failed\n"); + exit(1); + } + if (PR_MakeDir("tdir0640", 0640) == PR_FAILURE) { + fprintf(stderr, "PR_MakeDir failed\n"); + exit(1); + } + if (PR_MakeDir("tdir0660", 0660) == PR_FAILURE) { + fprintf(stderr, "PR_MakeDir failed\n"); + exit(1); + } + if (PR_MakeDir("tdir0644", 0644) == PR_FAILURE) { + fprintf(stderr, "PR_MakeDir failed\n"); + exit(1); + } + if (PR_MakeDir("tdir0664", 0664) == PR_FAILURE) { + fprintf(stderr, "PR_MakeDir failed\n"); + exit(1); + } + if (PR_MakeDir("tdir0666", 0666) == PR_FAILURE) { + fprintf(stderr, "PR_MakeDir failed\n"); + exit(1); + } + return 0; +} diff --git a/pr/tests/mbcs.c b/pr/tests/mbcs.c new file mode 100644 index 00000000..ffd0974b --- /dev/null +++ b/pr/tests/mbcs.c @@ -0,0 +1,168 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ + +/* +** File: mbcs.c +** +** Synopsis: mbcs {dirName} +** +** where dirName is the directory to be traversed. dirName is required. +** +** Description: +** mbcs.c tests use of multi-byte characters, as would be passed to +** NSPR funtions by internationalized applications. +** +** mbcs.c, when run on any single-byte platform, should run correctly. +** In truth, running the mbcs test on a single-byte platform is +** really meaningless. mbcs.c, nor any NSPR library or test is not +** intended for use with any wide character set, including Unicode. +** mbcs.c should not be included in runtests.ksh because it requires +** extensive user intervention to set-up and run. +** +** mbcs.c should be run on a platform using some form of multi-byte +** characters. The initial platform for this test is a Japanese +** language Windows NT 4.0 machine. ... Thank you Noriko Hoshi. +** +** To run mbcs.c, the tester should create a directory tree containing +** some files in the same directory from which the test is run; i.e. +** the current working directory. The directory and files should be +** named such that when represented in the local multi-byte character +** set, one or more characters of the name is longer than a single +** byte. +** +*/ + +#include <plgetopt.h> +#include <nspr.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* +** Test harness infrastructure +*/ +PRLogModuleInfo *lm; +PRLogModuleLevel msgLevel = PR_LOG_NONE; +PRIntn debug = 0; +PRUint32 failed_already = 0; +/* end Test harness infrastructure */ + +char *dirName = NULL; /* directory name to traverse */ + +/* +** Traverse directory +*/ +static void TraverseDirectory( unsigned char *dir ) +{ + PRDir *cwd; + PRDirEntry *dirEntry; + PRFileInfo info; + PRStatus rc; + PRInt32 err; + PRFileDesc *fd; + char nextDir[256]; + char file[256]; + + printf("Directory: %s\n", dir ); + cwd = PR_OpenDir( dir ); + if ( NULL == cwd ) { + printf("PR_OpenDir() failed on directory: %s, with error: %d, %d\n", + dir, PR_GetError(), PR_GetOSError()); + exit(1); + } + while( NULL != (dirEntry = PR_ReadDir( cwd, PR_SKIP_BOTH | PR_SKIP_HIDDEN ))) { + sprintf( file, "%s/%s", dir, dirEntry->name ); + rc = PR_GetFileInfo( file, &info ); + if ( PR_FAILURE == rc ) { + printf("PR_GetFileInfo() failed on file: %s, with error: %d, %d\n", + dirEntry->name, PR_GetError(), PR_GetOSError()); + exit(1); + } + if ( PR_FILE_FILE == info.type ) { + printf("File: %s \tsize: %ld\n", dirEntry->name, info.size ); + fd = PR_Open( file, PR_RDONLY, 0 ); + if ( NULL == fd ) { + printf("PR_Open() failed. Error: %ld, OSError: %ld\n", + PR_GetError(), PR_GetOSError()); + } + rc = PR_Close( fd ); + if ( PR_FAILURE == rc ) { + printf("PR_Close() failed. Error: %ld, OSError: %ld\n", + PR_GetError(), PR_GetOSError()); + } + } else if ( PR_FILE_DIRECTORY == info.type ) { + sprintf( nextDir, "%s/%s", dir, dirEntry->name ); + TraverseDirectory(nextDir); + } else { + printf("type is not interesting for file: %s\n", dirEntry->name ); + /* keep going */ + } + } + /* assume end-of-file, actually could be error */ + + rc = PR_CloseDir( cwd ); + if ( PR_FAILURE == rc ) { + printf("PR_CloseDir() failed on directory: %s, with error: %d, %d\n", + dir, PR_GetError(), PR_GetOSError()); + } + +} /* end TraverseDirectory() */ + +PRIntn main(PRIntn argc, char *argv[]) +{ + { /* get command line options */ + /* + ** Get command line options + */ + PLOptStatus os; + PLOptState *opt = PL_CreateOptState(argc, argv, "dv"); + + while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) + { + if (PL_OPT_BAD == os) continue; + switch (opt->option) + { + case 'd': /* debug */ + debug = 1; + msgLevel = PR_LOG_ERROR; + break; + case 'v': /* verbose mode */ + msgLevel = PR_LOG_DEBUG; + break; + default: + dirName = strdup(opt->value); + break; + } + } + PL_DestroyOptState(opt); + } /* end get command line options */ + + lm = PR_NewLogModule("Test"); /* Initialize logging */ + + + if ( dirName == NULL ) { + printf("you gotta specify a directory as an operand!\n"); + exit(1); + } + + TraverseDirectory( dirName ); + + if (debug) printf("%s\n", (failed_already)? "FAIL" : "PASS"); + return( (failed_already == PR_TRUE )? 1 : 0 ); +} /* main() */ +/* end template.c */ diff --git a/pr/tests/nonblock.c b/pr/tests/nonblock.c index 04475526..223b7a7e 100644 --- a/pr/tests/nonblock.c +++ b/pr/tests/nonblock.c @@ -70,7 +70,7 @@ clientThreadFunc(void *arg) char buf[CHUNK_SIZE]; int i; PRIntervalTime unitTime = PR_MillisecondsToInterval(UNIT_TIME); - PRIntn optval = 1; + PRSocketOptionData optval; PRStatus retVal; PRInt32 nBytes; @@ -85,7 +85,9 @@ clientThreadFunc(void *arg) /* time 1 */ PR_Sleep(unitTime); sock = PR_NewTCPSocket(); - PR_SetSockOpt(sock, PR_SockOpt_Nonblocking, &optval, sizeof(optval)); + optval.option = PR_SockOpt_Nonblocking; + optval.value.non_blocking = PR_TRUE; + PR_SetSocketOption(sock, &optval); retVal = PR_Connect(sock, &addr, PR_INTERVAL_NO_TIMEOUT); if (retVal == PR_FAILURE && PR_GetError() == PR_IN_PROGRESS_ERROR) { #if !defined(USE_PR_SELECT) @@ -138,7 +140,7 @@ static PRIntn PR_CALLBACK RealMain( PRIntn argc, char **argv ) char buf[CHUNK_SIZE]; PRThread *clientThread; PRInt32 retVal; - PRIntn optval = 1; + PRSocketOptionData optval; PRIntn i; PRIntervalTime unitTime = PR_MillisecondsToInterval(UNIT_TIME); @@ -184,8 +186,9 @@ static PRIntn PR_CALLBACK RealMain( PRIntn argc, char **argv ) printf("client thread created.\n"); - PR_SetSockOpt(listenSock, PR_SockOpt_Nonblocking, &optval, - sizeof(PRIntn)); + optval.option = PR_SockOpt_Nonblocking; + optval.value.non_blocking = PR_TRUE; + PR_SetSocketOption(listenSock, &optval); /* time 0 */ sock = PR_Accept(listenSock, NULL, PR_INTERVAL_NO_TIMEOUT); if (sock != NULL || PR_GetError() != PR_WOULD_BLOCK_ERROR) { @@ -208,7 +211,7 @@ static PRIntn PR_CALLBACK RealMain( PRIntn argc, char **argv ) fflush(stdout); PR_Close(listenSock); - PR_SetSockOpt(sock, PR_SockOpt_Nonblocking, &optval, sizeof(PRIntn)); + PR_SetSocketOption(sock, &optval); /* time 3, 5, 6, 8, etc. */ for (i = 0; i < NUMBER_ROUNDS; i++) { diff --git a/pr/tests/ntioto.c b/pr/tests/ntioto.c index e5c9ecea..7549a436 100644 --- a/pr/tests/ntioto.c +++ b/pr/tests/ntioto.c @@ -56,6 +56,7 @@ #include <nspr.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> /* ** Test harness infrastructure @@ -95,10 +96,17 @@ static void Help( void ) exit(1); } /* end Help() */ + +/* +** static computation of PR_AcceptRead() buffer size. +*/ +#define ACCEPT_READ_DATASIZE 10 +#define ACCEPT_READ_BUFSIZE (PR_ACCEPT_READ_BUF_OVERHEAD + ACCEPT_READ_DATASIZE) + static void AcceptThread(void *arg) { PRIntn bytesRead; - char dataBuf[100]; + char dataBuf[ACCEPT_READ_BUFSIZE]; PRFileDesc *arSock; PRNetAddr *arAddr; @@ -106,7 +114,7 @@ static void AcceptThread(void *arg) &arSock, &arAddr, dataBuf, - 10, + ACCEPT_READ_DATASIZE, PR_SecondsToInterval(1)); if ( bytesRead == -1 && PR_GetError() == PR_IO_TIMEOUT_ERROR ) diff --git a/pr/tests/ntoh.c b/pr/tests/ntoh.c new file mode 100644 index 00000000..006f5b92 --- /dev/null +++ b/pr/tests/ntoh.c @@ -0,0 +1,106 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 2000 Netscape Communications Corporation. All Rights + * Reserved. + */ + +/* + * A test program for PR_htons, PR_ntohs, PR_htonl, PR_ntohl, + * PR_htonll, and PR_ntohll. + */ + +#include "prnetdb.h" + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +/* Byte sequence in network byte order */ +static unsigned char bytes_n[8] = { 1, 2, 3, 4, 5, 6, 7, 8 }; + +/* Integers in host byte order */ +static PRUint16 s_h = 0x0102; +static PRUint32 l_h = 0x01020304; +static PRUint64 ll_h = LL_INIT(0x01020304, 0x05060708); + +int main() +{ + union { + PRUint16 s; + PRUint32 l; + PRUint64 ll; + unsigned char bytes[8]; + } un; + + un.s = s_h; + printf("%u %u\n", + un.bytes[0], un.bytes[1]); + un.s = PR_htons(un.s); + printf("%u %u\n", + un.bytes[0], un.bytes[1]); + if (memcmp(un.bytes, bytes_n, 2)) { + fprintf(stderr, "PR_htons failed\n"); + exit(1); + } + un.s = PR_ntohs(un.s); + printf("%u %u\n", + un.bytes[0], un.bytes[1]); + if (un.s != s_h) { + fprintf(stderr, "PR_ntohs failed\n"); + exit(1); + } + + un.l = l_h; + printf("%u %u %u %u\n", + un.bytes[0], un.bytes[1], un.bytes[2], un.bytes[3]); + un.l = PR_htonl(un.l); + printf("%u %u %u %u\n", + un.bytes[0], un.bytes[1], un.bytes[2], un.bytes[3]); + if (memcmp(un.bytes, bytes_n, 4)) { + fprintf(stderr, "PR_htonl failed\n"); + exit(1); + } + un.l = PR_ntohl(un.l); + printf("%u %u %u %u\n", + un.bytes[0], un.bytes[1], un.bytes[2], un.bytes[3]); + if (un.l != l_h) { + fprintf(stderr, "PR_ntohl failed\n"); + exit(1); + } + + un.ll = ll_h; + printf("%u %u %u %u %u %u %u %u\n", + un.bytes[0], un.bytes[1], un.bytes[2], un.bytes[3], + un.bytes[4], un.bytes[5], un.bytes[6], un.bytes[7]); + un.ll = PR_htonll(un.ll); + printf("%u %u %u %u %u %u %u %u\n", + un.bytes[0], un.bytes[1], un.bytes[2], un.bytes[3], + un.bytes[4], un.bytes[5], un.bytes[6], un.bytes[7]); + if (memcmp(un.bytes, bytes_n, 8)) { + fprintf(stderr, "PR_htonll failed\n"); + exit(1); + } + un.ll = PR_ntohll(un.ll); + printf("%u %u %u %u %u %u %u %u\n", + un.bytes[0], un.bytes[1], un.bytes[2], un.bytes[3], + un.bytes[4], un.bytes[5], un.bytes[6], un.bytes[7]); + if (LL_NE(un.ll, ll_h)) { + fprintf(stderr, "PR_ntohll failed\n"); + exit(1); + } + + printf("PASS\n"); + return 0; +} diff --git a/pr/tests/op_excl.c b/pr/tests/op_excl.c index bfbd33d3..748552a4 100644 --- a/pr/tests/op_excl.c +++ b/pr/tests/op_excl.c @@ -118,7 +118,7 @@ PRIntn main(PRIntn argc, char *argv[]) */ fd = PR_Open( NEW_FILENAME, PR_CREATE_FILE | PR_EXCL | PR_WRONLY, 0666 ); if ( NULL != fd ) { - if (debug) fprintf( stderr, "Open exclusive. Expected failure, got success"); + if (debug) fprintf( stderr, "Open exclusive. Expected failure, got success\n"); failed_already = 1; PR_Close(fd); } diff --git a/pr/tests/openfile.c b/pr/tests/openfile.c new file mode 100644 index 00000000..11992c5e --- /dev/null +++ b/pr/tests/openfile.c @@ -0,0 +1,126 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 2000 Netscape Communications Corporation. All Rights + * Reserved. + */ + +/* + * This test calls PR_OpenFile to create a bunch of files + * with various file modes. + */ + +#include "prio.h" +#include "prerror.h" +#include "prinit.h" + +#include <stdio.h> +#include <stdlib.h> + +#define TEMPLATE_FILE_NAME "template.txt" + +int main() +{ + FILE *template; + char buf[32]; + PRInt32 nbytes; + PRFileDesc *fd; + + + /* Write in text mode. Let stdio deal with line endings. */ + template = fopen(TEMPLATE_FILE_NAME, "w"); + fputs("line 1\nline 2\n", template); + fclose(template); + + /* Read in binary mode */ + fd = PR_OpenFile(TEMPLATE_FILE_NAME, PR_RDONLY, 0666); + nbytes = PR_Read(fd, buf, sizeof(buf)); + PR_Close(fd); + PR_Delete(TEMPLATE_FILE_NAME); + + fd = PR_OpenFile("tfil0700.txt", PR_RDWR | PR_CREATE_FILE, 0700); + if (NULL == fd) { + fprintf(stderr, "PR_OpenFile failed (%d, %d)\n", + PR_GetError(), PR_GetOSError()); + exit(1); + } + PR_Write(fd, buf, nbytes); + PR_Close(fd); + + fd = PR_OpenFile("tfil0500.txt", PR_RDWR | PR_CREATE_FILE, 0500); + if (NULL == fd) { + fprintf(stderr, "PR_OpenFile failed (%d, %d)\n", + PR_GetError(), PR_GetOSError()); + exit(1); + } + PR_Write(fd, buf, nbytes); + PR_Close(fd); + + fd = PR_OpenFile("tfil0400.txt", PR_RDWR | PR_CREATE_FILE, 0400); + if (NULL == fd) { + fprintf(stderr, "PR_OpenFile failed (%d, %d)\n", + PR_GetError(), PR_GetOSError()); + exit(1); + } + PR_Write(fd, buf, nbytes); + PR_Close(fd); + + fd = PR_OpenFile("tfil0644.txt", PR_RDWR | PR_CREATE_FILE, 0644); + if (NULL == fd) { + fprintf(stderr, "PR_OpenFile failed (%d, %d)\n", + PR_GetError(), PR_GetOSError()); + exit(1); + } + PR_Write(fd, buf, nbytes); + PR_Close(fd); + + fd = PR_OpenFile("tfil0664.txt", PR_RDWR | PR_CREATE_FILE, 0664); + if (NULL == fd) { + fprintf(stderr, "PR_OpenFile failed (%d, %d)\n", + PR_GetError(), PR_GetOSError()); + exit(1); + } + PR_Write(fd, buf, nbytes); + PR_Close(fd); + + fd = PR_OpenFile("tfil0660.txt", PR_RDWR | PR_CREATE_FILE, 0660); + if (NULL == fd) { + fprintf(stderr, "PR_OpenFile failed (%d, %d)\n", + PR_GetError(), PR_GetOSError()); + exit(1); + } + PR_Write(fd, buf, nbytes); + PR_Close(fd); + + fd = PR_OpenFile("tfil0666.txt", PR_RDWR | PR_CREATE_FILE, 0666); + if (NULL == fd) { + fprintf(stderr, "PR_OpenFile failed (%d, %d)\n", + PR_GetError(), PR_GetOSError()); + exit(1); + } + PR_Write(fd, buf, nbytes); + PR_Close(fd); + + fd = PR_OpenFile("tfil0640.txt", PR_RDWR | PR_CREATE_FILE, 0640); + if (NULL == fd) { + fprintf(stderr, "PR_OpenFile failed (%d, %d)\n", + PR_GetError(), PR_GetOSError()); + exit(1); + } + PR_Write(fd, buf, nbytes); + PR_Close(fd); + + PR_Cleanup(); + return 0; +} diff --git a/pr/tests/poll_nm.c b/pr/tests/poll_nm.c index 27937b62..65794e34 100644 --- a/pr/tests/poll_nm.c +++ b/pr/tests/poll_nm.c @@ -117,7 +117,7 @@ int main(int argc, char **argv) PRIntn npds; PRInt32 retVal; PRIntn i, j; - PRIntn optval = 1; + PRSocketOptionData optval; /* The command line argument: -d is used to determine if the test is being run in debug mode. The regress tool requires only one line output:PASS or FAIL. @@ -177,7 +177,9 @@ int main(int argc, char **argv) goto exit_now; } listenPort1 = PR_ntohs(addr.inet.port); - PR_SetSockOpt(listenSock1, PR_SockOpt_Nonblocking, &optval, sizeof(optval)); + optval.option = PR_SockOpt_Nonblocking; + optval.value.non_blocking = PR_TRUE; + PR_SetSocketOption(listenSock1, &optval); if (PR_Listen(listenSock1, 5) == PR_FAILURE) { fprintf(stderr, "Can't listen on a socket\n"); failed_already=1; @@ -203,7 +205,7 @@ int main(int argc, char **argv) goto exit_now; } listenPort2 = PR_ntohs(addr.inet.port); - PR_SetSockOpt(listenSock2, PR_SockOpt_Nonblocking, &optval, sizeof(optval)); + PR_SetSocketOption(listenSock2, &optval); if (PR_Listen(listenSock2, 5) == PR_FAILURE) { fprintf(stderr, "Can't listen on a socket\n"); failed_already=1; diff --git a/pr/tests/provider.c b/pr/tests/provider.c index b2a05283..bec8950a 100644 --- a/pr/tests/provider.c +++ b/pr/tests/provider.c @@ -1049,9 +1049,7 @@ static void Help(void) PR_fprintf(debug_out, "\t-G use GLOBAL threads (LOCAL)\n"); PR_fprintf(debug_out, "\t-T <string> thread provider ('n' | 'p' | 'w')(n)\n"); PR_fprintf(debug_out, "\t-X use XTP as transport (TCP)\n"); -#ifdef _PR_INET6 PR_fprintf(debug_out, "\t-6 Use IPv6 (IPv4)\n"); -#endif /* _PR_INET6 */ PR_fprintf(debug_out, "\t-v verbosity (accumulative) (0)\n"); PR_fprintf(debug_out, "\t-p pthread statistics (FALSE)\n"); PR_fprintf(debug_out, "\t-d debug mode (FALSE)\n"); @@ -1120,12 +1118,9 @@ PRIntn main(PRIntn argc, char** argv) case 'X': /* use XTP as transport */ protocol = 36; break; -#ifdef _PR_INET6 - case '6': /* Use IPv6 */ - domain = AF_INET6; - PR_SetIPv6Enable(PR_TRUE); + case '6': /* Use IPv6 */ + domain = PR_AF_INET6; break; -#endif /* _PR_INET6 */ case 'a': /* the value for accepting */ accepting = atoi(opt->value); break; diff --git a/pr/tests/runtests.ksh b/pr/tests/runtests.ksh index dc5ed319..2e102f52 100755 --- a/pr/tests/runtests.ksh +++ b/pr/tests/runtests.ksh @@ -35,11 +35,14 @@ fi # Irrevelant tests # #bug1test - used to demonstrate a bug on NT +#bigfile2 - requires 4Gig file creation. See BugZilla #5451 +#bigfile3 - requires 4Gig file creation. See BugZilla #5451 #dbmalloc - obsolete; originally for testing debug version of nspr's malloc #dbmalloc1 - obsolete; originally for testing debug version of nspr's malloc #depend - obsolete; used to test a initial spec for library dependencies #dceemu - used to tests special functions in NSPR for DCE emulation #ipv6 - IPV6 not in use by NSPR clients +#mbcs - tests use of multi-byte charset for filenames. See BugZilla #25140 #sproc_ch - obsolete; sproc-based tests for Irix #sproc_p - obsolete; sproc-based tests for Irix #io_timeoutk - obsolete; subsumed in io_timeout @@ -122,6 +125,7 @@ nameshm1 nblayer nonblock ntioto +ntoh op_2long op_excl op_filnf @@ -187,36 +191,75 @@ rval=0 # If TEST_TIMEOUT is not set or if it's value is 0, then test programs # don't timeout. # +# Running runtests.ksh under MKS toolkit on NT, 95, 98 does not cause +# timeout detection correctly. For these platforms, do not attempt timeout +# test. (lth). +# +# +OS_PLATFORM=`uname` OBJDIR=`basename $PWD` echo "\nNSPR Test Results - $OBJDIR\n" echo "BEGIN\t\t\t`date`" echo "NSPR_TEST_LOGFILE\t${LOGFILE}\n" echo "Test\t\t\tResult\n" -for prog in $TESTS -do -echo "$prog\c" -echo "\nBEGIN TEST: $prog\n" >> ${LOGFILE} 2>&1 -export test_rval -./$prog >> ${LOGFILE} 2>&1 & -test_pid=$! -sleep_pid=0 -if [ "$TEST_TIMEOUT" -gt 0 ] -then -(sleep $TEST_TIMEOUT; kill $test_pid >/dev/null 2>&1 ) & -sleep_pid=$! -fi -wait $test_pid -test_rval=$? -[ sleep_pid -eq 0 ] || kill $sleep_pid >/dev/null 2>&1 -if [ 0 = $test_rval ] ; then - echo "\t\t\tPassed"; +if [ $OS_PLATFORM = "Windows_95" ] || [ $OS_PLATFORM = "Windows_98" ] || [ $OS_PLATFORM = "Windows_NT" ] ; then + for prog in $TESTS + do + echo "$prog\c" + echo "\nBEGIN TEST: $prog\n" >> ${LOGFILE} 2>&1 + ./$prog >> ${LOGFILE} 2>&1 + if [ 0 = $? ] ; then + echo "\t\t\tPassed"; + else + echo "\t\t\tFAILED"; + rval=1 + fi; + echo "\nEND TEST: $prog\n" >> ${LOGFILE} 2>&1 + done else - echo "\t\t\tFAILED"; - rval=1 + for prog in $TESTS + do + echo "$prog\c" + echo "\nBEGIN TEST: $prog\n" >> ${LOGFILE} 2>&1 + export test_rval + ./$prog >> ${LOGFILE} 2>&1 & + test_pid=$! + sleep_pid=0 + if [ "$TEST_TIMEOUT" -gt 0 ] + then + (sleep $TEST_TIMEOUT; kill $test_pid >/dev/null 2>&1 ) & + sleep_pid=$! + fi + wait $test_pid + test_rval=$? + [ sleep_pid -eq 0 ] || kill $sleep_pid >/dev/null 2>&1 + if [ 0 = $test_rval ] ; then + echo "\t\t\tPassed"; + else + echo "\t\t\tFAILED"; + rval=1 + fi; + echo "\nEND TEST: $prog\n" >> ${LOGFILE} 2>&1 + done fi; -echo "\nEND TEST: $prog\n" >> ${LOGFILE} 2>&1 -done -echo "END\t\t\t`date`" +echo "END\t\t\t`date`" exit $rval + + + + + + + + + + + + + + + + + diff --git a/pr/tests/semaping.c b/pr/tests/semaping.c index c5430aab..a00b9b42 100644 --- a/pr/tests/semaping.c +++ b/pr/tests/semaping.c @@ -85,7 +85,8 @@ int main(int argc, char **argv) shm = PR_OpenSharedMemory(SHM_NAME, sizeof(*counter_addr), PR_SHM_CREATE, SHM_MODE); if (NULL == shm) { - fprintf(stderr, "PR_OpenSharedMemory failed\n"); + fprintf(stderr, "PR_OpenSharedMemory failed (%d, %d)\n", + PR_GetError(), PR_GetOSError()); exit(1); } counter_addr = PR_AttachSharedMemory(shm, 0); @@ -102,7 +103,8 @@ int main(int argc, char **argv) } sem2 = PR_OpenSemaphore(SEM_NAME2, PR_SEM_CREATE, SEM_MODE, 0); if (NULL == sem2) { - fprintf(stderr, "PR_OpenSemaphore failed\n"); + fprintf(stderr, "PR_OpenSemaphore failed (%d, %d)\n", + PR_GetError(), PR_GetOSError()); exit(1); } diff --git a/pr/tests/semapong.c b/pr/tests/semapong.c index 932a7985..a91aa27b 100644 --- a/pr/tests/semapong.c +++ b/pr/tests/semapong.c @@ -65,7 +65,8 @@ int main(int argc, char **argv) shm = PR_OpenSharedMemory(SHM_NAME, sizeof(*counter_addr), 0, 0666); if (NULL == shm) { - fprintf(stderr, "PR_OpenSharedMemory failed\n"); + fprintf(stderr, "PR_OpenSharedMemory failed (%d, %d)\n", + PR_GetError(), PR_GetOSError()); exit(1); } sem1 = PR_OpenSemaphore(SEM_NAME1, 0, 0, 0); @@ -76,7 +77,8 @@ int main(int argc, char **argv) } sem2 = PR_OpenSemaphore(SEM_NAME2, 0, 0, 0); if (NULL == sem2) { - fprintf(stderr, "PR_OpenSemaphore failed\n"); + fprintf(stderr, "PR_OpenSemaphore failed (%d, %d)\n", + PR_GetError(), PR_GetOSError()); exit(1); } diff --git a/pr/tests/server_test.c b/pr/tests/server_test.c index 10e70bac..6553f439 100644 --- a/pr/tests/server_test.c +++ b/pr/tests/server_test.c @@ -160,8 +160,8 @@ WorkerThreadFunc(void *_listenSock) char *sendBuf; if (debug_mode) DPRINTF("\tServer buffer is %d bytes; %d data, %d netaddrs\n", - _client_data+(4*sizeof(PRNetAddr)), _client_data, (4*sizeof(PRNetAddr))); - dataBuf = (char *)PR_MALLOC(_client_data *sizeof(char) + 4*sizeof(PRNetAddr)); + _client_data+(2*sizeof(PRNetAddr))+32, _client_data, (2*sizeof(PRNetAddr))+32); + dataBuf = (char *)PR_MALLOC(_client_data + 2*sizeof(PRNetAddr) + 32); if (!dataBuf) if (debug_mode) printf("\tServer could not malloc space!?\n"); sendBuf = (char *)PR_MALLOC(_server_data *sizeof(char)); diff --git a/pr/tests/servr_kk.c b/pr/tests/servr_kk.c index 3a225ff1..7ad32922 100644 --- a/pr/tests/servr_kk.c +++ b/pr/tests/servr_kk.c @@ -126,8 +126,8 @@ WorkerThreadFunc(void *_listenSock) char *sendBuf; if (debug_mode) DPRINTF("\tServer buffer is %d bytes; %d data, %d netaddrs\n", - _client_data+(4*sizeof(PRNetAddr)), _client_data, (4*sizeof(PRNetAddr))); - dataBuf = (char *)PR_MALLOC(_client_data *sizeof(char) + 4*sizeof(PRNetAddr)); + _client_data+(2*sizeof(PRNetAddr))+32, _client_data, (2*sizeof(PRNetAddr))+32); + dataBuf = (char *)PR_MALLOC(_client_data + 2*sizeof(PRNetAddr) + 32); if (!dataBuf) if (debug_mode) printf("\tServer could not malloc space!?\n"); sendBuf = (char *)PR_MALLOC(_server_data *sizeof(char)); diff --git a/pr/tests/servr_ku.c b/pr/tests/servr_ku.c index 53a117fa..1c573ffe 100644 --- a/pr/tests/servr_ku.c +++ b/pr/tests/servr_ku.c @@ -127,8 +127,8 @@ WorkerThreadFunc(void *_listenSock) char *sendBuf; if (debug_mode) DPRINTF("\tServer buffer is %d bytes; %d data, %d netaddrs\n", - _client_data+(4*sizeof(PRNetAddr)), _client_data, (4*sizeof(PRNetAddr))); - dataBuf = (char *)PR_MALLOC(_client_data *sizeof(char) + 4*sizeof(PRNetAddr)); + _client_data+(2*sizeof(PRNetAddr))+32, _client_data, (2*sizeof(PRNetAddr))+32); + dataBuf = (char *)PR_MALLOC(_client_data + 2*sizeof(PRNetAddr) + 32); if (!dataBuf) if (debug_mode) printf("\tServer could not malloc space!?\n"); sendBuf = (char *)PR_MALLOC(_server_data *sizeof(char)); diff --git a/pr/tests/servr_uk.c b/pr/tests/servr_uk.c index ef20cf08..19206b57 100644 --- a/pr/tests/servr_uk.c +++ b/pr/tests/servr_uk.c @@ -129,8 +129,8 @@ WorkerThreadFunc(void *_listenSock) char *sendBuf; if (debug_mode) DPRINTF("\tServer buffer is %d bytes; %d data, %d netaddrs\n", - _client_data+(4*sizeof(PRNetAddr)), _client_data, (4*sizeof(PRNetAddr))); - dataBuf = (char *)PR_MALLOC(_client_data *sizeof(char) + 4*sizeof(PRNetAddr)); + _client_data+(2*sizeof(PRNetAddr))+32, _client_data, (2*sizeof(PRNetAddr))+32); + dataBuf = (char *)PR_MALLOC(_client_data + 2*sizeof(PRNetAddr) + 32); if (!dataBuf) if (debug_mode) printf("\tServer could not malloc space!?\n"); sendBuf = (char *)PR_MALLOC(_server_data *sizeof(char)); diff --git a/pr/tests/servr_uu.c b/pr/tests/servr_uu.c index b6fc3a8f..8b9bc47d 100644 --- a/pr/tests/servr_uu.c +++ b/pr/tests/servr_uu.c @@ -127,8 +127,8 @@ WorkerThreadFunc(void *_listenSock) char *sendBuf; if (debug_mode) DPRINTF("\tServer buffer is %d bytes; %d data, %d netaddrs\n", - _client_data+(4*sizeof(PRNetAddr)), _client_data, (4*sizeof(PRNetAddr))); - dataBuf = (char *)PR_MALLOC(_client_data *sizeof(char) + 4*sizeof(PRNetAddr)); + _client_data+(2*sizeof(PRNetAddr))+32, _client_data, (2*sizeof(PRNetAddr))+32); + dataBuf = (char *)PR_MALLOC(_client_data + 2*sizeof(PRNetAddr) + 32); if (!dataBuf) if (debug_mode) printf("\tServer could not malloc space!?\n"); sendBuf = (char *)PR_MALLOC(_server_data *sizeof(char)); diff --git a/pr/tests/socket.c b/pr/tests/socket.c index 87165193..316ec75c 100644 --- a/pr/tests/socket.c +++ b/pr/tests/socket.c @@ -130,6 +130,7 @@ static PRInt32 num_udp_datagrams_per_client = NUM_UDP_DATAGRAMS_PER_CLIENT; static PRInt32 udp_datagram_size = UDP_DGRAM_SIZE; static PRInt32 thread_count; +PRUint16 server_domain = PR_AF_INET, client_domain = PR_AF_INET; int failed_already=0; typedef struct buffer { @@ -169,7 +170,7 @@ readn(PRFileDesc *sockfd, char *buf, int len) int rem; int bytes; int offset = 0; - int err, oserr; + int err; PRIntervalTime timeout = PR_INTERVAL_NO_TIMEOUT; if (test_cancelio) @@ -362,19 +363,23 @@ TCP_Server(void *arg) /* * Create a tcp socket */ - if ((sockfd = PR_NewTCPSocket()) == NULL) { + if ((sockfd = PR_OpenTCPSocket(server_domain)) == NULL) { fprintf(stderr,"prsocket_test: PR_NewTCPSocket failed\n"); goto exit; } memset(&netaddr, 0 , sizeof(netaddr)); - netaddr.inet.family = PR_AF_INET; - netaddr.inet.port = PR_htons(TCP_SERVER_PORT); - netaddr.inet.ip = PR_htonl(PR_INADDR_ANY); + + if (PR_SetNetAddr(PR_IpAddrAny, server_domain, TCP_SERVER_PORT, + &netaddr) == PR_FAILURE) { + fprintf(stderr,"prsocket_test: PR_SetNetAddr failed\n"); + goto exit; + } /* * try a few times to bind server's address, if addresses are in * use */ i = 0; + while (PR_Bind(sockfd, &netaddr) < 0) { if (PR_GetError() == PR_ADDRESS_IN_USE_ERROR) { netaddr.inet.port += 2; @@ -401,9 +406,15 @@ TCP_Server(void *arg) DPRINTF(("TCP_Server: PR_BIND netaddr.inet.ip = 0x%lx, netaddr.inet.port = %d\n", netaddr.inet.ip, netaddr.inet.port)); - tcp_server_addr.inet.family = netaddr.inet.family; - tcp_server_addr.inet.port = netaddr.inet.port; - tcp_server_addr.inet.ip = netaddr.inet.ip; + if (PR_SetNetAddr(PR_IpAddrLoopback, client_domain, + PR_ntohs(PR_NetAddrInetPort(&netaddr)), + &tcp_server_addr) == PR_FAILURE) { + fprintf(stderr,"prsocket_test: PR_SetNetAddr failed\n"); + goto exit; + } + if ((client_domain == PR_AF_INET6) && (server_domain == PR_AF_INET)) + PR_ConvertIPv4AddrToIPv6(PR_htonl(INADDR_LOOPBACK), + &tcp_server_addr.ipv6.ip); /* * Wake up parent thread because server address is bound and made @@ -413,11 +424,13 @@ TCP_Server(void *arg) for (i = 0; i < (num_tcp_clients * num_tcp_connections_per_client); i++) { + DPRINTF(("TCP_Server: Accepting connection\n")); if ((newsockfd = PR_Accept(sockfd, &netaddr, PR_INTERVAL_NO_TIMEOUT)) == NULL) { fprintf(stderr,"prsocket_test: ERROR - PR_Accept failed\n"); goto exit; } + DPRINTF(("TCP_Server: Accepted connection\n")); scp = PR_NEW(Serve_Client_Param); if (scp == NULL) { fprintf(stderr,"prsocket_test: PR_NEW failed\n"); @@ -480,15 +493,18 @@ UDP_Server(void *arg) /* * Create a udp socket */ - if ((sockfd = PR_NewUDPSocket()) == NULL) { + if ((sockfd = PR_OpenUDPSocket(server_domain)) == NULL) { fprintf(stderr,"prsocket_test: PR_NewUDPSocket failed\n"); failed_already=1; return; } memset(&netaddr, 0 , sizeof(netaddr)); - netaddr.inet.family = PR_AF_INET; - netaddr.inet.port = PR_htons(UDP_SERVER_PORT); - netaddr.inet.ip = PR_htonl(PR_INADDR_ANY); + if (PR_SetNetAddr(PR_IpAddrAny, server_domain, UDP_SERVER_PORT, + &netaddr) == PR_FAILURE) { + fprintf(stderr,"prsocket_test: PR_SetNetAddr failed\n"); + failed_already=1; + return; + } /* * try a few times to bind server's address, if addresses are in * use @@ -514,16 +530,23 @@ UDP_Server(void *arg) DPRINTF(("PR_Bind: UDP Server netaddr.inet.ip = 0x%lx, netaddr.inet.port = %d\n", netaddr.inet.ip, netaddr.inet.port)); - udp_server_addr = netaddr; - /* * We can't use the IP address returned by PR_GetSockName in - * netaddr.inet.ip because netaddr.inet.ip is returned - * as 0 (= PR_INADDR_ANY). + * netaddr.inet.ip because netaddr.inet.ip is returned + * as 0 (= PR_INADDR_ANY). */ - udp_server_addr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK); - + if (PR_SetNetAddr(PR_IpAddrLoopback, client_domain, + PR_ntohs(PR_NetAddrInetPort(&netaddr)), + &udp_server_addr) == PR_FAILURE) { + fprintf(stderr,"prsocket_test: PR_SetNetAddr failed\n"); + failed_already=1; + return; + } + if ((client_domain == PR_AF_INET6) && (server_domain == PR_AF_INET)) + PR_ConvertIPv4AddrToIPv6(PR_htonl(INADDR_LOOPBACK), + &udp_server_addr.ipv6.ip); + /* * Wake up parent thread because server address is bound and made * available in the global variable 'udp_server_addr' @@ -606,17 +629,14 @@ TCP_Client(void *arg) failed_already=1; return; } - netaddr.inet.family = cp->server_addr.inet.family; - netaddr.inet.port = cp->server_addr.inet.port; - netaddr.inet.ip = cp->server_addr.inet.ip; + netaddr = cp->server_addr; for (i = 0; i < num_tcp_connections_per_client; i++) { - if ((sockfd = PR_OpenTCPSocket(PR_AF_INET)) == NULL) { + if ((sockfd = PR_OpenTCPSocket(client_domain)) == NULL) { fprintf(stderr,"prsocket_test: PR_OpenTCPSocket failed\n"); failed_already=1; return; } - if (PR_Connect(sockfd, &netaddr,PR_INTERVAL_NO_TIMEOUT) < 0){ fprintf(stderr, "PR_Connect failed: (%ld, %ld)\n", PR_GetError(), PR_GetOSError()); @@ -712,7 +732,7 @@ UDP_Client(void *arg) failed_already=1; return; } - if ((sockfd = PR_OpenUDPSocket(PR_AF_INET)) == NULL) { + if ((sockfd = PR_OpenUDPSocket(client_domain)) == NULL) { fprintf(stderr,"prsocket_test: PR_OpenUDPSocket failed\n"); failed_already=1; return; @@ -723,9 +743,12 @@ UDP_Client(void *arg) * number */ memset(&netaddr, 0 , sizeof(netaddr)); - netaddr.inet.family = PR_AF_INET; - netaddr.inet.ip = PR_htonl(PR_INADDR_ANY); - netaddr.inet.port = PR_htons(0); + if (PR_SetNetAddr(PR_IpAddrAny, client_domain, 0, + &netaddr) == PR_FAILURE) { + fprintf(stderr,"prsocket_test: PR_SetNetAddr failed\n"); + failed_already=1; + return; + } if (PR_Bind(sockfd, &netaddr) < 0) { fprintf(stderr,"prsocket_test: ERROR - PR_Bind failed\n"); perror("PR_Bind"); @@ -741,9 +764,7 @@ UDP_Client(void *arg) DPRINTF(("PR_Bind: UDP Client netaddr.inet.ip = 0x%lx, netaddr.inet.port = %d\n", netaddr.inet.ip, netaddr.inet.port)); - netaddr.inet.family = cp->server_addr.inet.family; - netaddr.inet.port = cp->server_addr.inet.port; - netaddr.inet.ip = cp->server_addr.inet.ip; + netaddr = cp->server_addr; if (cp->udp_connect) { if (PR_Connect(sockfd, &netaddr,PR_INTERVAL_NO_TIMEOUT) < 0){ @@ -894,7 +915,6 @@ TCP_Socket_Client_Server_Test(void) return -1; } cparamp->server_addr = tcp_server_addr; - cparamp->server_addr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK); cparamp->exit_mon = mon2; cparamp->exit_counter = &thread_count; cparamp->datalen = datalen; @@ -2138,8 +2158,41 @@ main(int argc, char **argv) #endif PR_SetConcurrency(4); /* - * run client-server test with TCP + * run client-server test with TCP, Ipv4-Ipv4 */ + printf("TCP Client/Server Test - IPv4/Ipv4\n"); + if (TCP_Socket_Client_Server_Test() < 0) { + printf("TCP_Socket_Client_Server_Test failed\n"); + goto done; + } else + printf("TCP_Socket_Client_Server_Test Passed\n"); + /* + * client-server test, Ipv6-Ipv4 + */ + client_domain = PR_AF_INET6; + printf("TCP Client/Server Test - IPv6/Ipv4\n"); + if (TCP_Socket_Client_Server_Test() < 0) { + printf("TCP_Socket_Client_Server_Test failed\n"); + goto done; + } else + printf("TCP_Socket_Client_Server_Test Passed\n"); + /* + * client-server test, Ipv4-Ipv6 + */ + client_domain = PR_AF_INET; + server_domain = PR_AF_INET6; + printf("TCP Client/Server Test - IPv4/Ipv6\n"); + if (TCP_Socket_Client_Server_Test() < 0) { + printf("TCP_Socket_Client_Server_Test failed\n"); + goto done; + } else + printf("TCP_Socket_Client_Server_Test Passed\n"); + /* + * client-server test, Ipv6-Ipv6 + */ + client_domain = PR_AF_INET6; + server_domain = PR_AF_INET6; + printf("TCP Client/Server Test - IPv6/Ipv6\n"); if (TCP_Socket_Client_Server_Test() < 0) { printf("TCP_Socket_Client_Server_Test failed\n"); goto done; @@ -2147,8 +2200,44 @@ main(int argc, char **argv) printf("TCP_Socket_Client_Server_Test Passed\n"); test_cancelio = 0; /* - * run client-server test with UDP + * run client-server test with UDP, IPv4/IPv4 + */ + printf("UDP Client/Server Test - IPv4/Ipv4\n"); + client_domain = PR_AF_INET; + server_domain = PR_AF_INET; + if (UDP_Socket_Client_Server_Test() < 0) { + printf("UDP_Socket_Client_Server_Test failed\n"); + goto done; + } else + printf("UDP_Socket_Client_Server_Test Passed\n"); + /* + * run client-server test with UDP, IPv6/IPv4 + */ + printf("UDP Client/Server Test - IPv6/Ipv4\n"); + client_domain = PR_AF_INET6; + server_domain = PR_AF_INET; + if (UDP_Socket_Client_Server_Test() < 0) { + printf("UDP_Socket_Client_Server_Test failed\n"); + goto done; + } else + printf("UDP_Socket_Client_Server_Test Passed\n"); + /* + * run client-server test with UDP,IPv4-IPv6 + */ + printf("UDP Client/Server Test - IPv4/Ipv6\n"); + client_domain = PR_AF_INET; + server_domain = PR_AF_INET6; + if (UDP_Socket_Client_Server_Test() < 0) { + printf("UDP_Socket_Client_Server_Test failed\n"); + goto done; + } else + printf("UDP_Socket_Client_Server_Test Passed\n"); + /* + * run client-server test with UDP,IPv6-IPv6 */ + printf("UDP Client/Server Test - IPv6/Ipv6\n"); + client_domain = PR_AF_INET6; + server_domain = PR_AF_INET6; if (UDP_Socket_Client_Server_Test() < 0) { printf("UDP_Socket_Client_Server_Test failed\n"); goto done; diff --git a/pr/tests/sockopt.c b/pr/tests/sockopt.c index 0dca5b92..d4a3f6c6 100644 --- a/pr/tests/sockopt.c +++ b/pr/tests/sockopt.c @@ -100,9 +100,6 @@ PRIntn main(PRIntn argc, char *argv) else { PRSockOption option; - PRLinger linger; - PRUint32 ttl = 20; - PRBool boolean = PR_TRUE; PRUint32 segment = 1024; PRNetAddr addr; @@ -112,76 +109,6 @@ PRIntn main(PRIntn argc, char *argv) if (PR_FAILURE == rv) Failed("PR_Bind()", NULL); for(option = PR_SockOpt_Linger; option < PR_SockOpt_Last; Incr(&option)) { - void *value; - PRInt32 *size; - PRInt32 ttlsize = sizeof(ttl); - PRInt32 segmentsize = sizeof(segment); - PRInt32 booleansize = sizeof(boolean); - PRInt32 lingersize = sizeof(linger); - - PRFileDesc *socket = udp; - switch (option) - { - case PR_SockOpt_Linger: /* linger on close if data present */ - socket = tcp; - linger.polarity = PR_TRUE; - linger.linger = PR_SecondsToInterval(1); - value = &linger; - size = &lingersize; - break; - case PR_SockOpt_NoDelay: /* don't delay send to coalesce packets */ - case PR_SockOpt_Keepalive: /* keep connections alive */ - socket = tcp; - case PR_SockOpt_Reuseaddr: /* allow local address reuse */ - value = &boolean; - size = &booleansize; - break; -#ifndef WIN32 - case PR_SockOpt_MaxSegment: /* maximum segment size */ - socket = tcp; -#endif - case PR_SockOpt_RecvBufferSize: /* send buffer size */ - case PR_SockOpt_SendBufferSize: /* receive buffer size */ - value = &segment; - size = &segmentsize; - break; - - case PR_SockOpt_IpTimeToLive: /* time to live */ - value = &ttl; - size = &ttlsize; - break; - case PR_SockOpt_Broadcast: - value = &boolean; - size = &booleansize; - break; - case PR_SockOpt_IpTypeOfService: /* type of service and precedence */ - case PR_SockOpt_AddMember: /* add an IP group membership */ - case PR_SockOpt_DropMember: /* drop an IP group membership */ - case PR_SockOpt_McastInterface: /* multicast interface address */ - case PR_SockOpt_McastTimeToLive: /* multicast timetolive */ - case PR_SockOpt_McastLoopback: /* multicast loopback */ - default: - continue; - } - /* - * TCP_MAXSEG can only be read, not set - */ - if (option != PR_SockOpt_MaxSegment) { -#ifdef WIN32 - if (option != PR_SockOpt_McastLoopback) -#endif - { - rv = PR_SetSockOpt(socket, option, value, *size); - if (PR_FAILURE == rv) Failed("PR_SetSockOpt()", - tag[option]); - } - } - - rv = PR_GetSockOpt(socket, option, &value, size); - if (PR_FAILURE == rv) Failed("PR_GetSockOpt()", tag[option]); - } - for(option = PR_SockOpt_Linger; option < PR_SockOpt_Last; Incr(&option)) - { PRSocketOptionData data; PRFileDesc *fd = tcp; data.option = option; diff --git a/pr/tests/thrpool_client.c b/pr/tests/thrpool_client.c index d06930f3..46d93b0a 100644 --- a/pr/tests/thrpool_client.c +++ b/pr/tests/thrpool_client.c @@ -25,7 +25,6 @@ ** Modification History: */ #include "primpl.h" -#include "prtpool.h" #include "plgetopt.h" diff --git a/pr/tests/thrpool_server.c b/pr/tests/thrpool_server.c index 0452a0a9..56efcce9 100644 --- a/pr/tests/thrpool_server.c +++ b/pr/tests/thrpool_server.c @@ -25,7 +25,6 @@ ** Modification History: */ #include "primpl.h" -#include "prtpool.h" #include "plgetopt.h" @@ -251,6 +250,27 @@ Serve_Client(void *arg) PR_DELETE(scp); } +static void +print_stats(void *arg) +{ + Server_Param *sp = (Server_Param *) arg; + PRThreadPool *tp = sp->tp; + PRInt32 counter; + PRJob *jobp; + + PR_EnterMonitor(sp->exit_mon); + counter = (*sp->job_counterp); + PR_ExitMonitor(sp->exit_mon); + + printf("PRINT_STATS: #client connections = %d\n",counter); + + + jobp = PR_QueueJob_Timer(tp, PR_MillisecondsToInterval(500), + print_stats, sp, PR_FALSE); + + PR_ASSERT(NULL != jobp); +} + static int job_counter = 0; /* * TCP Server @@ -273,6 +293,7 @@ TCP_Server(void *arg) PRMonitor *sc_mon; PRJob *jobp; int i; + PRStatus rval; /* * Create a tcp socket @@ -318,6 +339,28 @@ TCP_Server(void *arg) "TCP_Server: PR_BIND netaddr.inet.ip = 0x%lx, netaddr.inet.port = %d\n", netaddr.inet.ip, netaddr.inet.port)); + sp = PR_NEW(Server_Param); + if (sp == NULL) { + fprintf(stderr,"%s: PR_NEW failed\n", program_name); + failed_already=1; + return; + } + sp->iod.socket = sockfd; + sp->iod.timeout = PR_SecondsToInterval(60); + sp->datalen = tcp_mesg_size; + sp->exit_mon = sc_mon; + sp->job_counterp = &job_counter; + sp->conn_counter = 0; + sp->tp = tp; + sp->netaddr = netaddr; + + /* create and cancel an io job */ + jobp = PR_QueueJob_Accept(tp, &sp->iod, TCP_Server_Accept, sp, + PR_FALSE); + PR_ASSERT(NULL != jobp); + rval = PR_CancelJob(jobp); + PR_ASSERT(PR_SUCCESS == rval); + /* * create the client process */ @@ -363,12 +406,6 @@ TCP_Server(void *arg) return; } - sp = PR_NEW(Server_Param); - if (sp == NULL) { - fprintf(stderr,"%s: PR_NEW failed\n", program_name); - failed_already=1; - return; - } sp->iod.socket = sockfd; sp->iod.timeout = PR_SecondsToInterval(60); sp->datalen = tcp_mesg_size; @@ -378,6 +415,13 @@ TCP_Server(void *arg) sp->tp = tp; sp->netaddr = netaddr; + /* create and cancel a timer job */ + jobp = PR_QueueJob_Timer(tp, PR_MillisecondsToInterval(5000), + print_stats, sp, PR_FALSE); + PR_ASSERT(NULL != jobp); + rval = PR_CancelJob(jobp); + PR_ASSERT(PR_SUCCESS == rval); + DPRINTF(("TCP_Server: Accepting connections \n")); jobp = PR_QueueJob_Accept(tp, &sp->iod, TCP_Server_Accept, sp, @@ -387,27 +431,6 @@ TCP_Server(void *arg) } static void -print_stats(void *arg) -{ - Server_Param *sp = (Server_Param *) arg; - PRThreadPool *tp = sp->tp; - PRInt32 counter; - PRJob *jobp; - - PR_EnterMonitor(sp->exit_mon); - counter = (*sp->job_counterp); - PR_ExitMonitor(sp->exit_mon); - - printf("PRINT_STATS: #client connections = %d\n",counter); - - - jobp = PR_QueueJob_Timer(tp, PR_MillisecondsToInterval(500), - print_stats, sp, PR_FALSE); - - PR_ASSERT(NULL != jobp); -} - -static void TCP_Server_Accept(void *arg) { Server_Param *sp = (Server_Param *) arg; diff --git a/pr/tests/thruput.c b/pr/tests/thruput.c index f06c1694..bdc23c3f 100644 --- a/pr/tests/thruput.c +++ b/pr/tests/thruput.c @@ -294,9 +294,7 @@ static void Help(void) PR_fprintf(err, "\t-B <nK> Transport recv/send buffer size (default: sys)\n"); PR_fprintf(err, "\t-G Use GLOBAL threads (default: LOCAL)\n"); PR_fprintf(err, "\t-X Use XTP transport (default: TCP)\n"); -#ifdef _PR_INET6 PR_fprintf(err, "\t-6 Use IPv6 (default: IPv4)\n"); -#endif /* _PR_INET6 */ PR_fprintf(err, "\t-h This message and nothing else\n"); PR_fprintf(err, "\t<server> DNS name of server\n"); PR_fprintf(err, "\t\tIf <server> is not specified, this host will be\n"); @@ -325,12 +323,9 @@ PRIntn main(PRIntn argc, char **argv) case 'X': /* Use XTP as the transport */ protocol = 36; break; -#ifdef _PR_INET6 case '6': /* Use IPv6 */ domain = PR_AF_INET6; - PR_SetIPv6Enable(PR_TRUE); break; -#endif /* _PR_INET6 */ case 's': /* initial_streams */ initial_streams = atoi(opt->value); break; diff --git a/pr/tests/tmoacc.c b/pr/tests/tmoacc.c index 2fe746c4..f41ce8c1 100644 --- a/pr/tests/tmoacc.c +++ b/pr/tests/tmoacc.c @@ -188,10 +188,6 @@ PRIntn Tmoacc(PRIntn argc, char **argv) PLOptState *opt = PL_CreateOptState(argc, argv, "dGb:t:T:R"); -#ifdef _PR_INET6 - PR_SetIPv6Enable(PR_TRUE); -#endif - shared = PR_NEWZAP(Shared); shared->debug = NULL; diff --git a/pr/tests/tmocon.c b/pr/tests/tmocon.c index d3bb9839..0fd83b3c 100644 --- a/pr/tests/tmocon.c +++ b/pr/tests/tmocon.c @@ -280,9 +280,6 @@ int Tmocon(int argc, char **argv) PRInt32 dally = DEFAULT_DALLY, timeout = DEFAULT_TIMEOUT; PLOptState *opt = PL_CreateOptState(argc, argv, "divGRh:m:s:t:T:D:"); -#ifdef _PR_INET6 - PR_SetIPv6Enable(PR_TRUE); -#endif shared = PR_NEWZAP(Shared); shared->debug = 0; diff --git a/pr/tests/vercheck.c b/pr/tests/vercheck.c index b616ad2a..461e7316 100644 --- a/pr/tests/vercheck.c +++ b/pr/tests/vercheck.c @@ -33,21 +33,26 @@ #include <stdlib.h> /* - * This release (3.5) is backward compatible with all - * the previous releases. It, of course, is compatible - * with itself. + * This release (4.0) is compatible with itself. */ static char *compatible_version[] = { - "2.1 19980529", "3.0", "3.0.1", "3.1", "3.1.1", "3.1.2", PR_VERSION + PR_VERSION }; /* + * This release is not backward compatible with the old + * NSPR 2.1 and 3.x releases. + * * Any release is incompatible with future releases and * patches. */ static char *incompatible_version[] = { - "3.5.1", - "4.0", "4.0.3", + "2.1 19980529", + "3.0", "3.0.1", + "3.1", "3.1.1", "3.1.2", "3.1.3", + "3.5", "3.5.1", + "4.0.1", + "4.1", "4.1.3", "10.0", "11.1", "12.14.20" }; diff --git a/pr/tests/version.c b/pr/tests/version.c index b361a9c1..a6218ec8 100644 --- a/pr/tests/version.c +++ b/pr/tests/version.c @@ -24,6 +24,8 @@ #include "plerror.h" #include "plgetopt.h" +PR_IMPORT(const PRVersionDescription *) libVersionPoint(void); + PRIntn main(PRIntn argc, char **argv) { PRIntn rv = 1; |