diff options
author | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
---|---|---|
committer | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
commit | 554fd8c5195424bdbcabf5de30fdc183aba391bd (patch) | |
tree | 976dc5ab7fddf506dadce60ae936f43f58787092 /libjava/classpath/native/jni/java-nio | |
download | cbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.bz2 cbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.xz |
obtained gcc-4.6.4.tar.bz2 from upstream website;upstream
verified gcc-4.6.4.tar.bz2.sig;
imported gcc-4.6.4 source tree from verified upstream tarball.
downloading a git-generated archive based on the 'upstream' tag
should provide you with a source tree that is binary identical
to the one extracted from the above tarball.
if you have obtained the source via the command 'git clone',
however, do note that line-endings of files in your working
directory might differ from line-endings of the respective
files in the upstream repository.
Diffstat (limited to 'libjava/classpath/native/jni/java-nio')
14 files changed, 5163 insertions, 0 deletions
diff --git a/libjava/classpath/native/jni/java-nio/.cvsignore b/libjava/classpath/native/jni/java-nio/.cvsignore new file mode 100644 index 000000000..e9f2658a6 --- /dev/null +++ b/libjava/classpath/native/jni/java-nio/.cvsignore @@ -0,0 +1,8 @@ +*.o +*.a +*.lo +*.la +.libs +.deps +Makefile +Makefile.in diff --git a/libjava/classpath/native/jni/java-nio/Makefile.am b/libjava/classpath/native/jni/java-nio/Makefile.am new file mode 100644 index 000000000..398e6a6e7 --- /dev/null +++ b/libjava/classpath/native/jni/java-nio/Makefile.am @@ -0,0 +1,24 @@ +nativeexeclib_LTLIBRARIES = libjavanio.la + +libjavanio_la_SOURCES = gnu_java_nio_VMPipe.c \ + gnu_java_nio_VMChannel.c \ + gnu_java_nio_VMSelector.c \ + gnu_java_nio_charset_iconv_IconvDecoder.c \ + gnu_java_nio_charset_iconv_IconvEncoder.c \ + java_nio_MappedByteBufferImpl.c \ + java_nio_VMDirectByteBuffer.c \ + gnu_java_nio_EpollSelectorImpl.c \ + gnu_java_nio_KqueueSelectorImpl.c \ + javanio.h + +libjavanio_la_LIBADD = $(top_builddir)/native/jni/classpath/jcl.lo \ + $(top_builddir)/native/jni/native-lib/libclasspathnative.la \ + $(LTLIBICONV) + +# Directly included through javanio.h +EXTRA_DIST = javanio.c + +AM_LDFLAGS = @CLASSPATH_MODULE@ +AM_CPPFLAGS = @CLASSPATH_INCLUDES@ +AM_CFLAGS = @WARNING_CFLAGS@ @STRICT_WARNING_CFLAGS@ @ERROR_CFLAGS@ \ + @EXTRA_CFLAGS@ diff --git a/libjava/classpath/native/jni/java-nio/Makefile.in b/libjava/classpath/native/jni/java-nio/Makefile.in new file mode 100644 index 000000000..427d072a1 --- /dev/null +++ b/libjava/classpath/native/jni/java-nio/Makefile.in @@ -0,0 +1,642 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = native/jni/java-nio +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/../../config/depstand.m4 \ + $(top_srcdir)/../../config/lead-dot.m4 \ + $(top_srcdir)/../../config/lib-ld.m4 \ + $(top_srcdir)/../../config/lib-link.m4 \ + $(top_srcdir)/../../config/lib-prefix.m4 \ + $(top_srcdir)/../../config/multi.m4 \ + $(top_srcdir)/../../config/no-executables.m4 \ + $(top_srcdir)/../../config/override.m4 \ + $(top_srcdir)/../../libtool.m4 \ + $(top_srcdir)/../../ltoptions.m4 \ + $(top_srcdir)/../../ltsugar.m4 \ + $(top_srcdir)/../../ltversion.m4 \ + $(top_srcdir)/../../lt~obsolete.m4 \ + $(top_srcdir)/m4/ac_prog_antlr.m4 \ + $(top_srcdir)/m4/ac_prog_java.m4 \ + $(top_srcdir)/m4/ac_prog_java_works.m4 \ + $(top_srcdir)/m4/ac_prog_javac.m4 \ + $(top_srcdir)/m4/ac_prog_javac_works.m4 \ + $(top_srcdir)/m4/acattribute.m4 $(top_srcdir)/m4/accross.m4 \ + $(top_srcdir)/m4/acinclude.m4 \ + $(top_srcdir)/m4/ax_create_stdint_h.m4 \ + $(top_srcdir)/m4/ax_func_which_gethostbyname_r.m4 \ + $(top_srcdir)/m4/gcc_attribute.m4 $(top_srcdir)/m4/iconv.m4 \ + $(top_srcdir)/m4/pkg.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/../../mkinstalldirs +CONFIG_HEADER = $(top_builddir)/include/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__installdirs = "$(DESTDIR)$(nativeexeclibdir)" +LTLIBRARIES = $(nativeexeclib_LTLIBRARIES) +am__DEPENDENCIES_1 = +libjavanio_la_DEPENDENCIES = \ + $(top_builddir)/native/jni/classpath/jcl.lo \ + $(top_builddir)/native/jni/native-lib/libclasspathnative.la \ + $(am__DEPENDENCIES_1) +am_libjavanio_la_OBJECTS = gnu_java_nio_VMPipe.lo \ + gnu_java_nio_VMChannel.lo gnu_java_nio_VMSelector.lo \ + gnu_java_nio_charset_iconv_IconvDecoder.lo \ + gnu_java_nio_charset_iconv_IconvEncoder.lo \ + java_nio_MappedByteBufferImpl.lo \ + java_nio_VMDirectByteBuffer.lo \ + gnu_java_nio_EpollSelectorImpl.lo \ + gnu_java_nio_KqueueSelectorImpl.lo +libjavanio_la_OBJECTS = $(am_libjavanio_la_OBJECTS) +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include +depcomp = $(SHELL) $(top_srcdir)/../../depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libjavanio_la_SOURCES) +ETAGS = etags +CTAGS = ctags +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +ANTLR = @ANTLR@ +ANTLR_JAR = @ANTLR_JAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CAIRO_CFLAGS = @CAIRO_CFLAGS@ +CAIRO_LIBS = @CAIRO_LIBS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CLASSPATH_CONVENIENCE = @CLASSPATH_CONVENIENCE@ +CLASSPATH_INCLUDES = @CLASSPATH_INCLUDES@ +CLASSPATH_MODULE = @CLASSPATH_MODULE@ +COLLECTIONS_PREFIX = @COLLECTIONS_PREFIX@ +CP = @CP@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATE = @DATE@ +DEFAULT_PREFS_PEER = @DEFAULT_PREFS_PEER@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +ECJ_JAR = @ECJ_JAR@ +EGREP = @EGREP@ +ERROR_CFLAGS = @ERROR_CFLAGS@ +EXAMPLESDIR = @EXAMPLESDIR@ +EXEEXT = @EXEEXT@ +EXTRA_CFLAGS = @EXTRA_CFLAGS@ +FGREP = @FGREP@ +FIND = @FIND@ +FREETYPE2_CFLAGS = @FREETYPE2_CFLAGS@ +FREETYPE2_LIBS = @FREETYPE2_LIBS@ +GCONF_CFLAGS = @GCONF_CFLAGS@ +GCONF_LIBS = @GCONF_LIBS@ +GDK_CFLAGS = @GDK_CFLAGS@ +GDK_LIBS = @GDK_LIBS@ +GJDOC = @GJDOC@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_LIBS = @GLIB_LIBS@ +GMP_CFLAGS = @GMP_CFLAGS@ +GMP_LIBS = @GMP_LIBS@ +GREP = @GREP@ +GSTREAMER_BASE_CFLAGS = @GSTREAMER_BASE_CFLAGS@ +GSTREAMER_BASE_LIBS = @GSTREAMER_BASE_LIBS@ +GSTREAMER_CFLAGS = @GSTREAMER_CFLAGS@ +GSTREAMER_FILE_READER = @GSTREAMER_FILE_READER@ +GSTREAMER_LIBS = @GSTREAMER_LIBS@ +GSTREAMER_MIXER_PROVIDER = @GSTREAMER_MIXER_PROVIDER@ +GSTREAMER_PLUGINS_BASE_CFLAGS = @GSTREAMER_PLUGINS_BASE_CFLAGS@ +GSTREAMER_PLUGINS_BASE_LIBS = @GSTREAMER_PLUGINS_BASE_LIBS@ +GST_PLUGIN_LDFLAGS = @GST_PLUGIN_LDFLAGS@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +INIT_LOAD_LIBRARY = @INIT_LOAD_LIBRARY@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +JAR = @JAR@ +JAVA = @JAVA@ +JAVAC = @JAVAC@ +JAVAC_IS_GCJ = @JAVAC_IS_GCJ@ +JAVAC_MEM_OPT = @JAVAC_MEM_OPT@ +JAVA_LANG_SYSTEM_EXPLICIT_INITIALIZATION = @JAVA_LANG_SYSTEM_EXPLICIT_INITIALIZATION@ +JAY = @JAY@ +JAY_SKELETON = @JAY_SKELETON@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDEBUG = @LIBDEBUG@ +LIBICONV = @LIBICONV@ +LIBMAGIC = @LIBMAGIC@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBVERSION = @LIBVERSION@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBICONV = @LTLIBICONV@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MKDIR = @MKDIR@ +MKDIR_P = @MKDIR_P@ +MOC = @MOC@ +MOZILLA_CFLAGS = @MOZILLA_CFLAGS@ +MOZILLA_LIBS = @MOZILLA_LIBS@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PANGOFT2_CFLAGS = @PANGOFT2_CFLAGS@ +PANGOFT2_LIBS = @PANGOFT2_LIBS@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PATH_TO_ESCHER = @PATH_TO_ESCHER@ +PATH_TO_GLIBJ_ZIP = @PATH_TO_GLIBJ_ZIP@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PLUGIN_DIR = @PLUGIN_DIR@ +QT_CFLAGS = @QT_CFLAGS@ +QT_LIBS = @QT_LIBS@ +RANLIB = @RANLIB@ +REMOVE = @REMOVE@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRICT_WARNING_CFLAGS = @STRICT_WARNING_CFLAGS@ +STRIP = @STRIP@ +TOOLSDIR = @TOOLSDIR@ +USER_JAVAH = @USER_JAVAH@ +VERSION = @VERSION@ +WANT_NATIVE_BIG_INTEGER = @WANT_NATIVE_BIG_INTEGER@ +WARNING_CFLAGS = @WARNING_CFLAGS@ +XMKMF = @XMKMF@ +XML_CFLAGS = @XML_CFLAGS@ +XML_LIBS = @XML_LIBS@ +XSLT_CFLAGS = @XSLT_CFLAGS@ +XSLT_LIBS = @XSLT_LIBS@ +XTEST_LIBS = @XTEST_LIBS@ +X_CFLAGS = @X_CFLAGS@ +X_EXTRA_LIBS = @X_EXTRA_LIBS@ +X_LIBS = @X_LIBS@ +X_PRE_LIBS = @X_PRE_LIBS@ +ZIP = @ZIP@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_ANTLR = @ac_ct_ANTLR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +default_toolkit = @default_toolkit@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +glibjdir = @glibjdir@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +multi_basedir = @multi_basedir@ +nativeexeclibdir = @nativeexeclibdir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +toolexeclibdir = @toolexeclibdir@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +uudecode = @uudecode@ +vm_classes = @vm_classes@ +nativeexeclib_LTLIBRARIES = libjavanio.la +libjavanio_la_SOURCES = gnu_java_nio_VMPipe.c \ + gnu_java_nio_VMChannel.c \ + gnu_java_nio_VMSelector.c \ + gnu_java_nio_charset_iconv_IconvDecoder.c \ + gnu_java_nio_charset_iconv_IconvEncoder.c \ + java_nio_MappedByteBufferImpl.c \ + java_nio_VMDirectByteBuffer.c \ + gnu_java_nio_EpollSelectorImpl.c \ + gnu_java_nio_KqueueSelectorImpl.c \ + javanio.h + +libjavanio_la_LIBADD = $(top_builddir)/native/jni/classpath/jcl.lo \ + $(top_builddir)/native/jni/native-lib/libclasspathnative.la \ + $(LTLIBICONV) + + +# Directly included through javanio.h +EXTRA_DIST = javanio.c +AM_LDFLAGS = @CLASSPATH_MODULE@ +AM_CPPFLAGS = @CLASSPATH_INCLUDES@ +AM_CFLAGS = @WARNING_CFLAGS@ @STRICT_WARNING_CFLAGS@ @ERROR_CFLAGS@ \ + @EXTRA_CFLAGS@ + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu native/jni/java-nio/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu native/jni/java-nio/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-nativeexeclibLTLIBRARIES: $(nativeexeclib_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(nativeexeclibdir)" || $(MKDIR_P) "$(DESTDIR)$(nativeexeclibdir)" + @list='$(nativeexeclib_LTLIBRARIES)'; test -n "$(nativeexeclibdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(nativeexeclibdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(nativeexeclibdir)"; \ + } + +uninstall-nativeexeclibLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(nativeexeclib_LTLIBRARIES)'; test -n "$(nativeexeclibdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(nativeexeclibdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(nativeexeclibdir)/$$f"; \ + done + +clean-nativeexeclibLTLIBRARIES: + -test -z "$(nativeexeclib_LTLIBRARIES)" || rm -f $(nativeexeclib_LTLIBRARIES) + @list='$(nativeexeclib_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libjavanio.la: $(libjavanio_la_OBJECTS) $(libjavanio_la_DEPENDENCIES) + $(LINK) -rpath $(nativeexeclibdir) $(libjavanio_la_OBJECTS) $(libjavanio_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnu_java_nio_EpollSelectorImpl.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnu_java_nio_KqueueSelectorImpl.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnu_java_nio_VMChannel.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnu_java_nio_VMPipe.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnu_java_nio_VMSelector.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnu_java_nio_charset_iconv_IconvDecoder.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnu_java_nio_charset_iconv_IconvEncoder.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/java_nio_MappedByteBufferImpl.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/java_nio_VMDirectByteBuffer.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(nativeexeclibdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-nativeexeclibLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-nativeexeclibLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-nativeexeclibLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-nativeexeclibLTLIBRARIES ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags dvi dvi-am html html-am info info-am install \ + install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-nativeexeclibLTLIBRARIES install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-nativeexeclibLTLIBRARIES + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/libjava/classpath/native/jni/java-nio/gnu_java_nio_EpollSelectorImpl.c b/libjava/classpath/native/jni/java-nio/gnu_java_nio_EpollSelectorImpl.c new file mode 100644 index 000000000..39161d68e --- /dev/null +++ b/libjava/classpath/native/jni/java-nio/gnu_java_nio_EpollSelectorImpl.c @@ -0,0 +1,416 @@ +/* gnu_java_nio_EpollSelectorImpl.c -- + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is a part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at +your option) any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 +USA + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif /* HAVE_CONFIG_H */ + +#ifdef HAVE_SYS_EPOLL_H +#include <sys/epoll.h> +#endif /* HAVE_SYS_EPOLL_H */ + +#include <config-int.h> + +#include <gnu_java_nio_EpollSelectorImpl.h> +#include <jcl.h> +#include <errno.h> +#include <string.h> + +#define IO_EXCEPTION "java/io/IOException" + +/* #define TRACE_EPOLL 1 */ + + +/* + * Class: gnu_java_nio_EpollSelectorImpl + * Method: epoll_supported + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL +Java_gnu_java_nio_EpollSelectorImpl_epoll_1supported (JNIEnv *e __attribute__((unused)), + jclass c __attribute__((unused))) +{ +#ifdef HAVE_EPOLL_CREATE + return JNI_TRUE; +#else + return JNI_FALSE; +#endif /* HAVE_EPOLL_CREATE */ +} + +/* + * Class: gnu_java_nio_EpollSelectorImpl + * Method: sizeof_struct + * Signature: ()I + */ +JNIEXPORT jint JNICALL +Java_gnu_java_nio_EpollSelectorImpl_sizeof_1struct (JNIEnv *env, + jclass c __attribute__((unused))) +{ +#ifdef HAVE_EPOLL_CREATE + (void) env; +#ifdef TRACE_EPOLL + fprintf (stderr, "%s: sizeof is %d\n", __FUNCTION__, sizeof (struct epoll_event)); +#endif /* TRACE_EPOLL */ + return sizeof (struct epoll_event); +#else + JCL_ThrowException (env, "java/lang/InternalError", "epoll support not available"); + return -1; +#endif /* HAVE_EPOLL_CREATE */ +} + +/* + * Class: gnu_java_nio_EpollSelectorImpl + * Method: epoll_create + * Signature: (I)I + */ +JNIEXPORT jint JNICALL +Java_gnu_java_nio_EpollSelectorImpl_epoll_1create (JNIEnv *env, + jclass c __attribute__((unused)), + jint size) +{ +#ifdef HAVE_EPOLL_CREATE + int fd = epoll_create (size); + +#ifdef TRACE_EPOLL + fprintf (stderr, "%s: epoll_create returns %d\n", __FUNCTION__, fd); +#endif /* TRACE_EPOLL */ + + if (fd == -1) + { + if (ENOSYS == errno) + JCL_ThrowException (env, "java/lang/InternalError", + strerror (errno)); + else + JCL_ThrowException (env, IO_EXCEPTION, strerror (errno)); + } + return fd; +#else + (void) size; + JCL_ThrowException (env, "java/lang/InternalError", "epoll support not available"); + return -1; +#endif /* HAVE_EPOLL_CREATE */ +} + +/* + * Class: gnu_java_nio_EpollSelectorImpl + * Method: epoll_add + * Signature: (III)V + */ +JNIEXPORT void JNICALL +Java_gnu_java_nio_EpollSelectorImpl_epoll_1add (JNIEnv *env, + jclass c __attribute__((unused)), + jint efd, jint fd, jint ops) +{ +#ifdef HAVE_EPOLL_CREATE + struct epoll_event event; + + memset (&event, 0, sizeof (struct epoll_event)); + + if ((ops & gnu_java_nio_EpollSelectorImpl_OP_ACCEPT) != 0 + || (ops & gnu_java_nio_EpollSelectorImpl_OP_READ) != 0) + event.events = EPOLLIN; + + if ((ops & gnu_java_nio_EpollSelectorImpl_OP_CONNECT) != 0 + || (ops & gnu_java_nio_EpollSelectorImpl_OP_WRITE) != 0) + event.events |= EPOLLOUT; + + event.data.fd = fd; + +#ifdef TRACE_EPOLL + fprintf (stderr, "%s: adding struct epoll_event { events: %o; data.fd: %d } to %d\n", + __FUNCTION__, event.events, event.data.fd, efd); +#endif /* TRACE_EPOLL */ + + if (epoll_ctl (efd, EPOLL_CTL_ADD, fd, &event) == -1) + { + if (ENOSYS == errno) + JCL_ThrowException (env, "java/lang/InternalError", + strerror (errno)); + else + JCL_ThrowException (env, IO_EXCEPTION, strerror (errno)); + } +#else + (void) efd; + (void) fd; + (void) ops; + JCL_ThrowException (env, "java/lang/InternalError", "epoll support not available"); +#endif /* HAVE_EPOLL_CREATE */ +} + + +/* + * Class: gnu_java_nio_EpollSelectorImpl + * Method: epoll_modify + * Signature: (III)V + */ +JNIEXPORT void JNICALL +Java_gnu_java_nio_EpollSelectorImpl_epoll_1modify (JNIEnv *env, + jclass c __attribute__((unused)), + jint efd, jint fd, jint ops) +{ +#ifdef HAVE_EPOLL_CREATE + struct epoll_event event; + + memset (&event, 0, sizeof (struct epoll_event)); + + if ((ops & gnu_java_nio_EpollSelectorImpl_OP_ACCEPT) != 0 + || (ops & gnu_java_nio_EpollSelectorImpl_OP_READ) != 0) + event.events = EPOLLIN; + + if ((ops & gnu_java_nio_EpollSelectorImpl_OP_CONNECT) != 0 + || (ops & gnu_java_nio_EpollSelectorImpl_OP_WRITE) != 0) + event.events |= EPOLLOUT; + + event.data.fd = fd; + +#ifdef TRACE_EPOLL + fprintf (stderr, "%s: modding struct epoll_event { events: %o; data.fd: %d } on %d\n", + __FUNCTION__, event.events, event.data.fd, efd); +#endif /* TRACE_EPOLL */ + + if (epoll_ctl (efd, EPOLL_CTL_MOD, fd, &event) == -1) + { + if (ENOSYS == errno) + JCL_ThrowException (env, "java/lang/InternalError", + strerror (errno)); + else + JCL_ThrowException (env, IO_EXCEPTION, strerror (errno)); + } +#else + (void) efd; + (void) fd; + (void) ops; + JCL_ThrowException (env, "java/lang/InternalError", "epoll support not available"); +#endif /* HAVE_EPOLL_CREATE */ +} + + +/* + * Class: gnu_java_nio_EpollSelectorImpl + * Method: epoll_delete + * Signature: (II)V + */ +JNIEXPORT void JNICALL +Java_gnu_java_nio_EpollSelectorImpl_epoll_1delete (JNIEnv *env, + jclass c __attribute__((unused)), + jint efd, jint fd) +{ +#ifdef HAVE_EPOLL_CREATE + struct epoll_event event; + + memset (&event, 0, sizeof (struct epoll_event)); + event.data.fd = fd; + +#ifdef TRACE_EPOLL + fprintf (stderr, "%s: delete events on fd %d for %d\n", __FUNCTION__, fd, efd); +#endif /* TRACE_EPOLL */ + + /* Older kernel versions require a non-null `event' parameter, + * even though it is ignored by this call. + */ + if (epoll_ctl (efd, EPOLL_CTL_DEL, fd, &event) == -1) + { + if (ENOSYS == errno) + JCL_ThrowException (env, "java/lang/InternalError", + strerror (errno)); + /* XXX the docs here seem a little strange. If `fd' is closed, + epoll_ctl returns EBADF; but the docs say that this happens + only when efd is invalid. Go figure. + */ + else if (ENOENT == errno || EBADF == errno) + return; /* fd is closed; it's already removed. */ + else + JCL_ThrowException (env, IO_EXCEPTION, strerror (errno)); + } +#else + (void) efd; + (void) fd; + JCL_ThrowException (env, "java/lang/InternalError", "epoll support not available"); +#endif /* HAVE_EPOLL_CREATE */ +} + +/* + * Class: gnu_java_nio_EpollSelectorImpl + * Method: epoll_wait + * Signature: (ILjava/nio/ByteBuffer;II)I + */ +JNIEXPORT jint JNICALL +Java_gnu_java_nio_EpollSelectorImpl_epoll_1wait (JNIEnv *env, + jclass c __attribute__((unused)), + jint efd, jobject nstate, + jint num_events, jint timeout) +{ +#ifdef HAVE_EPOLL_CREATE + void *p = (*env)->GetDirectBufferAddress (env, nstate); + struct epoll_event *events = (struct epoll_event *) p; + int ret; + + if (p == NULL) + { + if (!(*env)->ExceptionCheck (env)) + JCL_ThrowException (env, IO_EXCEPTION, "getting native state failed"); + return -1; + } + +#ifdef TRACE_EPOLL + fprintf (stderr, "%s: events: %p; num_events: %d; timeout: %d; efd: %d\n", + __FUNCTION__, p, num_events, timeout, efd); +#endif /* TRACE_EPOLL */ + + ret = epoll_wait (efd, events, num_events, timeout); + + if (ret == -1) + { + if (ENOSYS == errno) + JCL_ThrowException (env, "java/lang/InternalError", + strerror (errno)); + else if (EINTR == errno) + ret = 0; + else + JCL_ThrowException (env, IO_EXCEPTION, strerror (errno)); + } + +#ifdef TRACE_EPOLL + fprintf (stderr, " epoll_wait returns %d\n", ret); + { + int i; + for (i = 0; i < ret; i++) + { + fprintf (stderr, " [%4i]: events: %o; data.fd: %d\n", i, events[i].events, + events[i].data.fd); + } + } + fflush (stderr); +#endif /* TRACE_EPOLL */ + + return ret; +#else + (void) efd; + (void) nstate; + (void) num_events; + (void) timeout; + JCL_ThrowException (env, "java/lang/InternalError", "epoll support not available"); + return -1; +#endif /* HAVE_EPOLL_CREATE */ +} + + +/* + * Class: gnu_java_nio_EpollSelectorImpl + * Method: selected_fd + * Signature: (Ljava/nio/ByteBuffer;)I + */ +JNIEXPORT jint JNICALL +Java_gnu_java_nio_EpollSelectorImpl_selected_1fd (JNIEnv *env, + jclass c __attribute__((unused)), + jobject value) +{ +#ifdef HAVE_EPOLL_CREATE + void *p = (*env)->GetDirectBufferAddress (env, value); + struct epoll_event *event = (struct epoll_event *) p; + +#ifdef TRACE_EPOLL + fprintf (stderr, "%s: event: %p\n", __FUNCTION__, p); +#endif /* TRACE_EPOLL */ + + if (p == NULL) + { + if (!(*env)->ExceptionCheck (env)) + JCL_ThrowException (env, "java/lang/InternalError", + "getting native state failed"); + return -1; + } + +#ifdef TRACE_EPOLL + fprintf (stderr, " data.fd: %d\n", event->data.fd); + fflush (stderr); +#endif /* TRACE_EPOLL */ + + return event->data.fd; +#else + (void) value; + JCL_ThrowException (env, "java/lang/InternalError", "epoll support not available"); + return -1; +#endif /* HAVE_EPOLL_CREATE */ +} + + +/* + * Class: gnu_java_nio_EpollSelectorImpl + * Method: selected_ops + * Signature: (Ljava/nio/ByteBuffer;)I + */ +JNIEXPORT jint JNICALL +Java_gnu_java_nio_EpollSelectorImpl_selected_1ops (JNIEnv *env, + jclass c __attribute__((unused)), + jobject value) +{ +#ifdef HAVE_EPOLL_CREATE + void *p = (*env)->GetDirectBufferAddress (env, value); + struct epoll_event *event = (struct epoll_event *) p; + int ret = 0; + +#ifdef TRACE_EPOLL + fprintf (stderr, "%s: event: %p\n", __FUNCTION__, p); +#endif /* TRACE_EPOLL */ + + if (p == NULL) + { + if (!(*env)->ExceptionCheck (env)) + JCL_ThrowException (env, "java/lang/InternalError", + "getting native state failed"); + return -1; + } + + if ((event->events & EPOLLIN) != 0) + ret |= gnu_java_nio_EpollSelectorImpl_OP_ACCEPT | gnu_java_nio_EpollSelectorImpl_OP_READ; + if ((event->events & EPOLLOUT) != 0) + ret |= gnu_java_nio_EpollSelectorImpl_OP_CONNECT | gnu_java_nio_EpollSelectorImpl_OP_WRITE; + +#ifdef TRACE_EPOLL + fprintf (stderr, " events: %o\n", event->events); + fflush (stderr); +#endif /* TRACE_EPOLL */ + + return ret; +#else + (void) value; + JCL_ThrowException (env, "java/lang/InternalError", "epoll support not available"); + return -1; +#endif /* HAVE_EPOLL_CREATE */ +} diff --git a/libjava/classpath/native/jni/java-nio/gnu_java_nio_KqueueSelectorImpl.c b/libjava/classpath/native/jni/java-nio/gnu_java_nio_KqueueSelectorImpl.c new file mode 100644 index 000000000..94e6db7f8 --- /dev/null +++ b/libjava/classpath/native/jni/java-nio/gnu_java_nio_KqueueSelectorImpl.c @@ -0,0 +1,387 @@ +/* gnu_java_nio_channel_KqueueSelectorImpl.c -- + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is a part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at +your option) any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 +USA + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +#if HAVE_CONFIG_H +#include <config.h> +#endif /* HAVE_CONFIG_H */ + +#include <sys/types.h> +#if HAVE_SYS_EVENT_H +#include <sys/event.h> +#endif /* HAVE_SYS_EVENT_H */ +#include <sys/time.h> +#include <errno.h> +#include <string.h> +#include <unistd.h> + +#include <jni.h> +#include <gnu_java_nio_KqueueSelectorImpl.h> + +#include <jcl.h> + +#define KEY_OP_ACCEPT 16 +#define KEY_OP_CONNECT 8 +#define KEY_OP_READ 1 +#define KEY_OP_WRITE 4 + +/* XXX this requires -std=gnu99 or c99 */ +/* #ifdef TRACE_KQUEUE */ +/* #define TRACE(fmt, ...) fprintf (stderr, "%s: " fmt "\n", __FUNCTION__, __VA_ARGS__); */ +/* #else */ +/* #define TRACE(fmt, ...) */ +/* #endif */ + +/* #define TRACE_KQUEUE 1 */ + + +#define throw_not_supported(env) JCL_ThrowException (env, "java/lang/UnsupportedOperationException", "kqueue/kevent support not available") + + +/* + * Class: gnu_java_nio_KqueueSelectorImpl + * Method: kqueue_supported + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL +Java_gnu_java_nio_KqueueSelectorImpl_kqueue_1supported (JNIEnv *env __attribute__((unused)), + jclass clazz __attribute__((unused))) +{ +#if defined(HAVE_KQUEUE) && defined(HAVE_KEVENT) + return JNI_TRUE; +#else + return JNI_FALSE; +#endif /* HAVE_KQUEUE && HAVE_KEVENT */ +} + + +/* + * Class: gnu_java_nio_KqueueSelectorImpl + * Method: sizeof_struct_kevent + * Signature: ()I + */ +JNIEXPORT jint JNICALL +Java_gnu_java_nio_KqueueSelectorImpl_sizeof_1struct_1kevent +(JNIEnv *env __attribute__((unused)), jclass clazz __attribute__((unused))) +{ +#if defined(HAVE_KQUEUE) && defined(HAVE_KEVENT) +/* TRACE("return sizeof %lu", sizeof (struct kevent)); */ + return sizeof (struct kevent); +#else + throw_not_supported (env); + return -1; +#endif /* HAVE_KQUEUE && HAVE_KEVENT */ +} + + +/* + * Class: gnu_java_nio_KqueueSelectorImpl + * Method: implOpen + * Signature: ()I + */ +JNIEXPORT jint JNICALL +Java_gnu_java_nio_KqueueSelectorImpl_implOpen +(JNIEnv *env, jclass clazz __attribute__((unused))) +{ +#if defined(HAVE_KQUEUE) && defined(HAVE_KEVENT) + int kq = kqueue (); +/* TRACE("kqueue returns %d", kq); */ + if (kq == -1) + JCL_ThrowException (env, "java/io/IOException", strerror (errno)); + return kq; +#else + throw_not_supported (env); + return -1; +#endif +} + + +/* + * Class: gnu_java_nio_KqueueSelectorImpl + * Method: implClose + * Signature: (I)V + */ +JNIEXPORT void JNICALL +Java_gnu_java_nio_KqueueSelectorImpl_implClose (JNIEnv *env, + jclass clazz __attribute__((unused)), + jint kq) +{ +#if defined(HAVE_KQUEUE) && defined(HAVE_KEVENT) +/* TRACE("closing %d", kq); */ + if (close (kq) != 0) + JCL_ThrowException (env, "java/io/IOException", strerror (errno)); +#else + (void) kq; + throw_not_supported (env); +#endif /* HAVE_KQUEUE && HAVE_KEVENT */ +} + + +/* + * Class: gnu_java_nio_KqueueSelectorImpl + * Method: kevent_set + * Signature: (Ljava/nio/ByteBuffer;IIIZ)V + */ +JNIEXPORT void JNICALL +Java_gnu_java_nio_KqueueSelectorImpl_kevent_1set (JNIEnv *env, + jclass clazz __attribute__((unused)), + jobject nstate, jint i, jint fd, + jint ops, jint active, jint key) +{ +#if defined(HAVE_KQUEUE) && defined(HAVE_KEVENT) + struct kevent *kev; + short ident; + + kev = (struct kevent *) (*env)->GetDirectBufferAddress (env, nstate); + +#ifdef TRACE_KQUEUE + printf ("kevent_set fd:%d p:%p i:%d ops:%x active:%x key:%x\n", + fd, (void *) kev, i, ops, active, key); +#endif /* TRACE_KQUEUE */ + + if (kev == NULL) + { + JCL_ThrowException (env, "java/lang/InternalError", + "GetDirectBufferAddress returned NULL!"); + return; + } + + ident = fd; + memset (&kev[i], 0, sizeof (struct kevent)); + + if ((ops & KEY_OP_READ) || (ops & KEY_OP_ACCEPT)) + { + /* Add event if it wasn't previously added. */ + if (!(active & KEY_OP_READ) && !(active & KEY_OP_ACCEPT)) + EV_SET(&kev[i], ident, EVFILT_READ, EV_ADD, 0, 0, (void *) key); + } + else + { + /* Delete event if it was previously added */ + if ((active & KEY_OP_READ) || (active & KEY_OP_ACCEPT)) + EV_SET(&kev[i], ident, EVFILT_READ, EV_DELETE, 0, 0, (void *) key); + } + + /* Do the same thing for the write filter. */ + if ((ops & KEY_OP_WRITE) || (ops & KEY_OP_CONNECT)) + { + if (!(active & KEY_OP_WRITE) && !(active & KEY_OP_CONNECT)) + EV_SET(&kev[i], ident, EVFILT_WRITE, EV_ADD, 0, 0, (void *) key); + } + else + { + if ((active & KEY_OP_WRITE) || (active & KEY_OP_CONNECT)) + EV_SET(&kev[i], ident, EVFILT_WRITE, EV_DELETE, 0, 0, (void *) key); + } + +#ifdef TRACE_KQUEUE + printf (" set kevent %2d: ident:%u filter:%x flags:%o fflags:%o data:%p udata:%p\n", + i, (unsigned) kev[i].ident, kev[i].filter, kev[i].flags, kev[i].fflags, + (void *) kev[i].data, kev[i].udata); +#endif /* TRACE_KQUEUE */ +#else + (void) nstate; + (void) i; + (void) fd; + (void) ops; + (void) key; + (void) active; + throw_not_supported (env); +#endif /* HAVE_KQUEUE && HAVE_KEVENT */ +} + + +/* + * Class: gnu_java_nio_KqueueSelectorImpl + * Method: kevent + * Signature: (ILjava/nio/ByteBuffer;IJ)I + */ +JNIEXPORT jint JNICALL +Java_gnu_java_nio_KqueueSelectorImpl_kevent (JNIEnv *env, + jobject this __attribute__((unused)), + jint kq, jobject nstate, jint nevents, + jint maxevents, jlong timeout) +{ +#if defined(HAVE_KQUEUE) && defined(HAVE_KEVENT) + struct timespec tv; + struct timespec *t = NULL; + struct kevent *kev = (struct kevent *) (*env)->GetDirectBufferAddress (env, nstate); + int ret; + +#ifdef TRACE_KQUEUE + int i; + + printf ("[%d] kevent nevents:%d maxevents:%d timeout:%lld\n", kq, nevents, maxevents, timeout); + printf ("[%d] addding/deleting %d events\n", kq, nevents); + for (i = 0; i < nevents; i++) + { + printf ("[%d] kevent input [%d]: ident:%u filter:%x flags:%o fflags:%o data:%p udata:%p\n", + kq, i, (unsigned) kev[i].ident, kev[i].filter, kev[i].flags, kev[i].fflags, + (void *) kev[i].data, kev[i].udata); + } +#endif + +/* TRACE("events: %p; nevents: %d; timeout: %lld", (void *) kev, nevents, timeout); */ + + if (timeout != -1) + { + tv.tv_sec = timeout / 1000; + tv.tv_nsec = (timeout % 1000) * 1000; + t = &tv; + } + + ret = kevent (kq, (const struct kevent *) kev, nevents, kev, maxevents, t); + + if (ret == -1) + { + if (errno == EINTR) + ret = 0; + else + JCL_ThrowException (env, "java/io/IOException", strerror (errno)); + } + +#ifdef TRACE_KQUEUE + for (i = 0; i < ret; i++) + { + printf ("[%d] kevent output [%d]: ident:%u filter:%x flags:%o fflags:%o data:%p udata:%p\n", + kq, i, (unsigned) kev[i].ident, kev[i].filter, kev[i].flags, kev[i].fflags, + (void *) kev[i].data, kev[i].udata); + } +#endif + + return ret; +#else + (void) kq; + (void) nstate; + (void) nevents; + (void) maxevents; + (void) timeout; + throw_not_supported (env); + return -1; +#endif /* HAVE_KQUEUE && HAVE_KEVENT */ +} + + +/* + * Class: gnu_java_nio_KqueueSelectorImpl + * Method: fetch_key + * Signature: (Ljava/nio/ByteBuffer;)I; + */ +JNIEXPORT jint JNICALL +Java_gnu_java_nio_KqueueSelectorImpl_fetch_1key (JNIEnv *env, + jclass clazz __attribute__((unused)), + jobject nstate) +{ +#if defined(HAVE_KQUEUE) && defined(HAVE_KEVENT) + struct kevent *kev = (struct kevent *) (*env)->GetDirectBufferAddress (env, nstate); +/* TRACE("return key %p\n", kev->udata); */ + return (jint) kev->udata; +#else + (void) nstate; + throw_not_supported (env); + return -1; +#endif /* HAVE_KQUEUE && HAVE_KEVENT */ +} + + +/* + * Class: gnu_java_nio_KqueueSelectorImpl + * Method: ready_ops + * Signature: (Ljava/nio/ByteBuffer;I)I + */ +JNIEXPORT jint JNICALL +Java_gnu_java_nio_KqueueSelectorImpl_ready_1ops (JNIEnv *env, + jclass clazz __attribute__((unused)), + jobject nstate, jint interest) +{ +#if defined(HAVE_KQUEUE) && defined(HAVE_KEVENT) + struct kevent *kev = (struct kevent *) (*env)->GetDirectBufferAddress (env, nstate); + jint ready = 0; + + if ((kev->flags & EV_ERROR) == EV_ERROR) + { + printf ("!!! error selecting fd %d: %s", (int) (kev->ident), strerror ((int) (kev->data))); + return 0; + } + + /* We poll for READ for OP_READ and OP_ACCEPT. */ + if (kev->filter == EVFILT_READ) + { + ready = (interest & KEY_OP_READ) | (interest & KEY_OP_ACCEPT); +/* TRACE("filter EVFILT_READ. Ready ops set to %x", ready); */ + } + + /* Poll for WRITE for OP_WRITE and OP_CONNECT; I guess we *should* + get a WRITE event if we are connected, but I don't know if we do + for real. FIXME */ + if (kev->filter == EVFILT_WRITE) + { + ready = (interest & KEY_OP_WRITE) | (interest & KEY_OP_CONNECT); +/* TRACE("filter EVFILT_WRITE. Ready ops set to %x", ready); */ + } + + return ready; +#else + (void) nstate; + (void) interest; + throw_not_supported (env); + return -1; +#endif /* HAVE_KQUEUE && HAVE_KEVENT */ +} + + +/* + * Class: gnu_java_nio_KqueueSelectorImpl + * Method: check_eof + * Signature: (Ljava/nio/ByteBuffer;)Z + */ +JNIEXPORT jboolean JNICALL +Java_gnu_java_nio_KqueueSelectorImpl_check_1eof (JNIEnv *env, + jclass clazz __attribute__((unused)), + jobject nstate) +{ +#if defined(HAVE_KQUEUE) && defined(HAVE_KEVENT) + struct kevent *kev = (struct kevent *) (*env)->GetDirectBufferAddress (env, nstate); + if ((kev->flags & EV_EOF) == EV_EOF) + return JNI_TRUE; + return JNI_FALSE; +#else + (void) nstate; + throw_not_supported (env); + return JNI_FALSE; +#endif +} diff --git a/libjava/classpath/native/jni/java-nio/gnu_java_nio_VMChannel.c b/libjava/classpath/native/jni/java-nio/gnu_java_nio_VMChannel.c new file mode 100644 index 000000000..7899f0b94 --- /dev/null +++ b/libjava/classpath/native/jni/java-nio/gnu_java_nio_VMChannel.c @@ -0,0 +1,2035 @@ +/* gnu_java_nio_VMChannel.c - + Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <config-int.h> + +#include <sys/types.h> +#ifdef HAVE_SYS_MMAN_H +#include <sys/mman.h> +#endif +#include <sys/socket.h> +#include <sys/stat.h> +#include <sys/uio.h> + +#include <netinet/in.h> + +#include <stdlib.h> +#include <errno.h> +#include <unistd.h> +#include <string.h> + +#include <jni.h> +#include <jcl.h> + +#include "cpio.h" +#include "gnu_java_nio_VMChannel.h" +#include "javanio.h" + +#ifdef HAVE_FCNTL_H +#include <fcntl.h> +#endif /* HAVE_FCNTL_H */ + +#if defined(HAVE_SYS_IOCTL_H) +#define BSD_COMP /* Get FIONREAD on Solaris2 */ +#include <sys/ioctl.h> +#endif +#if defined(HAVE_SYS_FILIO_H) /* Get FIONREAD on Solaris 2.5 */ +#include <sys/filio.h> +#endif + +#define CONNECT_EXCEPTION "java/net/ConnectException" +#define IO_EXCEPTION "java/io/IOException" +#define SOCKET_EXCEPTION "java/net/SocketException" +#define INTERRUPTED_IO_EXCEPTION "java/io/InterruptedIOException" +#define NON_READABLE_CHANNEL_EXCEPTION "java/nio/channels/NonReadableChannelException" +#define NON_WRITABLE_CHANNEL_EXCEPTION "java/nio/channels/NonWritableChannelException" +#define SOCKET_TIMEOUT_EXCEPTION "java/net/SocketTimeoutException" + +/* Align a value up or down to a multiple of the pagesize. */ +#define ALIGN_DOWN(p,s) ((p) - ((p) % (s))) +#define ALIGN_UP(p,s) ((p) + ((s) - ((p) % (s)))) + +/* + * Limit to maximum of 16 buffers + */ +#define JCL_IOV_MAX 16 + +#ifdef __cplusplus +extern "C" +{ +#endif + +enum JCL_buffer_type { DIRECT, HEAP, ARRAY, UNKNOWN }; + +struct JCL_buffer +{ + enum JCL_buffer_type type; + jbyte *ptr; + jint offset; + jint position; + jint limit; + jint count; +}; + +jmethodID get_method_id(JNIEnv *, jclass, const char *, const char *); +void JCL_print_buffer(JNIEnv *, struct JCL_buffer *); +int JCL_init_buffer(JNIEnv *, struct JCL_buffer *, jobject); +void JCL_release_buffer(JNIEnv *, struct JCL_buffer *, jobject, jint); +void JCL_cleanup_buffers(JNIEnv *, struct JCL_buffer *, jint, jobjectArray, jint, jlong); +int JCL_thread_interrupted(JNIEnv *); + +static jfieldID address_fid; +static jmethodID get_position_mid; +static jmethodID set_position_mid; +static jmethodID get_limit_mid; +static jmethodID set_limit_mid; +static jmethodID has_array_mid; +static jmethodID array_mid; +static jmethodID array_offset_mid; +static jmethodID thread_interrupted_mid; +static jclass vm_channel_class; + +jmethodID +get_method_id(JNIEnv *env, jclass clazz, const char *name, + const char *sig) +{ + jmethodID mid = (*env)->GetMethodID(env, clazz, name, sig); +/* NIODBG("name: %s; sig: %s", name, sig); */ + if (mid == NULL) + { + JCL_ThrowException(env, "java/lang/InternalError", name); + return NULL; + } + + return mid; +} + +inline void +JCL_print_buffer(JNIEnv *env __attribute__((__unused__)), struct JCL_buffer *buf) +{ + fprintf (stderr, "Buffer - type: %d, ptr: %p\n", buf->type, buf->ptr); +} + + +int +JCL_init_buffer(JNIEnv *env, struct JCL_buffer *buf, jobject bbuf) +{ + void *addr = (*env)->GetDirectBufferAddress (env, bbuf); + +/* NIODBG("buf: %p; bbuf: %p; addr: %p", (void *) buf, bbuf, addr); */ + + buf->position = (*env)->CallIntMethod(env, bbuf, get_position_mid); + buf->limit = (*env)->CallIntMethod(env, bbuf, get_limit_mid); + buf->offset = 0; + buf->count = 0; + buf->type = UNKNOWN; + + if (addr != NULL) + { + buf->ptr = (jbyte *) addr; + buf->type = DIRECT; + } + else + { + jboolean has_array; + has_array = (*env)->CallBooleanMethod(env, bbuf, has_array_mid); + + if (has_array == JNI_TRUE) + { + jbyteArray arr; + buf->offset = (*env)->CallIntMethod(env, bbuf, array_offset_mid); + arr = (*env)->CallObjectMethod(env, bbuf, array_mid); + buf->ptr = (*env)->GetByteArrayElements(env, arr, 0); + buf->type = ARRAY; + (*env)->DeleteLocalRef(env, arr); + } + else + { + jobject address = (*env)->GetObjectField (env, bbuf, address_fid); + if (address == NULL) + return -1; /* XXX handle non-array, non-native buffers? */ + buf->ptr = (jbyte *) JCL_GetRawData(env, address); + buf->type = HEAP; + (*env)->DeleteLocalRef(env, address); + } + } + + return 0; +} + +void +JCL_release_buffer(JNIEnv *env, struct JCL_buffer *buf, jobject bbuf, + jint action) +{ + jbyteArray arr; + +/* NIODBG("buf: %p; bbuf: %p; action: %x", (void *) buf, bbuf, action); */ + + /* Set the position to the appropriate value */ + if (buf->count > 0) + { + jobject bbufTemp; + bbufTemp = (*env)->CallObjectMethod(env, bbuf, set_position_mid, + buf->position + buf->count); + (*env)->DeleteLocalRef(env, bbufTemp); + } + + switch (buf->type) + { + case DIRECT: + case HEAP: + break; + case ARRAY: + arr = (*env)->CallObjectMethod(env, bbuf, array_mid); + (*env)->ReleaseByteArrayElements(env, arr, buf->ptr, action); + (*env)->DeleteLocalRef(env, arr); + break; + case UNKNOWN: + /* TODO: Handle buffers that are not direct or array backed */ + break; + } +} + +void +JCL_cleanup_buffers(JNIEnv *env, + struct JCL_buffer *bi_list, + jint vec_len, + jobjectArray bbufs, + jint offset, + jlong num_bytes) +{ + jint i; + +/* NIODBG("bi_list: %p; vec_len: %d; bbufs: %p; offset: %d; num_bytes: %lld", */ +/* (void *) bi_list, vec_len, bbufs, offset, num_bytes); */ + + /* Update all of the bbufs with the approriate information */ + for (i = 0; i < vec_len; i++) + { + struct JCL_buffer* buf; + jobject bbuf; + + buf = &bi_list[i]; + bbuf = (*env)->GetObjectArrayElement(env, bbufs, offset + i); + + if (num_bytes > (buf->limit - buf->position)) + buf->count = (buf->limit - buf->position); + else + buf->count = num_bytes; + + num_bytes -= buf->count; + + JCL_release_buffer(env, buf, bbuf, JNI_ABORT); + (*env)->DeleteLocalRef(env, bbuf); + } +} + + +int +JCL_thread_interrupted(JNIEnv *env) +{ + return (int) (*env)->CallStaticBooleanMethod(env, vm_channel_class, + thread_interrupted_mid); +} + + +/* + * Class: gnu_java_nio_VMChannel + * Method: stdin_fd + * Signature: ()I + */ +JNIEXPORT jint JNICALL +Java_gnu_java_nio_VMChannel_stdin_1fd (JNIEnv *env __attribute__((unused)), + jclass c __attribute__((unused))) +{ +/* NIODBG("%d", fileno (stdin)); */ + return fileno (stdin); +} + + +/* + * Class: gnu_java_nio_VMChannel + * Method: stdout_fd + * Signature: ()I + */ +JNIEXPORT jint JNICALL +Java_gnu_java_nio_VMChannel_stdout_1fd (JNIEnv *env __attribute__((unused)), + jclass c __attribute__((unused))) +{ +/* NIODBG("%d", fileno (stdout)); */ + return fileno (stdout); +} + + +/* + * Class: gnu_java_nio_VMChannel + * Method: stderr_fd + * Signature: ()I + */ +JNIEXPORT jint JNICALL +Java_gnu_java_nio_VMChannel_stderr_1fd (JNIEnv *env __attribute__((unused)), + jclass c __attribute__((unused))) +{ +/* NIODBG("%d", fileno (stderr)); */ + return fileno (stderr); +} + + +JNIEXPORT void JNICALL +Java_gnu_java_nio_VMChannel_initIDs (JNIEnv *env, + jclass clazz) +{ + jclass bufferClass = JCL_FindClass(env, "java/nio/Buffer"); + jclass byteBufferClass = JCL_FindClass(env, "java/nio/ByteBuffer"); + +/* NIODBG("%s", "..."); */ + + address_fid = (*env)->GetFieldID(env, bufferClass, "address", + "Lgnu/classpath/Pointer;"); + if (address_fid == NULL) + { + JCL_ThrowException(env, "java/lang/InternalError", + "Unable to find internal field"); + return; + } + + get_position_mid = get_method_id(env, bufferClass, "position", "()I"); + set_position_mid = get_method_id(env, bufferClass, "position", + "(I)Ljava/nio/Buffer;"); + get_limit_mid = get_method_id(env, bufferClass, "limit", "()I"); + set_limit_mid = get_method_id(env, bufferClass, "limit", + "(I)Ljava/nio/Buffer;"); + has_array_mid = get_method_id(env, byteBufferClass, "hasArray", "()Z"); + array_mid = get_method_id(env, byteBufferClass, "array", "()[B"); + array_offset_mid = get_method_id(env, byteBufferClass, "arrayOffset", "()I"); + + vm_channel_class = clazz; + thread_interrupted_mid = (*env)->GetStaticMethodID(env, clazz, + "isThreadInterrupted", + "()Z"); +} + +JNIEXPORT void JNICALL +Java_gnu_java_nio_VMChannel_setBlocking (JNIEnv *env, + jobject o __attribute__ ((__unused__)), + jint fd, + jboolean blocking) +{ + int opts; + +/* NIODBG("fd: %d; blocking: %d", fd, blocking); */ + + opts = fcntl(fd, F_GETFL); + if (opts < 0) + { + JCL_ThrowException(env, IO_EXCEPTION, + "Failed to get flags for file desriptor"); + return; + } + + if (blocking == JNI_TRUE) + opts &= ~(O_NONBLOCK); + else + opts |= O_NONBLOCK; + + opts = fcntl(fd, F_SETFL, opts); + + if (opts < 0) + { + JCL_ThrowException(env, IO_EXCEPTION, + "Failed to set flags for file desriptor"); + return; + } +} + +/* Return true if fd is in non-blocking mode. */ +static jboolean +is_non_blocking_fd(jint fd) +{ + int opts; + opts = fcntl(fd, F_GETFL); + if (opts == -1) + { + /* Assume blocking on error. */ + return 0; + } + return (opts & O_NONBLOCK) != 0; +} + +JNIEXPORT jint JNICALL +Java_gnu_java_nio_VMChannel_read__ILjava_nio_ByteBuffer_2 (JNIEnv *env, + jobject o __attribute__ ((__unused__)), + jint fd, + jobject bbuf) +{ +#ifdef HAVE_READ + jint len; + ssize_t result; + struct JCL_buffer buf; + int tmp_errno; + +/* NIODBG("fd: %d; bbuf: %p", fd, bbuf); */ + + if (JCL_init_buffer(env, &buf, bbuf) < 0) + { + /* TODO: Rethrown exception */ + JCL_ThrowException (env, IO_EXCEPTION, "Buffer initialisation failed"); + return -1; + } + + len = buf.limit - buf.position; + + if (len == 0) + { + JCL_release_buffer (env, &buf, bbuf, JNI_ABORT); + return 0; + } + + do + { + result = cpnio_read (fd, &(buf.ptr[buf.position + buf.offset]), len); + tmp_errno = errno; + } + while (result == -1 && errno == EINTR && ! JCL_thread_interrupted(env)); + errno = tmp_errno; + + if (result == 0) + { + result = -1; + buf.count = 0; + } + else if (result == -1) + { + buf.count = 0; + if (errno == EAGAIN) + { + if (is_non_blocking_fd(fd)) + { + /* Non-blocking */ + result = 0; + } + else + { + /* Read timeout on a socket with SO_RCVTIMEO != 0. */ + JCL_release_buffer(env, &buf, bbuf, JNI_ABORT); + JCL_ThrowException(env, SOCKET_TIMEOUT_EXCEPTION, "read timed out"); + return -1; + } + } + else if (errno == EBADF) /* Bad fd */ + { + JCL_release_buffer(env, &buf, bbuf, JNI_ABORT); + JCL_ThrowException (env, NON_READABLE_CHANNEL_EXCEPTION, + strerror(errno)); + return -1; + } + else if (EINTR == errno) /* read interrupted */ + { + JCL_release_buffer(env, &buf, bbuf, JNI_ABORT); + JCL_ThrowException(env, INTERRUPTED_IO_EXCEPTION, strerror (errno)); + return -1; + } + else + { + JCL_release_buffer(env, &buf, bbuf, JNI_ABORT); + JCL_ThrowException (env, IO_EXCEPTION, strerror(errno)); + return -1; + } + } + else + buf.count = result; + + JCL_release_buffer(env, &buf, bbuf, 0); + + return result; +#else + (void) fd; + (void) bbuf; + JCL_ThrowException (env, IO_EXCEPTION, "read not supported"); + return -1; +#endif /* HAVE_READ */ +} + +JNIEXPORT jint JNICALL +Java_gnu_java_nio_VMChannel_write__ILjava_nio_ByteBuffer_2 (JNIEnv *env, + jobject o __attribute__ ((__unused__)), + jint fd, + jobject bbuf) +{ +#ifdef HAVE_WRITE + jint len; + ssize_t result; + struct JCL_buffer buf; + int tmp_errno; + +/* NIODBG("fd: %d; bbuf: %p", fd, bbuf); */ + + if (JCL_init_buffer(env, &buf, bbuf) < 0) + { + /* TODO: Rethrown exception */ + JCL_ThrowException (env, IO_EXCEPTION, "Buffer initialisation failed"); + return -1; + } + + len = buf.limit - buf.position; + + if (len == 0) + { + JCL_release_buffer (env, &buf, bbuf, JNI_ABORT); + return 0; + } + + do + { + result = cpnio_write (fd, &(buf.ptr[buf.position + buf.offset]), len); + tmp_errno = errno; + } + while (result == -1 && errno == EINTR && ! JCL_thread_interrupted(env)); + errno = tmp_errno; + + buf.count = result; + + if (result == -1) + { + if (errno == EAGAIN) /* Non-blocking */ + { + result = 0; + } + else + { + JCL_release_buffer(env, &buf, bbuf, JNI_ABORT); + JCL_ThrowException(env, IO_EXCEPTION, strerror(errno)); + return -1; + } + } + + JCL_release_buffer(env, &buf, bbuf, JNI_ABORT); + + return result; +#else + (void) fd; + (void) bbuf; + JCL_ThrowException (env, IO_EXCEPTION, "write not supported"); + return -1; +#endif /* HAVE_WRITE */ +} + + +/* + * Implementation of a scattering read. Will use the appropriate + * vector based read call (currently readv on Linux). + * + * This has a limit to the number of buffers that will be read. It + * will not make muliple readv calls. This is to ensure that operations + * are atomic. Currently it is limited to 16 buffers. This is for + * compatibiliy with Sun. + */ +JNIEXPORT jlong JNICALL +Java_gnu_java_nio_VMChannel_readScattering (JNIEnv *env, + jobject o __attribute__ ((__unused__)), + jint fd, + jobjectArray bbufs, + jint offset, + jint length) +{ + jint i; +/* jboolean is_error = JNI_FALSE; */ +/* char *error_msg; */ + struct iovec buffers[JCL_IOV_MAX]; + struct JCL_buffer bi_list[JCL_IOV_MAX]; + ssize_t result; + jint vec_len = length < JCL_IOV_MAX ? length : JCL_IOV_MAX; + jlong bytes_read = 0; + int tmp_errno; + +/* NIODBG("fd: %d; bbufs: %p; offset: %d; length: %d", */ +/* fd, bbufs, offset, length); */ + + /* Build the vector of buffers to read into */ + for (i = 0; i < vec_len; i++) + { + struct JCL_buffer* buf; + jobject bbuf; + + buf = &bi_list[i]; + bbuf = (*env)->GetObjectArrayElement(env, bbufs, offset + i); + + JCL_init_buffer(env, buf, bbuf); + +/* JCL_print_buffer (env, buf); */ + + buffers[i].iov_base = &(buf->ptr[buf->position + buf->offset]); + buffers[i].iov_len = buf->limit - buf->position; + (*env)->DeleteLocalRef(env, bbuf); + } + + /* Work the scattering magic */ + do + { + result = cpnio_readv (fd, buffers, vec_len); + tmp_errno = errno; + } + while (result == -1 && errno == EINTR && ! JCL_thread_interrupted(env)); + errno = tmp_errno; + bytes_read = (jlong) result; + + /* Handle the response */ + if (result < 0) + { + if (errno == EAGAIN) + { + if (is_non_blocking_fd(fd)) + { + /* Non-blocking */ + result = 0; + } + else + { + /* Read timeout on a socket with SO_RCVTIMEO != 0. */ + JCL_cleanup_buffers(env, bi_list, vec_len, bbufs, offset, bytes_read); + JCL_ThrowException(env, SOCKET_TIMEOUT_EXCEPTION, "read timed out"); + return -1; + } + } + else if (errno == EBADF) /* Bad fd */ + { + JCL_cleanup_buffers(env, bi_list, vec_len, bbufs, offset, bytes_read); + JCL_ThrowException (env, NON_READABLE_CHANNEL_EXCEPTION, + strerror(errno)); + return -1; + } + else + { + JCL_cleanup_buffers(env, bi_list, vec_len, bbufs, offset, bytes_read); + JCL_ThrowException (env, IO_EXCEPTION, strerror(errno)); + return -1; + } + bytes_read = 0; + } + else if (result == 0) /* EOF */ + { + result = -1; + } + + JCL_cleanup_buffers(env, bi_list, vec_len, bbufs, offset, bytes_read); + + return (jlong) result; +} + + +/* + * Implementation of a gathering write. Will use the appropriate + * vector based read call (currently readv on Linux). + * + * This has a limit to the number of buffers that will be read. It + * will not make muliple readv calls. This is to ensure that operations + * are atomic. Currently it is limited to 16 buffers. This is for + * compatibiliy with Sun. + */ +JNIEXPORT jlong JNICALL +Java_gnu_java_nio_VMChannel_writeGathering (JNIEnv *env, + jobject o __attribute__ ((__unused__)), + jint fd, + jobjectArray bbufs, + jint offset, + jint length) +{ + int i; +/* jboolean is_error = JNI_FALSE; */ +/* char *error_msg; */ + struct iovec buffers[JCL_IOV_MAX]; + struct JCL_buffer bi_list[JCL_IOV_MAX]; + ssize_t result; + jint vec_len = length < JCL_IOV_MAX ? length : JCL_IOV_MAX; + jlong bytes_written; + int tmp_errno; + +/* NIODBG("fd: %d; bbufs: %p; offset: %d; length: %d", */ +/* fd, bbufs, offset, length); */ + + /* Build the vector of buffers to read into */ + for (i = 0; i < vec_len; i++) + { + struct JCL_buffer* buf; + jobject bbuf; + + buf = &bi_list[i]; + bbuf = (*env)->GetObjectArrayElement(env, bbufs, offset + i); + + JCL_init_buffer(env, buf, bbuf); + +/* JCL_print_buffer(env, buf); */ + + buffers[i].iov_base = &(buf->ptr[buf->position + buf->offset]); + buffers[i].iov_len = buf->limit - buf->position; + (*env)->DeleteLocalRef(env, bbuf); + } + + /* Work the gathering magic */ + do + { + result = cpnio_writev (fd, buffers, vec_len); + tmp_errno = errno; + } + while (result == -1 && tmp_errno == EINTR && ! JCL_thread_interrupted(env)); + errno = tmp_errno; + + bytes_written = (jlong) result; + + if (result < 0) + { + bytes_written = 0; + if (errno == EAGAIN) /* Non blocking */ + result = 0; + else if (errno == EBADF) /* Bad fd */ + { + JCL_cleanup_buffers(env, bi_list, vec_len, bbufs, offset, + bytes_written); + JCL_ThrowException (env, NON_WRITABLE_CHANNEL_EXCEPTION, + strerror(errno)); + return -1; + } + else + { + JCL_cleanup_buffers(env, bi_list, vec_len, bbufs, offset, + bytes_written); + JCL_ThrowException (env, IO_EXCEPTION, strerror(errno)); + return -1; + } + } + else if (result == 0) /* EOF?? Does this happen on a write */ + result = -1; + + JCL_cleanup_buffers(env, bi_list, vec_len, bbufs, offset, bytes_written); + return (jlong) result; +} + + +/* + * Class: gnu_java_nio_VMChannel + * Method: receive + * Signature: (Ljava/nio/ByteBuffer;Ljava/nio/ByteBuffer;)I + */ +JNIEXPORT jint JNICALL +Java_gnu_java_nio_VMChannel_receive (JNIEnv *env, + jclass c __attribute__((unused)), + jint fd, jobject dst, jobject addrPort) +{ +#ifdef HAVE_RECVFROM + char *addrPortPtr = (*env)->GetDirectBufferAddress (env, addrPort); + struct JCL_buffer buf; +#ifdef HAVE_INET6 + struct sockaddr_in6 sock_storage; + struct sockaddr_in6 *sock6; + socklen_t slen = sizeof (struct sockaddr_in6); +#else + struct sockaddr_in sock_storage; + socklen_t slen = sizeof (struct sockaddr_in); +#endif /* HAVE_INET6 */ + struct sockaddr *sockaddr = (struct sockaddr *) &sock_storage; + struct sockaddr_in *sock4; + int ret; + jint result = -1; + + if (JCL_init_buffer (env, &buf, dst) == -1) + JCL_ThrowException (env, IO_EXCEPTION, "loading buffer failed"); + +#ifndef HAVE_MSG_WAITALL +#define MSG_WAITALL 0 +#endif + + ret = cpnio_recvfrom (fd, &(buf.ptr[buf.position + buf.offset]), + buf.limit - buf.position, MSG_WAITALL, + sockaddr, &slen); + + if (-1 == ret) + { + JCL_release_buffer (env, &buf, dst, JNI_ABORT); + if (EINTR == errno) + JCL_ThrowException (env, "java/io/InterruptedIOException", strerror (errno)); + else if (EAGAIN == errno) + { + /* If the socket is in blocking mode, our timeout expired. */ + int val = fcntl (fd, F_GETFL, 0); + if (val == -1) + JCL_ThrowException (env, IO_EXCEPTION, strerror (errno)); + else if ((val & O_NONBLOCK) == 0) + JCL_ThrowException (env, "java/net/SocketTimeoutException", + "read timed out"); + } + else + JCL_ThrowException (env, IO_EXCEPTION, strerror (errno)); + return 0; + } + + if (sockaddr->sa_family == AF_INET) + { + sock4 = (struct sockaddr_in *) sockaddr; + memcpy (addrPortPtr, &(sock4->sin_addr.s_addr), 4); + ;memcpy (addrPortPtr + 4, &(sock4->sin_port), 2); + result = 4; + } +#ifdef HAVE_INET6 + else if (sockaddr->sa_family == AF_INET6) + { + sock6 = (struct sockaddr_in6 *) sockaddr; + memcpy (addrPortPtr, &(sock6->sin6_addr.s6_addr), 16); + memcpy (addrPortPtr + 16, &(sock6->sin6_port), 2); + result = 16; + } +#endif /* HAVE_INET6 */ + else if (ret == 0) + { + result = 0; + } + else + { + JCL_ThrowException (env, "java/net/SocketException", + "unsupported address type returned"); + } + + buf.count += ret; + JCL_release_buffer (env, &buf, dst, 0); + return result; +#else + (void) fd; + (void) dst; + (void) addrPort; + JCL_ThrowException (env, IO_EXCEPTION, "recvfrom not supported"); +#endif /* HAVE_RECVFROM */ +} + + +/* + * Class: gnu_java_nio_VMChannel + * Method: send + * Signature: (Ljava/nio/ByteBuffer;[BI)I + */ +JNIEXPORT jint JNICALL +Java_gnu_java_nio_VMChannel_send (JNIEnv *env, + jclass c __attribute__((unused)), + int fd, jobject src, jbyteArray addr, jint port) +{ +#ifdef HAVE_SENDTO + struct sockaddr_in sockaddr; + jbyte *elems; + struct JCL_buffer buf; + int ret; + +/* NIODBG("fd: %d; src: %p; addr: %p; port: %d", */ +/* fd, src, addr, port); */ + + if (JCL_init_buffer (env, &buf, src) == -1) + { + JCL_ThrowException (env, IO_EXCEPTION, "loading buffer failed"); + return -1; + } + +/* JCL_print_buffer (env, &buf); */ + + elems = (*env)->GetByteArrayElements (env, addr, NULL); + + sockaddr.sin_family = AF_INET; + sockaddr.sin_addr.s_addr = *((uint32_t *) elems); + sockaddr.sin_port = htons (port); + + do + { + ret = cpnio_sendto (fd, &(buf.ptr[buf.position + buf.offset]), + buf.limit - buf.position, + 0, (const struct sockaddr *) &sockaddr, + sizeof (struct sockaddr_in)); + } + while (-1 == ret && EINTR == errno); + + (*env)->ReleaseByteArrayElements (env, addr, elems, JNI_ABORT); + + if (-1 == ret) + { + if (errno != EAGAIN) + JCL_ThrowException (env, IO_EXCEPTION, strerror (errno)); + JCL_release_buffer (env, &buf, src, JNI_ABORT); + return 0; + } + + buf.count += ret; + JCL_release_buffer (env, &buf, src, JNI_ABORT); + return ret; +#else + (void) fd; + (void) src; + (void) addr; + (void) port; +#endif /* HAVE_SENDTO */ +} + + +/* + * Class: gnu_java_nio_VMChannel + * Method: send6 + * Signature: (Ljava/nio/ByteBuffer;[BI)I + */ +JNIEXPORT jint JNICALL +Java_gnu_java_nio_VMChannel_send6 (JNIEnv *env, + jclass c __attribute__((unused)), + int fd, jobject src, jbyteArray addr, jint port) +{ +#if defined(HAVE_SENDTO) && defined(HAVE_INET6) + struct sockaddr_in6 sockaddr; + jbyte *elems; + struct JCL_buffer buf; + int ret; + +/* NIODBG("fd: %d; src: %p; addr: %p; port: %d", */ +/* fd, src, addr, port); */ + + if (JCL_init_buffer (env, &buf, src) == -1) + { + JCL_ThrowException (env, IO_EXCEPTION, "loading buffer failed"); + return -1; + } + +/* JCL_print_buffer (env, &buf); */ + + elems = (*env)->GetByteArrayElements (env, addr, NULL); + + sockaddr.sin6_family = AF_INET6; + memcpy (&sockaddr.sin6_addr.s6_addr, elems, 16); + sockaddr.sin6_port = htons (port); + + do + { + ret = cpnio_sendto (fd, (const void *) (buf.ptr + buf.offset), + buf.limit - buf.position, + 0, (const struct sockaddr *) &sockaddr, + sizeof (struct sockaddr_in6)); + } + while (-1 == ret && EINTR == errno); + + (*env)->ReleaseByteArrayElements (env, addr, elems, JNI_ABORT); + + if (-1 == ret) + { + if (errno != EAGAIN) + JCL_ThrowException (env, IO_EXCEPTION, strerror (errno)); + JCL_release_buffer (env, &buf, src, JNI_ABORT); + return 0; + } + + buf.count += ret; + JCL_release_buffer (env, &buf, src, JNI_ABORT); + return ret; +#else + (void) fd; + (void) src; + (void) addr; + (void) port; + JCL_ThrowException (env, IO_EXCEPTION, "IPv6 sendto not supported"); + return -1; +#endif /* HAVE_SENDTO && HAVE_INET6 */ +} + + +/* + * Class: gnu_java_nio_VMChannel + * Method: read + * Signature: (I)I + */ +JNIEXPORT jint JNICALL +Java_gnu_java_nio_VMChannel_read__I (JNIEnv *env, + jclass c __attribute__((unused)), + jint fd) +{ +#ifdef HAVE_READ + char in; + int ret; + int tmp_errno; + +/* NIODBG("fd: %d", fd); */ + + do + { + ret = cpnio_read (fd, &in, 1); + tmp_errno = errno; + } + while (ret == -1 && errno == EINTR && ! JCL_thread_interrupted(env)); + errno = tmp_errno; + + if (-1 == ret) + { + if (errno == EAGAIN && !is_non_blocking_fd(fd)) + { + /* Read timeout on a socket with SO_RCVTIMEO != 0. */ + JCL_ThrowException(env, SOCKET_TIMEOUT_EXCEPTION, "read timed out"); + } + else + JCL_ThrowException (env, IO_EXCEPTION, strerror (errno)); + return -1; + } + + if (0 == ret) + return -1; + + return (in & 0xFF); +#else + (void) fd; + JCL_ThrowException (env, IO_EXCEPTION, "read not supported"); +#endif /* HAVE_READ */ +} + + +/* + * Class: gnu_java_nio_VMChannel + * Method: write + * Signature: (I)V + */ +JNIEXPORT void JNICALL +Java_gnu_java_nio_VMChannel_write__II (JNIEnv *env, + jclass c __attribute__((unused)), + jint fd, jint data) +{ +#ifdef HAVE_WRITE + char out = (char) data; + int ret; + int tmp_errno; + +/* NIODBG("fd: %d; data: %d", fd, data); */ + + do + { + ret = cpnio_write (fd, &out, 1); + tmp_errno = errno; + } + while (ret == -1 && errno == EINTR && ! JCL_thread_interrupted(env)); + errno = tmp_errno; + + if (-1 == ret) + JCL_ThrowException(env, IO_EXCEPTION, strerror (errno)); +#else + (void) fd; + (void) data; + JCL_ThrowException (env, IO_EXCEPTION, "write not supported"); +#endif /* HAVE_WRITE */ +} + + +/* + * Class: gnu_java_nio_VMChannel + * Method: socket + * Signature: (Z)I + */ +JNIEXPORT jint JNICALL +Java_gnu_java_nio_VMChannel_socket (JNIEnv *env, jclass clazz __attribute__((unused)), + jboolean stream) +{ +#ifdef HAVE_SOCKET + int ret; + + do + { + ret = cpnio_socket (AF_INET, stream ? SOCK_STREAM : SOCK_DGRAM, 0); + } + while (-1 == ret && EINTR == errno); + + if (ret == -1) + JCL_ThrowException (env, "java/net/SocketException", strerror (errno)); +/* NIODBG("created socket %d", ret); */ + + return ret; +#else + (void) stream; + JCL_ThrowException (env, IO_EXCEPTION, "socket not supported"); + return -1; +#endif /* HAVE_SOCKET */ +} + + +/* + * Class: gnu_java_nio_VMChannel + * Method: connect + * Signature: (I[BI)Z + */ +JNIEXPORT jboolean JNICALL +Java_gnu_java_nio_VMChannel_connect (JNIEnv *env, jclass clazz __attribute__((unused)), + jint fd, jbyteArray addr, jint port, jint timeout) +{ +#ifdef HAVE_CONNECT + struct sockaddr_in sockaddr; + struct timeval timeo; + int origflags = 0, flags; + jbyte *addr_elems; + int ret; + int tmpErrno; + + if ((*env)->GetArrayLength (env, addr) != 4) + { + JCL_ThrowException (env, SOCKET_EXCEPTION, + "expecting 4-byte address"); + return JNI_FALSE; + } + + if (timeout > 0) + { + timeo.tv_sec = timeout / 1000; + timeo.tv_usec = (timeout % 1000) * 1000; + origflags = fcntl (fd, F_GETFL, 0); + if (origflags == -1) + { + JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno)); + return JNI_FALSE; + } + /* Set nonblocking mode, if not already set. */ + if (!(origflags & O_NONBLOCK)) + { + flags = origflags | O_NONBLOCK; + if (fcntl (fd, F_SETFL, flags) == -1) + { + JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno)); + return JNI_FALSE; + } + } + } + + addr_elems = (*env)->GetByteArrayElements (env, addr, NULL); + + memset (&sockaddr, 0, sizeof (struct sockaddr_in)); + sockaddr.sin_family = AF_INET; + sockaddr.sin_port = htons (port); + sockaddr.sin_addr.s_addr = *((uint32_t *) addr_elems); + + + do + { + ret = cpnio_connect (fd, (struct sockaddr *) &sockaddr, + sizeof (struct sockaddr_in)); + tmpErrno = errno; + } + while (ret == -1 && errno == EINTR && ! JCL_thread_interrupted(env)); + errno = tmpErrno; + + (*env)->ReleaseByteArrayElements (env, addr, addr_elems, JNI_ABORT); + + /* If a timeout was specified, select on the file descriptor with + the timeout. */ + if (timeout > 0 && ret == -1) + { + /* Reset the non-blocking flag, if needed. */ + if (!(origflags & O_NONBLOCK)) + { + if (fcntl (fd, F_SETFL, origflags) == -1) + { + /* oops */ + JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno)); + return JNI_FALSE; + } + } + if (EINPROGRESS == errno) + { + fd_set wrfds; + FD_ZERO(&wrfds); + FD_SET(fd, &wrfds); + ret = cpnio_select (fd + 1, NULL, &wrfds, NULL, &timeo); + if (ret == -1) + { + JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno)); + return JNI_FALSE; + } + if (ret == 0) /* connect timed out */ + { + JCL_ThrowException (env, SOCKET_TIMEOUT_EXCEPTION, + "connect timed out"); + return JNI_FALSE; + } + return JNI_TRUE; /* Connected! */ + } + else if (ECONNREFUSED == errno) + { + JCL_ThrowException (env, CONNECT_EXCEPTION, + strerror (errno)); + return JNI_FALSE; + } + else + { + JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno)); + return JNI_FALSE; + } + } + + if (ret == -1) + { + if (EINPROGRESS == errno) + return JNI_FALSE; + else if (ECONNREFUSED == errno) + { + JCL_ThrowException (env, CONNECT_EXCEPTION, + strerror (errno)); + return JNI_FALSE; + } + else + { + JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno)); + return JNI_FALSE; + } + } + + return JNI_TRUE; +#else + (void) fd; + (void) addr; + (void) port; + (void) timeout; + JCL_ThrowException (env, SOCKET_EXCEPTION, "connect not supported"); + return JNI_FALSE; +#endif /* HAVE_CONNECT */ +} + + +/* + * Class: gnu_java_nio_VMChannel + * Method: connect6 + * Signature: (I[BI)Z + */ +JNIEXPORT jboolean JNICALL +Java_gnu_java_nio_VMChannel_connect6 (JNIEnv *env, jclass clazz __attribute__((unused)), + jint fd, jbyteArray addr, jint port, int timeout) +{ +#if defined(HAVE_CONNECT) && defined(HAVE_INET6) + struct sockaddr_in6 sockaddr; + struct timeval timeo; + int flags, origflags = 0; + jbyte *addr_elems; + int ret; + + if (timeout > 0) + { + timeo.tv_sec = timeout / 1000; + timeo.tv_usec = (timeout % 1000) * 1000; + origflags = fcntl (fd, F_GETFL, 0); + if (origflags == -1) + { + JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno)); + return JNI_FALSE; + } + /* Set nonblocking mode, if not already set. */ + if (!(origflags & O_NONBLOCK)) + { + flags = origflags | O_NONBLOCK; + if (fcntl (fd, F_SETFL, flags) == -1) + { + JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno)); + return JNI_FALSE; + } + } + } + + addr_elems = (*env)->GetByteArrayElements (env, addr, NULL); + + memset (&sockaddr, 0, sizeof (struct sockaddr_in6)); + sockaddr.sin6_family = AF_INET6; + sockaddr.sin6_port = htons (port); + memcpy (&sockaddr.sin6_addr.s6_addr, addr_elems, 16); + + ret = cpnio_connect (fd, (struct sockaddr *) &sockaddr, + sizeof (struct sockaddr_in6)); + + (*env)->ReleaseByteArrayElements (env, addr, addr_elems, JNI_ABORT); + + /* If a timeout was specified, select on the file descriptor with + the timeout. */ + if (timeout > 0 && ret == -1) + { + /* Reset the non-blocking flag, if needed. */ + if (!(origflags & O_NONBLOCK)) + { + if (fcntl (fd, F_SETFL, origflags) == -1) + { + /* oops */ + JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno)); + return JNI_FALSE; + } + } + if (EINPROGRESS == errno) + { + fd_set wrfds; + FD_ZERO(&wrfds); + FD_SET(fd, &wrfds); + ret = cpnio_select (fd + 1, NULL, &wrfds, NULL, &timeo); + if (ret == -1) + { + JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno)); + return JNI_FALSE; + } + if (ret == 0) /* connect timed out */ + { + JCL_ThrowException (env, SOCKET_TIMEOUT_EXCEPTION, + "connect timed out"); + return JNI_FALSE; + } + return JNI_TRUE; /* Connected! */ + } + else if (ECONNREFUSED == errno) + { + JCL_ThrowException (env, CONNECT_EXCEPTION, + strerror (errno)); + return JNI_FALSE; + } + else + { + JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno)); + return JNI_FALSE; + } + } + + if (ret == -1) + { + if (EAGAIN == errno) + return JNI_FALSE; + else if (ECONNREFUSED == errno) + { + JCL_ThrowException (env, CONNECT_EXCEPTION, + strerror (errno)); + return JNI_FALSE; + } + else + { + JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno)); + return JNI_FALSE; + } + } + + return JNI_TRUE; +#else + (void) fd; + (void) addr; + (void) port; + (void) timeout; + JCL_ThrowException (env, SOCKET_EXCEPTION, "IPv6 connect not supported"); + return JNI_FALSE; +#endif /* HAVE_CONNECT && HAVE_INET6 */ +} + + +/* + * Class: gnu_java_nio_VMChannel + * Method: getsockname + * Signature: (ILjava/nio/ByteBuffer;)I + */ +JNIEXPORT jint JNICALL +Java_gnu_java_nio_VMChannel_getsockname (JNIEnv *env, jclass clazz __attribute__((unused)), + jint fd, jobject name) +{ +#ifdef HAVE_GETSOCKNAME +#ifdef HAVE_INET6 + struct sockaddr_in6 *addr6; + struct sockaddr_in6 sock_storage; + socklen_t socklen = sizeof (struct sockaddr_in6); +#else + struct sockaddr_in sock_storage; + socklen_t socklen = sizeof (struct sockaddr_in); +#endif /* HAVE_INET6 */ + + struct sockaddr *sockaddr = (struct sockaddr *) &sock_storage; + struct sockaddr_in *addr4; + int ret; + char *nameptr = (*env)->GetDirectBufferAddress (env, name); + + ret = getsockname (fd, sockaddr, &socklen); + if (ret == -1) + { + JCL_ThrowException (env, "java/net/SocketException", strerror (errno)); + return 0; + } + + if (sockaddr->sa_family == AF_INET) + { + addr4 = (struct sockaddr_in *) sockaddr; + memcpy (nameptr, &(addr4->sin_addr.s_addr), 4); + memcpy (nameptr + 4, &(addr4->sin_port), 2); + return 4; + } + +#ifdef HAVE_INET6 + /* IPv6 */ + if (sockaddr->sa_family == AF_INET6) + { + addr6 = (struct sockaddr_in6 *) sockaddr; + memcpy (nameptr, &(addr6->sin6_addr.s6_addr), 16); + memcpy (nameptr + 16, &(addr6->sin6_port), 2); + return 16; + } +#endif /* HAVE_INET6 */ + JCL_ThrowException (env, IO_EXCEPTION, "unsupported address format"); + return -1; +#else + (void) fd; + (void) name; + JCL_ThrowException (env, IO_EXCEPTION, "getsockname not supported"); + return -1; +#endif /* HAVE_GETSOCKNAME */ +} + + +/* + * Class: gnu_java_nio_VMChannel + * Method: getpeername + * Signature: (ILjava/nio/ByteBuffer;)I + */ +JNIEXPORT jint JNICALL +Java_gnu_java_nio_VMChannel_getpeername (JNIEnv *env, jclass clazz __attribute__((unused)), + jint fd, jobject name) +{ +#ifdef HAVE_GETPEERNAME +#ifdef HAVE_INET6 + struct sockaddr_in6 *addr6; + struct sockaddr_in6 sock_storage; + socklen_t socklen = sizeof (struct sockaddr_in6); +#else + struct sockaddr_in sock_storage; + socklen_t socklen = sizeof (struct sockaddr_in); +#endif /* HAVE_INET6 */ + + struct sockaddr *sockaddr = (struct sockaddr *) &sock_storage; + struct sockaddr_in *addr4; + int ret; + char *nameptr = (*env)->GetDirectBufferAddress (env, name); + + ret = getpeername (fd, sockaddr, &socklen); + if (ret == -1) + { + if (ENOTCONN != errno) + JCL_ThrowException (env, "java/net/SocketException", strerror (errno)); + return 0; + } + + if (sockaddr->sa_family == AF_INET) + { + addr4 = (struct sockaddr_in *) sockaddr; + memcpy (nameptr, &(addr4->sin_addr.s_addr), 4); + memcpy (nameptr + 4, &(addr4->sin_port), 2); + return 4; + } +#ifdef HAVE_INET6 + else if (sockaddr->sa_family == AF_INET6) + { + addr6 = (struct sockaddr_in6 *) sockaddr; + memcpy (nameptr, &(addr6->sin6_addr.s6_addr), 16); + memcpy (nameptr + 16, &(addr6->sin6_port), 2); + return 16; + } +#endif /* HAVE_INET6 */ + + JCL_ThrowException (env, "java/net/SocketException", + "unsupported address type"); + return -1; +#else + (void) fd; + (void) name; + JCL_ThrowException (env, IO_EXCEPTION, "getpeername not supported"); + return -1; +#endif /* HAVE_GETPEERNAME */ +} + + +/* + * Class: gnu_java_nio_VMChannel + * Method: accept + * Signature: (I)I + */ +JNIEXPORT jint JNICALL +Java_gnu_java_nio_VMChannel_accept (JNIEnv *env, + jclass c __attribute__((unused)), + jint fd) +{ +#ifdef HAVE_ACCEPT + int ret; + int tmp_errno = 0; + +#ifdef HAVE_INET6 + struct sockaddr_in6 addr; + socklen_t alen = sizeof (struct sockaddr_in6); +#else + struct sockaddr_in addr; + socklen_t alen = sizeof (struct sockaddr_in); +#endif /* HAVE_INET6 */ + + do + { + ret = cpnio_accept (fd, (struct sockaddr *) &addr, &alen); + tmp_errno = errno; + + if (ret == -1) + switch (tmp_errno) + { + case EINTR: + /* Check if interrupted by Thread.interrupt(). If not then some + * other unrelated signal interrupted the system function and + * we should start over again. + */ + if (JCL_thread_interrupted(env)) + { + JCL_ThrowException (env, "java/net/SocketException", strerror (tmp_errno)); + return -1; + } + break; +#if defined(EWOULDBLOCK) && defined(EAGAIN) && EWOULDBLOCK != EAGAIN + case EWOULDBLOCK: +#endif + case EAGAIN: + if (!is_non_blocking_fd(fd)) + { + JCL_ThrowException(env, SOCKET_TIMEOUT_EXCEPTION, "Accept timed out"); + } + /* Socket in non-blocking mode and no pending connection. */ + return -1; + default: + JCL_ThrowException (env, "java/net/SocketException", strerror (tmp_errno)); + return -1; + } + else + break; + } + while (1); + + cpio_closeOnExec(ret); + + return ret; +#else + (void) fd; + JCL_ThrowException (env, IO_EXCEPTION, "accept not supported"); + return -1; +#endif /* HAVE_ACCEPT */ +} + + + +/* + * Class: gnu_java_nio_VMChannel + * Method: disconnect + * Signature: (I)V + */ +JNIEXPORT void JNICALL +Java_gnu_java_nio_VMChannel_disconnect (JNIEnv *env, + jclass c __attribute__((unused)), + jint fd) +{ + struct sockaddr sockaddr; + + sockaddr.sa_family = AF_UNSPEC; + if (connect (fd, &sockaddr, sizeof (struct sockaddr)) == -1) + { + /* The expected error for a successful disconnect is EAFNOSUPPORT. */ + if (errno != EAFNOSUPPORT) + JCL_ThrowException (env, IO_EXCEPTION, strerror (errno)); + } +} + + +/* + * Class: gnu_java_nio_VMChannel + * Method: close + * Signature: (I)V + */ +JNIEXPORT void JNICALL +Java_gnu_java_nio_VMChannel_close (JNIEnv *env, + jclass c __attribute__((unused)), + jint fd) +{ + if (close (fd) == -1) + JCL_ThrowException (env, IO_EXCEPTION, strerror (errno)); +} + + +/* + * Class: gnu_java_nio_VMChannel + * Method: available + * Signature: (I)I + */ +JNIEXPORT jint JNICALL +Java_gnu_java_nio_VMChannel_available (JNIEnv *env, + jclass c __attribute__((unused)), + jint fd) +{ +#if defined (FIONREAD) + + jint avail = 0; + +#if defined(ENOTTY) && defined(HAVE_FSTAT) + struct stat statBuffer; + off_t n; +#endif + +/* NIODBG("fd: %d", fd); */ + if (ioctl (fd, FIONREAD, &avail) == -1) + { +#if defined(ENOTTY) && defined(HAVE_FSTAT) + if (errno == ENOTTY) + { + if ((fstat (fd, &statBuffer) == 0) && S_ISREG (statBuffer.st_mode)) + { + n = lseek (fd, 0, SEEK_CUR); + if (n != -1) + { + avail = statBuffer.st_size - n; + return avail; + } + } + } +#endif + JCL_ThrowException (env, IO_EXCEPTION, strerror (errno)); + } +/* NIODBG("avail: %d", avail); */ + + return avail; + +#elif defined(HAVE_FSTAT) + + jint avail = 0; + + struct stat statBuffer; + off_t n; + + if ((fstat (fd, &statBuffer) == 0) && S_ISREG (statBuffer.st_mode)) + { + n = lseek (fd, 0, SEEK_CUR); + if (n != -1) + { + avail = statBuffer.st_size - n; + return avail; + } + } + JCL_ThrowException (env, IO_EXCEPTION, strerror (errno)); + +#elif defined(HAVE_SELECT) + + jint avail = 0; + fd_set filedescriptset; + struct timeval tv; + + FD_ZERO (&filedescriptset); + FD_SET (fd,&filedescriptset); + memset (&tv, 0, sizeof(tv)); + + switch (select (fd+1, &filedescriptset, NULL, NULL, &tv)) + { + case -1: + break; + case 0: + avail = 0; + return avail; + default: + avail = 1; + return avail; + } + JCL_ThrowException (env, IO_EXCEPTION, strerror (errno)); + +#else + + JCL_ThrowException (env, IO_EXCEPTION, "No native method for available"); + +#endif +} + + +enum FileChannel_mode { + CPNIO_READ = 1, + CPNIO_WRITE = 2, + CPNIO_APPEND = 4, + CPNIO_EXCL = 8, + CPNIO_SYNC = 16, + CPNIO_DSYNC = 32 +}; + + +/* + * Class: gnu_java_nio_VMChannel + * Method: open + * Signature: (Ljava/lang/String;I)I + */ +JNIEXPORT jint JNICALL +Java_gnu_java_nio_VMChannel_open (JNIEnv *env, + jclass c __attribute__((unused)), + jstring path, jint mode) +{ + int nmode = 0; + int ret; + const char *npath; + + if ((mode & CPNIO_READ) && (mode & CPNIO_WRITE)) + nmode = O_RDWR; + else if (mode & CPNIO_WRITE) + nmode = O_WRONLY; + else + nmode = O_RDONLY; + + nmode = (nmode + | ((nmode == O_RDWR || nmode == O_WRONLY) ? O_CREAT : 0) + | ((mode & CPNIO_APPEND) ? O_APPEND : + ((nmode == O_WRONLY) ? O_TRUNC : 0)) + | ((mode & CPNIO_EXCL) ? O_EXCL : 0) + | ((mode & CPNIO_SYNC) ? O_SYNC : 0)); + + npath = JCL_jstring_to_cstring (env, path); + +/* NIODBG("path: %s; mode: %x", npath, nmode); */ + + ret = open (npath, nmode, 0666); + +/* NIODBG("ret: %d\n", ret); */ + + JCL_free_cstring (env, path, npath); + + if (-1 == ret) + JCL_ThrowException (env, IO_EXCEPTION, strerror (errno)); + + return ret; +} + + +/* + * Class: gnu_java_nio_VMChannel + * Method: position + * Signature: (I)J + */ +JNIEXPORT jlong JNICALL +Java_gnu_java_nio_VMChannel_position (JNIEnv *env, + jclass c __attribute__((unused)), + jint fd) +{ +#ifdef HAVE_LSEEK + off_t ret; + + ret = lseek (fd, 0, SEEK_CUR); + + if (-1 == ret) + JCL_ThrowException (env, IO_EXCEPTION, strerror (errno)); + + return (jlong) ret; +#else + JCL_ThrowException (env, IO_EXCEPTION, "position not supported"); + return -1; +#endif /* HAVE_LSEEK */ +} + + +/* + * Class: gnu_java_nio_VMChannel + * Method: seek + * Signature: (IJ)V + */ +JNIEXPORT void JNICALL +Java_gnu_java_nio_VMChannel_seek (JNIEnv *env, + jclass c __attribute__((unused)), + jint fd, jlong pos) +{ +#ifdef HAVE_LSEEK + if (lseek (fd, (off_t) pos, SEEK_SET) == -1) + JCL_ThrowException (env, IO_EXCEPTION, strerror (errno)); +#else + JCL_ThrowException (env, IO_EXCEPTION, "seek not supported"); +#endif /* HAVE_LSEEK */ +} + + +/* + * Class: gnu_java_nio_VMChannel + * Method: truncate + * Signature: (IJ)V + */ +JNIEXPORT void JNICALL +Java_gnu_java_nio_VMChannel_truncate (JNIEnv *env, + jclass c __attribute__((unused)), + jint fd, jlong len) +{ +#if defined(HAVE_FTRUNCATE) && defined(HAVE_LSEEK) + off_t pos = lseek (fd, 0, SEEK_CUR); + if (pos == -1) + { + JCL_ThrowException (env, IO_EXCEPTION, strerror (errno)); + return; + } + if (ftruncate (fd, (off_t) len) == -1) + { + JCL_ThrowException (env, IO_EXCEPTION, strerror (errno)); + return; + } + if (pos > len) + { + if (lseek (fd, len, SEEK_SET) == -1) + JCL_ThrowException (env, IO_EXCEPTION, strerror (errno)); + } +#else + JCL_ThrowException (env, IO_EXCEPTION, "truncate not supported"); +#endif /* HAVE_FTRUNCATE && HAVE_LSEEK */ +} + + +/* + * Class: gnu_java_nio_VMChannel + * Method: lock + * Signature: (IJJZZ)Z + */ +JNIEXPORT jboolean JNICALL +Java_gnu_java_nio_VMChannel_lock (JNIEnv *env, + jclass c __attribute__((unused)), + jint fd, jlong pos, jlong len, + jboolean shared, jboolean wait) +{ +#if HAVE_FCNTL + struct flock fl; + + fl.l_start = (off_t) pos; + /* Long.MAX_VALUE means lock everything possible starting at pos. */ + if (len == 9223372036854775807LL) + fl.l_len = 0; + else + fl.l_len = (off_t) len; + fl.l_pid = getpid (); + fl.l_type = (shared ? F_RDLCK : F_WRLCK); + fl.l_whence = SEEK_SET; + + if (cpnio_fcntl (fd, (wait ? F_SETLKW : F_SETLK), (long) &fl) == -1) + { + if (errno != EAGAIN) + JCL_ThrowException (env, IO_EXCEPTION, strerror (errno)); + return JNI_FALSE; + } + + return JNI_TRUE; +#else + JCL_ThrowException (env, IO_EXCEPTION, "lock not supported"); + return JNI_FALSE; +#endif /* HAVE_FCNTL */ +} + +/* + * Class: gnu_java_nio_VMChannel + * Method: unlock + * Signature: (IJJ)V + */ +JNIEXPORT void JNICALL +Java_gnu_java_nio_VMChannel_unlock (JNIEnv *env, + jclass c __attribute__((unused)), + jint fd, jlong pos, jlong len) +{ +#if HAVE_FCNTL + struct flock fl; + + fl.l_start = (off_t) pos; + fl.l_len = (off_t) len; + fl.l_pid = getpid (); + fl.l_type = F_UNLCK; + fl.l_whence = SEEK_SET; + + if (cpnio_fcntl (fd, F_SETLK, (long) &fl) == -1) + { + JCL_ThrowException (env, IO_EXCEPTION, strerror (errno)); + } +#else + JCL_ThrowException (env, IO_EXCEPTION, "unlock not supported"); +#endif /* HAVE_FCNTL */ +} + +/* + * Class: gnu_java_nio_VMChannel + * Method: size + * Signature: (I)J + */ +JNIEXPORT jlong JNICALL +Java_gnu_java_nio_VMChannel_size (JNIEnv *env, + jclass c __attribute__((unused)), + jint fd) +{ +#ifdef HAVE_FSTAT + struct stat st; + + if (fstat (fd, &st) == -1) + JCL_ThrowException (env, IO_EXCEPTION, strerror (errno)); + + return (jlong) st.st_size; +#else + JCL_ThrowException (env, IO_EXCEPTION, "size not supported"); + return 0; +#endif +} + +/* + * Class: gnu_java_nio_VMChannel + * Method: map + * Signature: (ICJI)Lgnu/classpath/Pointer; + */ +JNIEXPORT jobject JNICALL +Java_gnu_java_nio_VMChannel_map (JNIEnv *env, + jclass clazz __attribute__((unused)), + jint fd, jchar mode, jlong position, jint size) +{ +#ifdef HAVE_MMAP + jclass MappedByteBufferImpl_class; + jmethodID MappedByteBufferImpl_init = NULL; + jobject Pointer_instance; + volatile jobject buffer; + long pagesize; + int prot, flags; + void *p; + void *address; + +/* NIODBG("fd: %d; mode: %x; position: %lld; size: %d", */ +/* fd, mode, position, size); */ + + /* FIXME: should we just assume we're on an OS modern enough to + have 'sysconf'? And not check for 'getpagesize'? */ +#if defined(HAVE_GETPAGESIZE) + pagesize = getpagesize (); +#elif defined(HAVE_SYSCONF) + pagesize = sysconf (_SC_PAGESIZE); +#else + JCL_ThrowException (env, IO_EXCEPTION, + "can't determine memory page size"); + return NULL; +#endif /* HAVE_GETPAGESIZE/HAVE_SYSCONF */ + + if ((*env)->ExceptionOccurred (env)) + { + return NULL; + } + + prot = PROT_READ; + if (mode == '+' || mode == 'c') + { + /* When writing we need to make sure the file is big enough, + otherwise the result of mmap is undefined. */ + struct stat st; + if (fstat (fd, &st) == -1) + { + JCL_ThrowException (env, IO_EXCEPTION, strerror (errno)); + return NULL; + } + if (position + size > st.st_size) + { + if (ftruncate(fd, position + size) == -1) + { + JCL_ThrowException (env, IO_EXCEPTION, strerror (errno)); + return NULL; + } + } + prot |= PROT_WRITE; + } + + flags = (mode == 'c' ? MAP_PRIVATE : MAP_SHARED); + p = mmap (NULL, (size_t) ALIGN_UP (size, pagesize), prot, flags, + fd, ALIGN_DOWN (position, pagesize)); + if (p == MAP_FAILED) + { + JCL_ThrowException (env, IO_EXCEPTION, strerror (errno)); + return NULL; + } + + /* Unalign the mapped value back up, since we aligned offset + down to a multiple of the page size. */ + address = (void *) ((char *) p + (position % pagesize)); + + Pointer_instance = JCL_NewRawDataObject(env, address); + + MappedByteBufferImpl_class = (*env)->FindClass (env, + "java/nio/MappedByteBufferImpl"); + if (MappedByteBufferImpl_class != NULL) + { + MappedByteBufferImpl_init = + (*env)->GetMethodID (env, MappedByteBufferImpl_class, + "<init>", "(Lgnu/classpath/Pointer;IZ)V"); + } + + if ((*env)->ExceptionOccurred (env)) + { + munmap (p, ALIGN_UP (size, pagesize)); + return NULL; + } + if (MappedByteBufferImpl_init == NULL) + { + JCL_ThrowException (env, "java/lang/InternalError", + "could not get MappedByteBufferImpl constructor"); + munmap (p, ALIGN_UP (size, pagesize)); + return NULL; + } + + buffer = (*env)->NewObject (env, MappedByteBufferImpl_class, + MappedByteBufferImpl_init, Pointer_instance, + (jint) size, mode == 'r'); + return buffer; +#else + (void) fd; + (void) mode; + (void) position; + (void) size; + JCL_ThrowException (env, IO_EXCEPTION, + "memory-mapped files not implemented"); + return 0; +#endif /* HAVE_MMAP */ +} + +/* + * Class: gnu_java_nio_VMChannel + * Method: flush + * Signature: (IZ)Z + */ +JNIEXPORT jboolean JNICALL +Java_gnu_java_nio_VMChannel_flush (JNIEnv *env, + jclass c __attribute__((unused)), + jint fd, jboolean metadata __attribute__((unused))) +{ +#ifdef HAVE_FSYNC + /* XXX blocking? */ + if (fsync (fd) == -1) + { + JCL_ThrowException (env, IO_EXCEPTION, strerror (errno)); + return JNI_FALSE; + } + return JNI_TRUE; +#else + JCL_ThrowException (env, IO_EXCEPTION, "flush not implemented"); + return JNI_TRUE; +#endif /* HAVE_FSYNC */ +} + + +#ifdef __cplusplus +} +#endif diff --git a/libjava/classpath/native/jni/java-nio/gnu_java_nio_VMPipe.c b/libjava/classpath/native/jni/java-nio/gnu_java_nio_VMPipe.c new file mode 100644 index 000000000..cbaaa0834 --- /dev/null +++ b/libjava/classpath/native/jni/java-nio/gnu_java_nio_VMPipe.c @@ -0,0 +1,83 @@ +/* gnu_java_nio_VMPipe.c - Native methods for PipeImpl class + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif /* HAVE_CONFIG_H */ + +#include <errno.h> +#include <string.h> +#include <unistd.h> + +#include <jni.h> +#include <jcl.h> + +#include "gnu_java_nio_VMPipe.h" + +#define IO_EXCEPTION "java/io/IOException" + +/* + * Class: gnu_java_nio_VMPipe + * Method: pipe0 + * Signature: ()[I + */ +JNIEXPORT jintArray JNICALL +Java_gnu_java_nio_VMPipe_pipe0 (JNIEnv *env, + jclass c __attribute__((unused))) +{ + int fd[2]; + jintArray array; + jint* elem; + int ret; + + /* FIXME: autoconf this? */ + ret = pipe (fd); + + if (ret == -1) + { + JCL_ThrowException (env, "java/io/IOException", strerror (errno)); + return NULL; + } + + array = (*env)->NewIntArray (env, 2); + elem = (*env)->GetIntArrayElements (env, array, NULL); + elem[0] = fd[0]; + elem[1] = fd[1]; + (*env)->ReleaseIntArrayElements (env, array, elem, 0); + return array; +} diff --git a/libjava/classpath/native/jni/java-nio/gnu_java_nio_VMSelector.c b/libjava/classpath/native/jni/java-nio/gnu_java_nio_VMSelector.c new file mode 100644 index 000000000..19a6f244d --- /dev/null +++ b/libjava/classpath/native/jni/java-nio/gnu_java_nio_VMSelector.c @@ -0,0 +1,303 @@ +/* gnu_java_nio_VMSelector.c - Native methods for SelectorImpl class + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +#include "config.h" + +/* <sys/types.h> needs to be included on OSX before <sys/select.h> */ +#if defined(HAVE_SYS_TYPES_H) +#include <sys/types.h> +#endif +#if defined(HAVE_SYS_SELECT_H) +#include <sys/select.h> +#endif +#include <sys/time.h> + +#include <string.h> + +#include <errno.h> + +#include <jni.h> +#include <jcl.h> + +#include "gnu_java_nio_VMSelector.h" + +/* Amount of characters in the error message buffer for strerror_r. */ +#define BUF_SIZE 250 + +void helper_put_filedescriptors (JNIEnv *, jintArray, fd_set *, int *); + +void helper_get_filedescriptors (JNIEnv *, jintArray *, fd_set *); + +void helper_reset (JNIEnv *, jintArray *); + +int +helper_select (JNIEnv *, jclass, jmethodID, + int, fd_set *, fd_set *, fd_set *, struct timeval *); + +void +helper_put_filedescriptors (JNIEnv * env, jintArray fdArray, fd_set * fds, + int *max_fd) +{ + jint *tmpFDArray = (*env)->GetIntArrayElements (env, fdArray, 0); + int size = (*env)->GetArrayLength (env, fdArray); + int index, fd; + + for (index = 0; index < size; index++) + { + fd = tmpFDArray[index]; + + if (fd > 0) + { + FD_SET (tmpFDArray[index], fds); + + if (tmpFDArray[index] > (*max_fd)) + (*max_fd) = tmpFDArray[index]; + } + } +} + +void +helper_get_filedescriptors (JNIEnv * env, jintArray * fdArray, fd_set * fds) +{ + jint *tmpFDArray = (*env)->GetIntArrayElements (env, fdArray, 0); + int size = (*env)->GetArrayLength (env, fdArray); + int index, fd; + + for (index = 0; index < size; index++) + { + fd = tmpFDArray[index]; + if (fd < 0 || !FD_ISSET (fd, fds)) + tmpFDArray[index] = 0; + } +} + +void +helper_reset (JNIEnv * env, jintArray * fdArray) +{ + jint *tmpFDArray = (*env)->GetIntArrayElements (env, fdArray, 0); + int size = (*env)->GetArrayLength (env, fdArray); + int index; + + for (index = 0; index < size; index++) + tmpFDArray[index] = 0; +} + +/* A wrapper for select() which ignores EINTR. + * Taken from gclib's posix.cc + */ +int +helper_select (JNIEnv * env, jclass thread_class, + jmethodID thread_interrupted, int n, fd_set * readfds, + fd_set * writefds, fd_set * exceptfds, struct timeval *timeout) +{ +#ifdef HAVE_SYS_SELECT_H + /* If we have a timeout, compute the absolute ending time. */ + struct timeval end, delay, after; + int r; + + if (timeout) + { + gettimeofday (&end, NULL); + + end.tv_usec += timeout->tv_usec; + + if (end.tv_usec >= 1000000) + { + ++end.tv_sec; + end.tv_usec -= 1000000; + } + + end.tv_sec += timeout->tv_sec; + delay = *timeout; + } + else + { + /* Placate compiler. */ + delay.tv_sec = delay.tv_usec = 0; + } + + while (1) + { + r = select (n, readfds, writefds, exceptfds, timeout ? &delay : NULL); + + if (r < 0 && errno != EINTR) + return -errno; + else if (r >= 0) + return r; + + /* Here we know we got EINTR. */ + if ((*env)-> + CallStaticBooleanMethod (env, thread_class, thread_interrupted)) + { + return -EINTR; + } + + if (timeout) + { + gettimeofday (&after, NULL); + + /* Now compute new timeout argument. */ + delay.tv_usec = end.tv_usec - after.tv_usec; + delay.tv_sec = end.tv_sec - after.tv_sec; + + if (delay.tv_usec < 0) + { + --delay.tv_sec; + delay.tv_usec += 1000000; + } + + if (delay.tv_sec < 0) + { + /* We assume that the user wants a valid select() call + * more than precise timing. So if we get a series of + * EINTR we just keep trying with delay 0 until we get a + * valid result. + */ + delay.tv_sec = 0; + } + } + } +#else /* HAVE_SYS_SELECT_H */ + return 0; +#endif + +} + +JNIEXPORT jint JNICALL +Java_gnu_java_nio_VMSelector_select (JNIEnv * env, + jclass obj __attribute__ ((__unused__)), + jintArray read, + jintArray write, + jintArray except, jlong timeout) +{ + jint result; + jclass thread_class = (*env)->FindClass (env, "java/lang/Thread"); + jmethodID thread_current_thread = + (*env)->GetStaticMethodID (env, thread_class, "currentThread", + "()Ljava/lang/Thread;"); + jmethodID thread_interrupt = + (*env)->GetMethodID (env, thread_class, "interrupt", "()V"); + jmethodID thread_interrupted = + (*env)->GetStaticMethodID (env, thread_class, "interrupted", "()Z"); + jobject current_thread; + int max_fd = 0; + fd_set read_fds; + fd_set write_fds; + fd_set except_fds; + struct timeval real_time_data; + struct timeval *time_data = NULL; + char *message; + + /* If a legal timeout value isn't given, use NULL. + * This means an infinite timeout. The specification + * also says that a zero timeout should be treated + * as infinite. Otherwise (if the timeout value is legal), + * fill our timeval struct and use it for the select. + */ + if (timeout > 0) + { + real_time_data.tv_sec = timeout / 1000; + real_time_data.tv_usec = (timeout % 1000) * 1000; + time_data = &real_time_data; + } + + /* Reset all fd_set structures */ + FD_ZERO (&read_fds); + FD_ZERO (&write_fds); + FD_ZERO (&except_fds); + + /* Fill the fd_set data structures for the _Jv_select() call. */ + helper_put_filedescriptors (env, read, &read_fds, &max_fd); + helper_put_filedescriptors (env, write, &write_fds, &max_fd); + helper_put_filedescriptors (env, except, &except_fds, &max_fd); + + /* Actually do the select */ + result = + helper_select (env, thread_class, thread_interrupted, max_fd + 1, + &read_fds, &write_fds, &except_fds, time_data); + + if (result == -EINTR) + { + /* The behavior of JRE 1.4.1 is that no exception is thrown + * when the thread is interrupted, but the thread's interrupt + * status is set. Clear all of our select sets and return 0, + * indicating that nothing was selected. + */ + current_thread = + (*env)->CallStaticObjectMethod (env, thread_class, + thread_current_thread); + (*env)->CallVoidMethod (env, current_thread, thread_interrupt); + + helper_reset (env, read); + helper_reset (env, write); + helper_reset (env, except); + + return 0; + } + + if (result < 0) + { +#if defined(HAVE_STRERROR_R) + char message_buf[BUF_SIZE+1]; + int errorcode = -result; + + if (strerror_r (errorcode, message_buf, BUF_SIZE)) + { + /* This would mean that message_buf was to small + * to hold the error message. + */ + JCL_ThrowException (env, "java/lang/InternalError", + "Not enough space in message buffer."); + return 0; + } + + message = message_buf; +#else + message = strerror(errno); +#endif + + JCL_ThrowException (env, "java/io/IOException", message); + return 0; + } + + /* Set the file descriptors according to the values returned from select(). */ + helper_get_filedescriptors (env, read, &read_fds); + helper_get_filedescriptors (env, write, &write_fds); + helper_get_filedescriptors (env, except, &except_fds); + + return result; +} diff --git a/libjava/classpath/native/jni/java-nio/gnu_java_nio_charset_iconv_IconvDecoder.c b/libjava/classpath/native/jni/java-nio/gnu_java_nio_charset_iconv_IconvDecoder.c new file mode 100644 index 000000000..248a948c3 --- /dev/null +++ b/libjava/classpath/native/jni/java-nio/gnu_java_nio_charset_iconv_IconvDecoder.c @@ -0,0 +1,208 @@ +/* gnu_java_nio_charset_iconv_IconvDecoder.c -- + Copyright (C) 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +#include <config.h> +#include <jcl.h> + +#include <stdio.h> +#include <assert.h> +#include <errno.h> + +#if defined(HAVE_ICONV) +#include <iconv.h> +#endif + +#include "gnu_java_nio_charset_iconv_IconvDecoder.h" + +#if defined(HAVE_ICONV) +static void createRawData (JNIEnv * env, jobject obj, void *ptr); +static void *getData (JNIEnv * env, jobject obj); + +static jfieldID infid = NULL; +static jfieldID outfid = NULL; +#endif + +/* Union used for type punning. */ +union char_union +{ + jbyte **jb; + jchar **jc; + char **c; +}; + +JNIEXPORT void JNICALL +Java_gnu_java_nio_charset_iconv_IconvDecoder_openIconv (JNIEnv * env UNUSED, + jobject obj UNUSED, + jstring jname UNUSED) +{ +#if defined(HAVE_ICONV) + iconv_t iconv_object; + jclass cls; + + const char *name = JCL_jstring_to_cstring (env, jname); + if (name == NULL) + return; + + /* Cache fieldIDs for use in decode function. */ + if (infid == NULL || outfid == NULL) + { + cls = (*env)->GetObjectClass (env, obj); + infid = (*env)->GetFieldID (env, cls, "inremaining", "I"); + assert (infid != 0); + outfid = (*env)->GetFieldID (env, cls, "outremaining", "I"); + assert (outfid != 0); + } + + /* to java from "name", native java format depends on endianness */ +#ifdef WORDS_BIGENDIAN + iconv_object = iconv_open ("UTF-16BE", name); +#else + iconv_object = iconv_open ("UTF-16LE", name); +#endif + + JCL_free_cstring (env, jname, name); + if ((long) iconv_object == -1L) + { + JCL_ThrowException (env, "java/lang/IllegalArgumentException", + "Charset not available"); + return; + } + createRawData (env, obj, (void *) iconv_object); +#else + JCL_ThrowException (env, "java/lang/IllegalArgumentException", + "iconv not available"); +#endif +} + +JNIEXPORT jint JNICALL +Java_gnu_java_nio_charset_iconv_IconvDecoder_decode (JNIEnv * env UNUSED, + jobject obj UNUSED, + jbyteArray inArr UNUSED, + jcharArray outArr UNUSED, + jint posIn UNUSED, + jint remIn UNUSED, + jint posOut UNUSED, + jint remOut UNUSED) +{ +#if defined(HAVE_ICONV) + iconv_t iconv_object = getData (env, obj); + size_t retval; + union char_union in, out; + jbyte *input, *inputcopy; + jchar *output, *outputcopy; + size_t lenIn = (size_t) remIn; + size_t lenOut = (size_t) remOut * 2; + + inputcopy = input = (*env)->GetByteArrayElements (env, inArr, 0); + outputcopy = output = (*env)->GetCharArrayElements (env, outArr, 0); + + input += posIn; + output += posOut; + + in.jb = &input; + out.jc = &output; + retval = iconv (iconv_object, (ICONV_CONST char **) in.c, &lenIn, + out.c, &lenOut); + + /* XXX: Do we need to relase the input array? It's not modified. */ + (*env)->ReleaseByteArrayElements (env, inArr, inputcopy, 0); + (*env)->ReleaseCharArrayElements (env, outArr, outputcopy, 0); + + if (retval == (size_t) (-1)) + { + if (errno == EILSEQ) + retval = 1; + else + retval = 0; + } + else + retval = 0; + + (*env)->SetIntField (env, obj, infid, (jint) lenIn); + (*env)->SetIntField (env, obj, outfid, (jint) (lenOut >> 1)); + + return (jint) retval; +#else + return -1; +#endif +} + +JNIEXPORT void JNICALL +Java_gnu_java_nio_charset_iconv_IconvDecoder_closeIconv (JNIEnv * env UNUSED, + jobject obj UNUSED) +{ +#if defined(HAVE_ICONV) + iconv_t iconv_object; + iconv_object = getData (env, obj); + iconv_close (iconv_object); +#endif +} + + +#if defined(HAVE_ICONV) +static void +createRawData (JNIEnv * env, jobject obj, void *ptr) +{ + jclass cls; + jobject data; + jfieldID data_fid; + + cls = (*env)->GetObjectClass (env, obj); + data_fid = (*env)->GetFieldID (env, cls, "data", "Lgnu/classpath/Pointer;"); + assert (data_fid != 0); + + data = JCL_NewRawDataObject(env, ptr); + + (*env)->SetObjectField (env, obj, data_fid, data); +} + +static void * +getData (JNIEnv * env, jobject obj) +{ + jclass cls; + jfieldID data_fid; + jobject data; + + cls = (*env)->GetObjectClass (env, obj); + data_fid = (*env)->GetFieldID (env, cls, "data", "Lgnu/classpath/Pointer;"); + assert (data_fid != 0); + data = (*env)->GetObjectField (env, obj, data_fid); + + return JCL_GetRawData(env, data); +} +#endif + diff --git a/libjava/classpath/native/jni/java-nio/gnu_java_nio_charset_iconv_IconvEncoder.c b/libjava/classpath/native/jni/java-nio/gnu_java_nio_charset_iconv_IconvEncoder.c new file mode 100644 index 000000000..54fd17286 --- /dev/null +++ b/libjava/classpath/native/jni/java-nio/gnu_java_nio_charset_iconv_IconvEncoder.c @@ -0,0 +1,208 @@ +/* gnu_java_nio_charset_iconv_IconvEncoder.c -- + Copyright (C) 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +#include <config.h> +#include <jcl.h> + +#include <stdio.h> +#include <assert.h> +#include <errno.h> + +#if defined(HAVE_ICONV) +#include <iconv.h> +#endif + +#include "gnu_java_nio_charset_iconv_IconvEncoder.h" + + +#if defined(HAVE_ICONV) +static void createRawData (JNIEnv * env, jobject obj, void *ptr); +static void *getData (JNIEnv * env, jobject obj); + +static jfieldID infid = NULL; +static jfieldID outfid = NULL; +#endif + +/* Union used for type punning. */ +union char_union +{ + jbyte **jb; + jchar **jc; + char **c; +}; + +JNIEXPORT void JNICALL +Java_gnu_java_nio_charset_iconv_IconvEncoder_openIconv (JNIEnv * env UNUSED, + jobject obj UNUSED, + jstring jname UNUSED) +{ +#if defined(HAVE_ICONV) + iconv_t iconv_object; + jclass cls; + + const char *name = JCL_jstring_to_cstring (env, jname); + if (name == NULL) + return; + + /* Cache fieldIDs for use in encode function. */ + if (infid == NULL || outfid == NULL) + { + cls = (*env)->GetObjectClass (env, obj); + infid = (*env)->GetFieldID (env, cls, "inremaining", "I"); + assert (infid != 0); + outfid = (*env)->GetFieldID (env, cls, "outremaining", "I"); + assert (outfid != 0); + } + + /* to "name" from java, native java format depends on endianness */ +#ifdef WORDS_BIGENDIAN + iconv_object = iconv_open (name, "UTF-16BE"); +#else + iconv_object = iconv_open (name, "UTF-16LE"); +#endif + + JCL_free_cstring (env, jname, name); + if ((long) iconv_object == -1L) + { + JCL_ThrowException (env, "java/lang/IllegalArgumentException", + "Charset not available"); + return; + } + createRawData (env, obj, (void *) iconv_object); +#else + JCL_ThrowException (env, "java/lang/IllegalArgumentException", + "iconv not available"); +#endif +} + +JNIEXPORT jint JNICALL +Java_gnu_java_nio_charset_iconv_IconvEncoder_encode (JNIEnv * env UNUSED, + jobject obj UNUSED, + jcharArray inArr UNUSED, + jbyteArray outArr UNUSED, + jint posIn UNUSED, + jint remIn UNUSED, + jint posOut UNUSED, + jint remOut UNUSED) +{ +#if defined(HAVE_ICONV) + iconv_t iconv_object = getData (env, obj); + size_t retval; + union char_union in, out; + jchar *input, *inputcopy; + jbyte *output, *outputcopy; + size_t lenIn = (size_t) remIn * 2; + size_t lenOut = (size_t) remOut; + + inputcopy = input = (*env)->GetCharArrayElements (env, inArr, 0); + outputcopy = output = (*env)->GetByteArrayElements (env, outArr, 0); + + input += posIn; + output += posOut; + + in.jc = &input; + out.jb = &output; + retval = iconv (iconv_object, (ICONV_CONST char **) in.c, &lenIn, + out.c, &lenOut); + + /* XXX: Do we need to relase the input array? It's not modified. */ + (*env)->ReleaseCharArrayElements (env, inArr, inputcopy, 0); + (*env)->ReleaseByteArrayElements (env, outArr, outputcopy, 0); + + if (retval == (size_t) (-1)) + { + if (errno == EILSEQ || errno == EINVAL) + retval = 1; + else + retval = 0; + } + else + retval = 0; + + (*env)->SetIntField (env, obj, infid, (jint) (lenIn >> 1)); + (*env)->SetIntField (env, obj, outfid, (jint) lenOut); + + return (jint) retval; +#else + return -1; +#endif +} + +JNIEXPORT void JNICALL +Java_gnu_java_nio_charset_iconv_IconvEncoder_closeIconv (JNIEnv * env UNUSED, + jobject obj UNUSED) +{ +#if defined(HAVE_ICONV) + iconv_t iconv_object; + iconv_object = getData (env, obj); + iconv_close (iconv_object); +#endif +} + + +#if defined(HAVE_ICONV) +static void +createRawData (JNIEnv * env, jobject obj, void *ptr) +{ + jclass cls; + jobject data; + jfieldID data_fid; + + cls = (*env)->GetObjectClass (env, obj); + data_fid = (*env)->GetFieldID (env, cls, "data", "Lgnu/classpath/Pointer;"); + assert (data_fid != 0); + + data = JCL_NewRawDataObject (env, ptr); + + (*env)->SetObjectField (env, obj, data_fid, data); +} + +static void * +getData (JNIEnv * env, jobject obj) +{ + jclass cls; + jfieldID data_fid; + jobject data; + + cls = (*env)->GetObjectClass (env, obj); + data_fid = (*env)->GetFieldID (env, cls, "data", "Lgnu/classpath/Pointer;"); + assert (data_fid != 0); + data = (*env)->GetObjectField (env, obj, data_fid); + + return JCL_GetRawData(env, data); +} +#endif diff --git a/libjava/classpath/native/jni/java-nio/java_nio_MappedByteBufferImpl.c b/libjava/classpath/native/jni/java-nio/java_nio_MappedByteBufferImpl.c new file mode 100644 index 000000000..2a87d2950 --- /dev/null +++ b/libjava/classpath/native/jni/java-nio/java_nio_MappedByteBufferImpl.c @@ -0,0 +1,241 @@ +/* java_nio_MappedByteBufferImpl.c - Native methods for MappedByteBufferImpl + Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +#include <config.h> +#include <errno.h> + +#include <jni.h> +#include <jcl.h> + +#include "java_nio_MappedByteBufferImpl.h" + +#include <string.h> +#include <stdlib.h> +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif /* HAVE_UNISTD_H */ +#ifdef HAVE_SYS_MMAN_H +#include <sys/mman.h> +#endif /* HAVE_SYS_MMAN_H */ + +#define IO_EXCEPTION "java/io/IOException" + +/* FIXME these are defined in gnu_java_nio_channels_FileChannelImpl + too; should be someplace common. */ +#define ALIGN_DOWN(p,s) ((jpointer)(p) - ((jpointer)(p) % (s))) +#define ALIGN_UP(p,s) ((jpointer)(p) + ((s) - ((jpointer)(p) % (s)))) + +/** + * Returns the memory page size of this platform. + * + * \return The page size. + */ +static long +get_pagesize (void) +{ + /* FIXME can we just try HAVE_SYSCONF? */ +#if defined(HAVE_GETPAGESIZE) + return getpagesize (); +#elif defined (HAVE_SYSCONF) + return sysconf (_SC_PAGESIZE); +#endif /* HAVE_GETPAGESIZE / HAVE_SYSCONF */ +} + +/** + * Retrieve the 'address' and 'cap' (the mapped size) fields of this + * buffer. + * + * This function will align the address down to the nearest page + * boundary, and the size up to the nearest page boundary. Thus, it is + * safe to use these values in 'mman' functions. + * + * \param env The JNI environment pointer. + * \param this The MappedByteBufferImpl instance. + * \param address A pointer to where the actual pointer should be + * stored. + * \param size A pointer to where the mapped region's size should be + * stored + */ +static void +get_raw_values (JNIEnv *env, jobject this, void **address, size_t *size) +{ + const long pagesize = get_pagesize (); + jfieldID MappedByteBufferImpl_address; + jfieldID MappedByteBufferImpl_size; + jobject MappedByteBufferImpl_address_value = NULL; + + *address = NULL; + /* 'address' is declared in java.nio.Buffer */ + MappedByteBufferImpl_address + = (*env)->GetFieldID (env, (*env)->GetObjectClass (env, this), + "address", "Lgnu/classpath/Pointer;"); + /* 'cap' -- likewise, the capacity */ + MappedByteBufferImpl_size + = (*env)->GetFieldID (env, (*env)->GetObjectClass (env, this), + "cap", "I"); + if (MappedByteBufferImpl_address != NULL) + { + MappedByteBufferImpl_address_value = + (*env)->GetObjectField (env, this, MappedByteBufferImpl_address); + } + if ((*env)->ExceptionOccurred (env)) + return; + if (MappedByteBufferImpl_address_value == NULL) + { + JCL_ThrowException (env, "java/lang/NullPointerException", + "mapped address is NULL"); + return; + } + + *address = (void *) + ALIGN_DOWN (JCL_GetRawData (env, MappedByteBufferImpl_address_value), pagesize); + *size = (size_t) + ALIGN_UP ((*env)->GetIntField (env, this, MappedByteBufferImpl_size), + pagesize); +} + +JNIEXPORT void JNICALL +Java_java_nio_MappedByteBufferImpl_unmapImpl (JNIEnv *env, jobject this) +{ +#ifdef HAVE_MUNMAP + void *address; + size_t size; + + get_raw_values (env, this, &address, &size); + + if (address == NULL) + return; + + if (munmap (address, size) != 0) + { + JCL_ThrowException (env, IO_EXCEPTION, strerror (errno)); + return; + } +#else + JCL_ThrowException (env, IO_EXCEPTION, + "unmapping files not implemented"); +#endif /* HAVE_MUNMAP */ +} + +JNIEXPORT jboolean JNICALL +Java_java_nio_MappedByteBufferImpl_isLoadedImpl (JNIEnv * env, jobject this) +{ +#ifdef HAVE_MINCORE + void *address; + size_t size; + char *vec; + size_t count, i; + const long pagesize = get_pagesize (); + + /* + * FIXME on Darwin this does not work if the mapped region is + * exactly one page long; i.e., 'mincore' tells us it isn't loaded. + */ + get_raw_values (env, this, &address, &size); + if (address == NULL) + return JNI_FALSE; + count = (size_t) ((size + pagesize - 1) / pagesize); + vec = (char *) malloc (count * sizeof (unsigned char)); + + /* + * Darwin (and BSD?) define argument 3 of 'mincore' to be 'char *', + * while GNU libc defines it to be 'unsigned char *'. Casting the + * argument to 'void *' fixes this, but not with C++. So you might + * be SOL if you compile this with g++ (!) on GNU with -Werror. + */ +#ifdef __cplusplus + if (mincore (address, size, vec) != 0) +#else + if (mincore (address, size, (void *) vec) != 0) +#endif /* __cplusplus */ + { + free (vec); + JCL_ThrowException (env, IO_EXCEPTION, strerror (errno)); + return JNI_FALSE; + } + + for (i = 0; i < count; i++) + { + if ((vec[i] & 1) == 0) + return JNI_FALSE; + } + return JNI_TRUE; +#else + return JNI_FALSE; +#endif +} + +JNIEXPORT void JNICALL +Java_java_nio_MappedByteBufferImpl_loadImpl (JNIEnv *env, jobject this) +{ +#ifdef HAVE_MADVISE + void *address; + size_t size; + + get_raw_values (env, this, &address, &size); + if (address == NULL) + return; + + madvise (address, size, MADV_WILLNEED); +#else + JCL_ThrowException (env, IO_EXCEPTION, + "forcing mapped files into core not implemented"); +#endif /* HAVE_MADVISE */ +} + +JNIEXPORT void JNICALL +Java_java_nio_MappedByteBufferImpl_forceImpl (JNIEnv *env, jobject this) +{ +#ifdef HAVE_MSYNC + void *address; + size_t size; + + get_raw_values (env, this, &address, &size); + + if (address == NULL) + return; + + /* FIXME: is using MS_SYNC ok? Should we use MS_INVALIDATE? */ + if (msync (address, size, MS_SYNC) != 0) + { + JCL_ThrowException (env, IO_EXCEPTION, strerror (errno)); + } +#else + JCL_ThrowException (env, IO_EXCEPTION, + "forcing mapped files to disk not implemented"); +#endif /* HAVE_MSYNC */ +} diff --git a/libjava/classpath/native/jni/java-nio/java_nio_VMDirectByteBuffer.c b/libjava/classpath/native/jni/java-nio/java_nio_VMDirectByteBuffer.c new file mode 100644 index 000000000..bfee7e9dc --- /dev/null +++ b/libjava/classpath/native/jni/java-nio/java_nio_VMDirectByteBuffer.c @@ -0,0 +1,130 @@ +/* java_nio_VMDirectByteBuffer.c - Native methods for VMDirectByteBuffer + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +#include <config.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +#include <jni.h> +#include <jcl.h> + +#include "java_nio_VMDirectByteBuffer.h" + +JNIEXPORT jobject JNICALL +Java_java_nio_VMDirectByteBuffer_allocate + (JNIEnv * env, jclass clazz __attribute__ ((__unused__)), jint capacity) +{ + void *buffer; + + buffer = malloc (capacity); + + if (buffer == NULL) + { + JCL_ThrowException (env, "java/lang/OutOfMemoryError", + "unable to allocate memory for direct byte buffer"); + return 0; + } + + memset (buffer, 0, capacity); + + return JCL_NewRawDataObject (env, buffer); +} + +JNIEXPORT void JNICALL +Java_java_nio_VMDirectByteBuffer_free + (JNIEnv * env, jclass clazz __attribute__ ((__unused__)), jobject address) +{ + free (JCL_GetRawData (env, address)); +} + +JNIEXPORT jbyte JNICALL +Java_java_nio_VMDirectByteBuffer_get__Lgnu_classpath_Pointer_2I + (JNIEnv * env, jclass clazz __attribute__ ((__unused__)), + jobject address, jint index) +{ + return ((jbyte *) JCL_GetRawData (env, address))[index]; +} + +JNIEXPORT void JNICALL +Java_java_nio_VMDirectByteBuffer_put__Lgnu_classpath_Pointer_2IB + (JNIEnv * env, jclass clazz __attribute__ ((__unused__)), + jobject address, jint index, jbyte value) +{ + jbyte *pointer = (jbyte *) JCL_GetRawData (env, address) + index; + *pointer = value; +} + +JNIEXPORT void JNICALL +Java_java_nio_VMDirectByteBuffer_get__Lgnu_classpath_Pointer_2I_3BII + (JNIEnv * env, jclass clazz __attribute__ ((__unused__)), + jobject address, jint index, jbyteArray dst, jint dst_offset, jint dst_len) +{ + jbyte *src = (jbyte *) JCL_GetRawData (env, address) + index; + jbyte *_dst = (*env)->GetByteArrayElements (env, dst, NULL); + memcpy (_dst + dst_offset, src, dst_len); + (*env)->ReleaseByteArrayElements (env, dst, _dst, 0); +} + +JNIEXPORT void JNICALL +Java_java_nio_VMDirectByteBuffer_put__Lgnu_classpath_Pointer_2I_3BII + (JNIEnv *env, jclass clazz __attribute__ ((__unused__)), + jobject address, jint index, jbyteArray src, jint src_offset, jint src_len) +{ + jbyte *_src = (*env)->GetByteArrayElements (env, src, NULL); + jbyte *dst = (jbyte *)JCL_GetRawData (env, address); + memcpy (dst + index, _src + src_offset, src_len); + (*env)->ReleaseByteArrayElements (env, src, _src, 0); +} + +JNIEXPORT void JNICALL +Java_java_nio_VMDirectByteBuffer_shiftDown + (JNIEnv * env, jclass clazz __attribute__ ((__unused__)), + jobject address, jint dst_offset, jint src_offset, jint count) +{ + jbyte *dst = (jbyte *) JCL_GetRawData (env, address) + dst_offset; + jbyte *src = (jbyte *) JCL_GetRawData (env, address) + src_offset; + memmove (dst, src, count); +} + +JNIEXPORT jobject JNICALL +Java_java_nio_VMDirectByteBuffer_adjustAddress + (JNIEnv * env, jclass clazz __attribute__ ((__unused__)), + jobject address, jint offset) +{ + return JCL_NewRawDataObject (env, (jbyte *) JCL_GetRawData (env, address) + offset); +} diff --git a/libjava/classpath/native/jni/java-nio/javanio.c b/libjava/classpath/native/jni/java-nio/javanio.c new file mode 100644 index 000000000..a7018b347 --- /dev/null +++ b/libjava/classpath/native/jni/java-nio/javanio.c @@ -0,0 +1,144 @@ +/* javanio.c -- implementations of functions in javanio.h. + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is a part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at +your option) any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 +USA + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +/* + * Note, because these functions are trivial, and should be inlined, + * we include this file in the header, and do not compile it. + */ + +#include <fcntl.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/socket.h> +#ifdef HAVE_SYS_SELECT_H +#include <sys/select.h> +#endif +#include <sys/uio.h> + +CPNIO_EXPORT ssize_t +cpnio_read (int fd, void *buf, size_t nbytes) +{ + return read (fd, buf, nbytes); +} + +CPNIO_EXPORT ssize_t +cpnio_readv (int fd, const struct iovec *iov, int iovcnt) +{ + return readv (fd, iov, iovcnt); +} + +CPNIO_EXPORT ssize_t +cpnio_write (int fd, const void *buf, size_t nbytes) +{ + return write (fd, buf, nbytes); +} + +CPNIO_EXPORT ssize_t +cpnio_writev (int fd, const struct iovec *iov, size_t iovcnt) +{ + return writev (fd, iov, iovcnt); +} + +CPNIO_EXPORT int +cpnio_socket (int domain, int type, int protocol) +{ + return socket (domain, type, protocol); +} + +CPNIO_EXPORT int +cpnio_connect (int fd, const struct sockaddr *addr, socklen_t addrlen) +{ + return connect (fd, addr, addrlen); +} + +CPNIO_EXPORT int +cpnio_accept (int fd, struct sockaddr *addr, socklen_t *addrlen) +{ + fd_set rset; + struct timeval tv; + socklen_t tvlen = sizeof(tv); + int ret; + + tv.tv_sec = 0; + tv.tv_usec = 0; + getsockopt (fd, SOL_SOCKET, SO_RCVTIMEO, &tv, &tvlen); + if (tv.tv_sec > 0 || tv.tv_usec > 0) + { + FD_ZERO(&rset); + FD_SET(fd,&rset); + ret = select (fd+1,&rset,NULL,NULL,&tv); + if (ret == 0) + { + errno = EAGAIN; + return -1; + } + } + return accept (fd, addr, addrlen); +} + +CPNIO_EXPORT ssize_t +cpnio_sendto (int fd, const void *msg, size_t len, int flags, + const struct sockaddr *to, socklen_t tolen) +{ + return sendto (fd, msg, len, flags, to, tolen); +} + +CPNIO_EXPORT ssize_t +cpnio_recvfrom (int fd, void *buf, size_t len, int flags, + struct sockaddr *from, socklen_t *fromlen) +{ + return recvfrom (fd, buf, len, flags, from, fromlen); +} + +CPNIO_EXPORT int +cpnio_fcntl (int fd, int cmd, long arg) +{ +#ifdef HAVE_FCNTL + return fcntl (fd, cmd, arg); +#else + errno = ENOSUP; + return -1; +#endif /* HAVE_FCNTL */ +} + +CPNIO_EXPORT int +cpnio_select (int nfds, fd_set *readfds, fd_set *writefds, + fd_set *excepfds, struct timeval *timeo) +{ + return select (nfds, readfds, writefds, excepfds, timeo); +} diff --git a/libjava/classpath/native/jni/java-nio/javanio.h b/libjava/classpath/native/jni/java-nio/javanio.h new file mode 100644 index 000000000..cc31cf3c1 --- /dev/null +++ b/libjava/classpath/native/jni/java-nio/javanio.h @@ -0,0 +1,334 @@ +/* javanio.h -- reference implementation of native functions. + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is a part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at +your option) any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 +USA + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +#ifndef __JAVANIO_H__ +#define __JAVANIO_H__ + +#include <sys/time.h> + +/** + * This header defines functions that are called by our JNI reference + * implementation of java.nio.*. In our reference implementation, these + * functions map exactly to their counterparts in POSIX; in implementations + * that can't use these functions directly (such as systems that use user-land + * threads, and thus can't call blocking system calls directly) can provide + * their own implementations suitable for their system. + */ + +/** + * This macro is used in all function prototypes below; if any additional + * keywords need to be added to a prototype, declare them in this macro. + */ +#define CPNIO_EXPORT static inline + +/** + * Read bytes from the given file descriptor into the given memory address, which + * has sufficient space for NBYTES bytes. + * + * \param fd The file descriptor to read from. + * \param buf The memory address to read bytes into. + * \param nbytes The number of bytes available to store in BUF. + * \return The number of bytes read, possibly zero, on success; return -1 on failure, + * and set ERRNO to an appropriate value. + * \see read(2) + * + * Allowed errno values: + * [EBADF] If FD is not a valid file descriptor, or is not open for reading. + * [EFAULT] If BUF points outside the process's address space. + * [EIO] An I/O error occurrs. + * [EINTR] If the read is interrupted by a signal. + * [EINVAL] If FD is negative. + * [EAGAIN] If FD was marked for non-blocking I/O, and no data were ready to + * be read. + */ +CPNIO_EXPORT ssize_t cpnio_read (int fd, void *buf, size_t nbytes); + +/* + * Read bytes from a file descriptor into a sequence of IO buffers. + * + * The iovec structure is defined as: + * + * struct iovec { + * char *iov_base; + * size_t iov_len; + * }; + * + * The call to _cp_readv should do a scattering read, where for each struct iovec + * in the supplied list, up to IOV_LEN bytes are read into IOV_BASE. The function + * returns the total number of bytes read into all supplied buffers. + * + * \param fd The file descriptor. + * \param iov A pointer to the head of a list of iovec structures. + * \param iovcnt The number of iovec structures pointed to by IOV. + * \return The total number of bytes read accross all buffers, possibly zero. On + * error, -1 is returned and ERRNO is set. + * \see readv(2) + * + * Allowed ERRNO values include all of those listed for _cp_read, as well as the + * following: + * [EINVAL] If IOVCNT overflows the maximum number of iovec structures + * this platform supports (usually 16), if any IOV_LEN value + * is negative, or if the sum of all IOV_LEN values is too + * large to be stored in a ssize_t (usually a 32-bit integer). + * [EFAULT] If part of IOV points outside the process's address space. + */ +CPNIO_EXPORT ssize_t cpnio_readv (int fd, const struct iovec *iov, int iovcnt); + +/* + * Write NBYTES bytes from BUF to the file descriptor FD, returning the number + * of bytes successfully written. + * + * \param fd The file descriptor. + * \param buf A pointer to the bytes to write. + * \param nbytes The maximum number of bytes to write. + * \return The number of bytes written to the file descriptor, possibly zero. -1 + * is returned if an error is encountered, and ERRNO will be set. + * \see write(2) + * + * Allowed ERRNO values: + * [EBADF] If FD is not a valid file descriptor or is not open for writing. + * [EPIPE] If FD is a pipe, when the other side is disconnected; if FD is a + * socket, when the peer is not connected. + * [EFBIG] When FD is a file, and writing to it overflows the process's + * or the system's maximim file size. + * [EFAULT] If the buffer to write points outside the process's address + * space. + * [EINVAL] If the descriptor FD is negative. + * [ENOSPC] If FD is a file, and there is insufficient space on the + * filesystem. + * [EDQUOT] If FD is a file, and the user's disk quota has been exceeded. + * [EIO] If an I/O error occurs. + * [EINTR] If the call is interrupted by a signal. + * [EAGAIN] If FD is in non-blocking mode, and no bytes could be immediately + * written. + */ +CPNIO_EXPORT ssize_t cpnio_write (int fd, const void *buf, size_t nbytes); + +/* + * Write data from a sequence of IOVCNT buffers IOV to a file descriptor FD. + * + * \param fd The file descriptor. + * \param iov The list of buffers to write. + * \param iovcnt The number of iovec structures pointed to by IOV. + * \return The total number of bytes written from the given buffers, possibly + * zero. -1 if an error occurs, and ERRNO will be set. + * \see writev(2) + * + * Allowed ERRNO values include those mentioned in _cp_write, as well as: + * [EDESTADDRREQ] If the descriptor is a datagram socket, and the peer is + * no longer available. + * [EINVAL] If IOVCNT is out of range, if any IOV_LEN value is + * negative, or if the sum of all IOVCNT IOV_LEN values + * will overflow a ssize_t. + * [ENOBUFS] If the mbuf pool is exhausted (???). + */ +CPNIO_EXPORT ssize_t cpnio_writev (int fd, const struct iovec *iov, size_t iovcnt); + +/** + * Open a new, unbound and unconnected socket. + * + * \param domain The socket domain. Implementations need only handle AF_INET. + * \param type The socket type; implementations need only handle types + * SOCK_STREAM (for streaming sockets) and SOCK_DGRAM (for datagram sockets). + * \param protocol This should always be 0. It can be ignored. + * \return A new file descriptor pointing to a newly created socket, or -1 on + * error, and ERRNO set. + * + * Allowed ERRNO values: + * [EPROTONOSUPPORT] If TYPE is unrecognized. + * [EMFILE] If a new file descriptor cannot be allocated, because + * the process's descriptor table is full. + * [ENFILE] Likewise, but when the system table is full. + * [EACCES] If this operation is not allowed. + * [ENOBUFS] If there is not enough buffer space available for the + * new socket. + */ +CPNIO_EXPORT int cpnio_socket (int domain, int type, int protocol); + +/** + * Connect a socket to a remote address. + * + * \param fd The file descriptor of the socket to connect. + * \param addr The address to connect to. In practice, this should be + * either a `struct sockaddr_in' or a `struct sockaddr_in6'. + * \param addrlen The size of the address structure passed by ADDR. + * \return Zero if the connect succeeds. -1 on error, and ERRNO should be set. + * + * Allowed ERRNO values: + * [EBADF] If FD is not a valid file descriptor. + * [ENOTSOCK] If FD is not a socket descriptor. + * [EADDRNOTAVAIL] If ADDR is not available for use to this process. + * [EAFNOSUPPORT] If the address family of ADDR is not supported. + * [EISCONN] If the socket is already connected. + * [ETIMEDOUT] If the connection could not be made in a reasonable + * amount of time. + * [ECONNREFUSED] If the connection attempt was rejected. + * [ENETUNREACH] If the network ADDR is on is unreachable. + * [EADDRINUSE] If the address is already in use. + * [EFAULT] If ADDR points outside the addressable space. + * [EINPROGRESS] If FD is in non-blocking mode, and the connection could + * not be completed immediately. + * [EALREADY] If FD is in non-blocking mode, and a connection attempt + * is still pending. + * [EACCESS] If ADDR is the broadcast address, and the socket option + * SO_BROADCAST is not set. + */ +CPNIO_EXPORT int cpnio_connect (int fd, const struct sockaddr *addr, socklen_t addrlen); + +/** + * Accept an incoming connection on a socket, returning a new socket for + * the connection, and storing the peer address in ADDR. + * + * \param fd The socket file descriptor. + * \param addr The structure to store the peer address in. + * \param addrlen The size of the data available in ADDR; upon return, the + * number of bytes stored in ADDR will be placed here. + * \return The new socket file descriptor, or -1 on error, and ERRNO set. + * + * Allowed ERRNO values: + * [EBADF] If FD is not a valid file descriptor. + * [ENOTSOCK] If FD in not a socket descriptor. + * [EOPNOTSUPP] If the socket is not a SOCK_STREAM socket. + * [EFAULT] If ADDR points outside the process's addressable space. + * [EWOULDBLOCK] If the socket is in non-blocking mode, and no connection + * attempt is currently ready. + * [EMFILE] If the process's descriptor table is full. + * [ENFILE] If the system's descriptor table is full. + */ +CPNIO_EXPORT int cpnio_accept (int fd, struct sockaddr *addr, socklen_t *addrlen); + +/** + * Send a datagram to the given address. + * + * \param fd The socket file descriptor. + * \param msg A pointer to the message to send. + * \param len The size of the message to send. + * \param flags Flags for sending. + * \param to The remote address to send the message to. + * \param tolen The size of the TO address structure. + * \return The number of bytes written, possibly zero, on success. Returns + * -1 on failure, and sets ERRNO. + * \see sendto(2) + * + * Allowed ERRNO values: + * [EBADF] + * [ENOTSOCK] + * [EFAULT] + * [EMSGSIZE] + * [EAGAIN] + * [ENOBUFS] + * [EACCES] + * [EHOSTUNREACH] + */ +CPNIO_EXPORT ssize_t cpnio_sendto (int fd, const void *msg, size_t len, int flags, + const struct sockaddr *to, socklen_t tolen); + +/** + * Receive a message on a socket, storing the remote host's address in + * FROM. + * + * \param fd The socket file descriptor. + * \param buf The buffer to store received bytes in. + * \param flags Flags to control the receive. + * \param from Where to store the remote address. + * \param fromlen Pointer to the size of FROM; on return, it will contain the + * size of the structure placed in FROM. + * \return The number of bytes received on success. -1 on error, and ERRNO will + * be set. + * \see recvfrom(2) + * + * Allewed ERRNO values: + * [EBADF] FD is not a valid file descriptor. + * [ENOTCONN] If the socket is stream-oriented, and no prior call to + * connect(2) was made. + * [ENOTSOCK] FD is not a socket. + * [EAGAIN] FD is in non-blocking mode, and no message was + * immediately available. + * [EINTR] The system call was interrupted by a signal. + * [EFAULT] BUF, FROM, or FROMLEN lie outside the process's address + * space. + */ +CPNIO_EXPORT ssize_t cpnio_recvfrom (int fd, void *buf, size_t len, int flags, + struct sockaddr *from, socklen_t *fromlen); + + +/** + * Control file descriptor properties. + * + * \param fd The file descriptor to control. + * \param cmd The command to execute. + * \param arg The command argument. + * \return A value other than -1, specific to CMD. On error, -1 is + * returned, and ERRNO is set. + * + * Allowed ERRNO values: + * FIXME + */ +CPNIO_EXPORT int cpnio_fcntl (int fd, int cmd, long arg); + + +/** + * Select from one of the given file descriptor sets a descriptor that + * is ready for the given operation (read, write, etc.). + * + * \param nfds A value one larger than the largest file + * descriptor. + * \param readfds A set of file descriptors to select for + * readability. + * \param writefds A set of file descriptors to select for + * writability. + * \param exceptfds A set of file descriptors to select for + * exceptional conditions. + * \param tm The selection timeout. + * \return The number of file descriptors selected, possibly zero, or + * -1 on error (and with ERRNO set). + */ +CPNIO_EXPORT int cpnio_select (int nfds, fd_set *readfds, fd_set *writefds, + fd_set *exceptfds, struct timeval *tm); + +/* + * We include the implementation file here, because our reference + * implementation is trivial, and the functions are declared extern + * inline. + * + * Implementations that need different implementations of these functions + * SHOULD remove this line, and compile javanio.c as a separate unit. + */ +#include "javanio.c" + +#endif /* __JAVANIO_H__ */ |