diff options
Diffstat (limited to 'src/util')
82 files changed, 8470 insertions, 4169 deletions
diff --git a/src/util/Makefile.am b/src/util/Makefile.am index 8414ef2..425cc8c 100644 --- a/src/util/Makefile.am +++ b/src/util/Makefile.am @@ -2,6 +2,8 @@ INCLUDES = -I$(top_srcdir)/src/include -I$(top_builddir)/src/include plugindir = $(libdir)/gnunet +libexecdir= $(pkglibdir)/libexec/ + pkgcfgdir= $(pkgdatadir)/config.d/ dist_pkgcfg_DATA = \ @@ -14,7 +16,7 @@ if MINGW noinst_LTLIBRARIES = \ libgnunetutilwin.la libgnunetutilwin_la_SOURCES = \ - win.cc \ + win.c \ winproc.c libgnunetutilwin_la_LDFLAGS = \ -no-undefined -Wl,--export-all-symbols @@ -22,6 +24,7 @@ libgnunetutilwin_la_LIBADD = \ -lshell32 -liconv -lstdc++ \ -lcomdlg32 -lgdi32 -liphlpapi WINLIB = libgnunetutilwin.la +W32CAT = w32cat endif if !MINGW @@ -33,8 +36,11 @@ if USE_COVERAGE XLIB = -lgcov endif +w32cat_SOURCES = w32cat.c + noinst_PROGRAMS = \ gnunet-config-diff \ + $(W32CAT) \ test_common_logging_dummy @@ -70,6 +76,7 @@ libgnunetutil_la_SOURCES = \ container_slist.c \ crypto_aes.c \ crypto_crc.c \ + crypto_ecc.c \ crypto_hash.c \ crypto_hkdf.c \ crypto_kdf.c \ @@ -107,17 +114,23 @@ libgnunetutil_la_LIBADD = \ $(GCLIBADD) $(WINLIB) \ $(LIBGCRYPT_LIBS) \ $(LTLIBICONV) \ + $(LTLIBINTL) \ -lltdl -lz -lunistring $(XLIB) libgnunetutil_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) \ - -version-info 8:0:0 + -version-info 11:0:2 + +libexec_PROGRAMS = \ + gnunet-service-resolver bin_PROGRAMS = \ - gnunet-service-resolver \ gnunet-resolver \ - gnunet-rsa + gnunet-config \ + gnunet-ecc \ + gnunet-rsa \ + gnunet-uri gnunet_service_resolver_SOURCES = \ @@ -142,10 +155,37 @@ gnunet_rsa_SOURCES = \ gnunet-rsa.c gnunet_rsa_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ - $(GN_LIBINTL) + $(GN_LIBINTL) -lgcrypt gnunet_rsa_DEPENDENCIES = \ libgnunetutil.la + +gnunet_ecc_SOURCES = \ + gnunet-ecc.c +gnunet_ecc_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(GN_LIBINTL) -lgcrypt +gnunet_ecc_DEPENDENCIES = \ + libgnunetutil.la + + +gnunet_config_SOURCES = \ + gnunet-config.c +gnunet_config_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(GN_LIBINTL) +gnunet_config_DEPENDENCIES = \ + libgnunetutil.la + + +gnunet_uri_SOURCES = \ + gnunet-uri.c +gnunet_uri_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(GN_LIBINTL) +gnunet_uri_DEPENDENCIES = \ + libgnunetutil.la + plugin_LTLIBRARIES = \ libgnunet_plugin_test.la @@ -156,7 +196,8 @@ libgnunet_plugin_test_la_LDFLAGS = \ if HAVE_BENCHMARKS BENCHMARKS = \ - perf_crypto_hash + perf_crypto_hash \ + perf_malloc endif check_PROGRAMS = \ @@ -174,6 +215,7 @@ check_PROGRAMS = \ test_crypto_aes \ test_crypto_aes_weak \ test_crypto_crc \ + test_crypto_ecc \ test_crypto_hash \ test_crypto_hkdf \ test_crypto_ksk \ @@ -223,6 +265,8 @@ test_os_start_process_SOURCES = \ test_os_start_process.c test_os_start_process_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la +test_os_start_process_DEPENDENCIES = \ + $(WINCAT) test_client_SOURCES = \ test_client.c @@ -295,6 +339,11 @@ test_crypto_crc_SOURCES = \ test_crypto_crc_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la +test_crypto_ecc_SOURCES = \ + test_crypto_ecc.c +test_crypto_ecc_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la + test_crypto_hash_SOURCES = \ test_crypto_hash.c test_crypto_hash_LDADD = \ @@ -456,6 +505,11 @@ perf_crypto_hash_SOURCES = \ perf_crypto_hash_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la +perf_malloc_SOURCES = \ + perf_malloc.c +perf_malloc_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la + EXTRA_DIST = \ test_configuration_data.conf \ diff --git a/src/util/Makefile.in b/src/util/Makefile.in index 5ea0157..9406228 100644 --- a/src/util/Makefile.in +++ b/src/util/Makefile.in @@ -1,9 +1,9 @@ -# Makefile.in generated by automake 1.11.1 from Makefile.am. +# Makefile.in generated by automake 1.11.6 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. +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 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. @@ -18,6 +18,23 @@ VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ @@ -37,10 +54,11 @@ POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ -noinst_PROGRAMS = gnunet-config-diff$(EXEEXT) \ +noinst_PROGRAMS = gnunet-config-diff$(EXEEXT) $(am__EXEEXT_3) \ test_common_logging_dummy$(EXEEXT) -bin_PROGRAMS = gnunet-service-resolver$(EXEEXT) \ - gnunet-resolver$(EXEEXT) gnunet-rsa$(EXEEXT) +libexec_PROGRAMS = gnunet-service-resolver$(EXEEXT) +bin_PROGRAMS = gnunet-resolver$(EXEEXT) gnunet-config$(EXEEXT) \ + gnunet-ecc$(EXEEXT) gnunet-rsa$(EXEEXT) gnunet-uri$(EXEEXT) check_PROGRAMS = test_bio$(EXEEXT) test_client$(EXEEXT) \ test_common_allocation$(EXEEXT) test_common_endian$(EXEEXT) \ test_common_logging$(EXEEXT) test_configuration$(EXEEXT) \ @@ -49,11 +67,12 @@ check_PROGRAMS = test_bio$(EXEEXT) test_client$(EXEEXT) \ test_container_multihashmap$(EXEEXT) \ test_container_heap$(EXEEXT) test_container_slist$(EXEEXT) \ test_crypto_aes$(EXEEXT) test_crypto_aes_weak$(EXEEXT) \ - test_crypto_crc$(EXEEXT) test_crypto_hash$(EXEEXT) \ - test_crypto_hkdf$(EXEEXT) test_crypto_ksk$(EXEEXT) \ - test_crypto_random$(EXEEXT) test_crypto_rsa$(EXEEXT) \ - test_disk$(EXEEXT) test_getopt$(EXEEXT) \ - test_connection$(EXEEXT) test_connection_addressing$(EXEEXT) \ + test_crypto_crc$(EXEEXT) test_crypto_ecc$(EXEEXT) \ + test_crypto_hash$(EXEEXT) test_crypto_hkdf$(EXEEXT) \ + test_crypto_ksk$(EXEEXT) test_crypto_random$(EXEEXT) \ + test_crypto_rsa$(EXEEXT) test_disk$(EXEEXT) \ + test_getopt$(EXEEXT) test_connection$(EXEEXT) \ + test_connection_addressing$(EXEEXT) \ test_connection_receive_cancel$(EXEEXT) \ test_connection_timeout$(EXEEXT) \ test_connection_timeout_no_connect$(EXEEXT) \ @@ -75,14 +94,15 @@ DIST_COMMON = $(dist_pkgcfg_DATA) $(srcdir)/Makefile.am \ ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/align.m4 $(top_srcdir)/m4/argz.m4 \ - $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/iconv.m4 \ - $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ - $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libcurl.m4 \ - $(top_srcdir)/m4/libgcrypt.m4 $(top_srcdir)/m4/libtool.m4 \ - $(top_srcdir)/m4/libunistring.m4 $(top_srcdir)/m4/ltdl.m4 \ - $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ - $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ - $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \ + $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/glib-2.0.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libcurl.m4 $(top_srcdir)/m4/libgcrypt.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/libunistring.m4 \ + $(top_srcdir)/m4/ltdl.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ + $(top_srcdir)/m4/pkg.m4 $(top_srcdir)/m4/po.m4 \ $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/acinclude.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ @@ -112,17 +132,23 @@ am__nobase_list = $(am__nobase_strip_setup); \ am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(plugindir)" \ - "$(DESTDIR)$(bindir)" "$(DESTDIR)$(pkgcfgdir)" \ - "$(DESTDIR)$(pkgcfgdir)" + "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libexecdir)" \ + "$(DESTDIR)$(pkgcfgdir)" "$(DESTDIR)$(pkgcfgdir)" LTLIBRARIES = $(lib_LTLIBRARIES) $(noinst_LTLIBRARIES) \ $(plugin_LTLIBRARIES) libgnunet_plugin_test_la_LIBADD = am_libgnunet_plugin_test_la_OBJECTS = test_plugin_plug.lo libgnunet_plugin_test_la_OBJECTS = \ $(am_libgnunet_plugin_test_la_OBJECTS) -AM_V_lt = $(am__v_lt_$(V)) -am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY)) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent libgnunet_plugin_test_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ @@ -130,38 +156,45 @@ libgnunet_plugin_test_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(LDFLAGS) -o $@ am__DEPENDENCIES_1 = libgnunetutil_la_DEPENDENCIES = $(WINLIB) $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) am_libgnunetutil_la_OBJECTS = bandwidth.lo bio.lo client.lo \ common_allocation.lo common_endian.lo common_logging.lo \ configuration.lo connection.lo container_bloomfilter.lo \ container_heap.lo container_meta_data.lo \ container_multihashmap.lo container_slist.lo crypto_aes.lo \ - crypto_crc.lo crypto_hash.lo crypto_hkdf.lo crypto_kdf.lo \ - crypto_ksk.lo crypto_random.lo crypto_rsa.lo disk.lo getopt.lo \ - getopt_helpers.lo helper.lo load.lo network.lo \ - os_installation.lo os_network.lo os_priority.lo peer.lo \ - plugin.lo program.lo pseudonym.lo resolver_api.lo scheduler.lo \ - server.lo server_mst.lo server_nc.lo server_tc.lo service.lo \ - signal.lo strings.lo time.lo speedup.lo + crypto_crc.lo crypto_ecc.lo crypto_hash.lo crypto_hkdf.lo \ + crypto_kdf.lo crypto_ksk.lo crypto_random.lo crypto_rsa.lo \ + disk.lo getopt.lo getopt_helpers.lo helper.lo load.lo \ + network.lo os_installation.lo os_network.lo os_priority.lo \ + peer.lo plugin.lo program.lo pseudonym.lo resolver_api.lo \ + scheduler.lo server.lo server_mst.lo server_nc.lo server_tc.lo \ + service.lo signal.lo strings.lo time.lo speedup.lo libgnunetutil_la_OBJECTS = $(am_libgnunetutil_la_OBJECTS) libgnunetutil_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libgnunetutil_la_LDFLAGS) $(LDFLAGS) \ -o $@ libgnunetutilwin_la_DEPENDENCIES = -am__libgnunetutilwin_la_SOURCES_DIST = win.cc winproc.c +am__libgnunetutilwin_la_SOURCES_DIST = win.c winproc.c @MINGW_TRUE@am_libgnunetutilwin_la_OBJECTS = win.lo winproc.lo libgnunetutilwin_la_OBJECTS = $(am_libgnunetutilwin_la_OBJECTS) -libgnunetutilwin_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ - $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ - $(AM_CXXFLAGS) $(CXXFLAGS) $(libgnunetutilwin_la_LDFLAGS) \ +libgnunetutilwin_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) $(libgnunetutilwin_la_LDFLAGS) \ $(LDFLAGS) -o $@ @MINGW_TRUE@am_libgnunetutilwin_la_rpath = @MINGW_FALSE@am__EXEEXT_1 = test_server_with_client_unix$(EXEEXT) -@HAVE_BENCHMARKS_TRUE@am__EXEEXT_2 = perf_crypto_hash$(EXEEXT) -PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS) +@HAVE_BENCHMARKS_TRUE@am__EXEEXT_2 = perf_crypto_hash$(EXEEXT) \ +@HAVE_BENCHMARKS_TRUE@ perf_malloc$(EXEEXT) +@MINGW_TRUE@am__EXEEXT_3 = w32cat$(EXEEXT) +PROGRAMS = $(bin_PROGRAMS) $(libexec_PROGRAMS) $(noinst_PROGRAMS) +am_gnunet_config_OBJECTS = gnunet-config.$(OBJEXT) +gnunet_config_OBJECTS = $(am_gnunet_config_OBJECTS) am_gnunet_config_diff_OBJECTS = gnunet-config-diff.$(OBJEXT) gnunet_config_diff_OBJECTS = $(am_gnunet_config_diff_OBJECTS) +am_gnunet_ecc_OBJECTS = gnunet-ecc.$(OBJEXT) +gnunet_ecc_OBJECTS = $(am_gnunet_ecc_OBJECTS) am_gnunet_resolver_OBJECTS = gnunet-resolver.$(OBJEXT) gnunet_resolver_OBJECTS = $(am_gnunet_resolver_OBJECTS) am_gnunet_rsa_OBJECTS = gnunet-rsa.$(OBJEXT) @@ -170,10 +203,15 @@ am_gnunet_service_resolver_OBJECTS = \ gnunet-service-resolver.$(OBJEXT) gnunet_service_resolver_OBJECTS = \ $(am_gnunet_service_resolver_OBJECTS) +am_gnunet_uri_OBJECTS = gnunet-uri.$(OBJEXT) +gnunet_uri_OBJECTS = $(am_gnunet_uri_OBJECTS) am_perf_crypto_hash_OBJECTS = perf_crypto_hash.$(OBJEXT) perf_crypto_hash_OBJECTS = $(am_perf_crypto_hash_OBJECTS) perf_crypto_hash_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la +am_perf_malloc_OBJECTS = perf_malloc.$(OBJEXT) +perf_malloc_OBJECTS = $(am_perf_malloc_OBJECTS) +perf_malloc_DEPENDENCIES = $(top_builddir)/src/util/libgnunetutil.la am_test_bio_OBJECTS = test_bio.$(OBJEXT) test_bio_OBJECTS = $(am_test_bio_OBJECTS) test_bio_DEPENDENCIES = $(top_builddir)/src/util/libgnunetutil.la @@ -279,6 +317,10 @@ am_test_crypto_crc_OBJECTS = test_crypto_crc.$(OBJEXT) test_crypto_crc_OBJECTS = $(am_test_crypto_crc_OBJECTS) test_crypto_crc_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la +am_test_crypto_ecc_OBJECTS = test_crypto_ecc.$(OBJEXT) +test_crypto_ecc_OBJECTS = $(am_test_crypto_ecc_OBJECTS) +test_crypto_ecc_DEPENDENCIES = \ + $(top_builddir)/src/util/libgnunetutil.la am_test_crypto_hash_OBJECTS = test_crypto_hash.$(OBJEXT) test_crypto_hash_OBJECTS = $(am_test_crypto_hash_OBJECTS) test_crypto_hash_DEPENDENCIES = \ @@ -315,8 +357,6 @@ test_os_priority_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la am_test_os_start_process_OBJECTS = test_os_start_process.$(OBJEXT) test_os_start_process_OBJECTS = $(am_test_os_start_process_OBJECTS) -test_os_start_process_DEPENDENCIES = \ - $(top_builddir)/src/util/libgnunetutil.la am_test_peer_OBJECTS = test_peer.$(OBJEXT) test_peer_OBJECTS = $(am_test_peer_OBJECTS) test_peer_DEPENDENCIES = $(top_builddir)/src/util/libgnunetutil.la @@ -379,6 +419,9 @@ test_strings_DEPENDENCIES = $(top_builddir)/src/util/libgnunetutil.la am_test_time_OBJECTS = test_time.$(OBJEXT) test_time_OBJECTS = $(am_test_time_OBJECTS) test_time_DEPENDENCIES = $(top_builddir)/src/util/libgnunetutil.la +am_w32cat_OBJECTS = w32cat.$(OBJEXT) +w32cat_OBJECTS = $(am_w32cat_OBJECTS) +w32cat_LDADD = $(LDADD) DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles @@ -389,43 +432,29 @@ LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) -AM_V_CC = $(am__v_CC_$(V)) -am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY)) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; -AM_V_at = $(am__v_at_$(V)) -am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ -AM_V_CCLD = $(am__v_CCLD_$(V)) -am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY)) +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; -CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ - $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ - $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ - $(AM_CXXFLAGS) $(CXXFLAGS) -AM_V_CXX = $(am__v_CXX_$(V)) -am__v_CXX_ = $(am__v_CXX_$(AM_DEFAULT_VERBOSITY)) -am__v_CXX_0 = @echo " CXX " $@; -CXXLD = $(CXX) -CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ - $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ -AM_V_CXXLD = $(am__v_CXXLD_$(V)) -am__v_CXXLD_ = $(am__v_CXXLD_$(AM_DEFAULT_VERBOSITY)) -am__v_CXXLD_0 = @echo " CXXLD " $@; -AM_V_GEN = $(am__v_GEN_$(V)) -am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; SOURCES = $(libgnunet_plugin_test_la_SOURCES) \ $(libgnunetutil_la_SOURCES) $(libgnunetutilwin_la_SOURCES) \ - $(gnunet_config_diff_SOURCES) $(gnunet_resolver_SOURCES) \ + $(gnunet_config_SOURCES) $(gnunet_config_diff_SOURCES) \ + $(gnunet_ecc_SOURCES) $(gnunet_resolver_SOURCES) \ $(gnunet_rsa_SOURCES) $(gnunet_service_resolver_SOURCES) \ - $(perf_crypto_hash_SOURCES) $(test_bio_SOURCES) \ + $(gnunet_uri_SOURCES) $(perf_crypto_hash_SOURCES) \ + $(perf_malloc_SOURCES) $(test_bio_SOURCES) \ $(test_client_SOURCES) $(test_common_allocation_SOURCES) \ $(test_common_endian_SOURCES) $(test_common_logging_SOURCES) \ $(test_common_logging_dummy_SOURCES) \ @@ -442,27 +471,29 @@ SOURCES = $(libgnunet_plugin_test_la_SOURCES) \ $(test_container_multihashmap_SOURCES) \ $(test_container_slist_SOURCES) $(test_crypto_aes_SOURCES) \ $(test_crypto_aes_weak_SOURCES) $(test_crypto_crc_SOURCES) \ - $(test_crypto_hash_SOURCES) $(test_crypto_hkdf_SOURCES) \ - $(test_crypto_ksk_SOURCES) $(test_crypto_random_SOURCES) \ - $(test_crypto_rsa_SOURCES) $(test_disk_SOURCES) \ - $(test_getopt_SOURCES) $(test_os_network_SOURCES) \ - $(test_os_priority_SOURCES) $(test_os_start_process_SOURCES) \ - $(test_peer_SOURCES) $(test_plugin_SOURCES) \ - $(test_program_SOURCES) $(test_pseudonym_SOURCES) \ - $(test_resolver_api_SOURCES) $(test_scheduler_SOURCES) \ - $(test_scheduler_delay_SOURCES) $(test_server_SOURCES) \ - $(test_server_disconnect_SOURCES) \ + $(test_crypto_ecc_SOURCES) $(test_crypto_hash_SOURCES) \ + $(test_crypto_hkdf_SOURCES) $(test_crypto_ksk_SOURCES) \ + $(test_crypto_random_SOURCES) $(test_crypto_rsa_SOURCES) \ + $(test_disk_SOURCES) $(test_getopt_SOURCES) \ + $(test_os_network_SOURCES) $(test_os_priority_SOURCES) \ + $(test_os_start_process_SOURCES) $(test_peer_SOURCES) \ + $(test_plugin_SOURCES) $(test_program_SOURCES) \ + $(test_pseudonym_SOURCES) $(test_resolver_api_SOURCES) \ + $(test_scheduler_SOURCES) $(test_scheduler_delay_SOURCES) \ + $(test_server_SOURCES) $(test_server_disconnect_SOURCES) \ $(test_server_mst_interrupt_SOURCES) \ $(test_server_with_client_SOURCES) \ $(test_server_with_client_unix_SOURCES) \ $(test_service_SOURCES) $(test_speedup_SOURCES) \ - $(test_strings_SOURCES) $(test_time_SOURCES) + $(test_strings_SOURCES) $(test_time_SOURCES) $(w32cat_SOURCES) DIST_SOURCES = $(libgnunet_plugin_test_la_SOURCES) \ $(libgnunetutil_la_SOURCES) \ $(am__libgnunetutilwin_la_SOURCES_DIST) \ - $(gnunet_config_diff_SOURCES) $(gnunet_resolver_SOURCES) \ + $(gnunet_config_SOURCES) $(gnunet_config_diff_SOURCES) \ + $(gnunet_ecc_SOURCES) $(gnunet_resolver_SOURCES) \ $(gnunet_rsa_SOURCES) $(gnunet_service_resolver_SOURCES) \ - $(perf_crypto_hash_SOURCES) $(test_bio_SOURCES) \ + $(gnunet_uri_SOURCES) $(perf_crypto_hash_SOURCES) \ + $(perf_malloc_SOURCES) $(test_bio_SOURCES) \ $(test_client_SOURCES) $(test_common_allocation_SOURCES) \ $(test_common_endian_SOURCES) $(test_common_logging_SOURCES) \ $(test_common_logging_dummy_SOURCES) \ @@ -479,21 +510,26 @@ DIST_SOURCES = $(libgnunet_plugin_test_la_SOURCES) \ $(test_container_multihashmap_SOURCES) \ $(test_container_slist_SOURCES) $(test_crypto_aes_SOURCES) \ $(test_crypto_aes_weak_SOURCES) $(test_crypto_crc_SOURCES) \ - $(test_crypto_hash_SOURCES) $(test_crypto_hkdf_SOURCES) \ - $(test_crypto_ksk_SOURCES) $(test_crypto_random_SOURCES) \ - $(test_crypto_rsa_SOURCES) $(test_disk_SOURCES) \ - $(test_getopt_SOURCES) $(test_os_network_SOURCES) \ - $(test_os_priority_SOURCES) $(test_os_start_process_SOURCES) \ - $(test_peer_SOURCES) $(test_plugin_SOURCES) \ - $(test_program_SOURCES) $(test_pseudonym_SOURCES) \ - $(test_resolver_api_SOURCES) $(test_scheduler_SOURCES) \ - $(test_scheduler_delay_SOURCES) $(test_server_SOURCES) \ - $(test_server_disconnect_SOURCES) \ + $(test_crypto_ecc_SOURCES) $(test_crypto_hash_SOURCES) \ + $(test_crypto_hkdf_SOURCES) $(test_crypto_ksk_SOURCES) \ + $(test_crypto_random_SOURCES) $(test_crypto_rsa_SOURCES) \ + $(test_disk_SOURCES) $(test_getopt_SOURCES) \ + $(test_os_network_SOURCES) $(test_os_priority_SOURCES) \ + $(test_os_start_process_SOURCES) $(test_peer_SOURCES) \ + $(test_plugin_SOURCES) $(test_program_SOURCES) \ + $(test_pseudonym_SOURCES) $(test_resolver_api_SOURCES) \ + $(test_scheduler_SOURCES) $(test_scheduler_delay_SOURCES) \ + $(test_server_SOURCES) $(test_server_disconnect_SOURCES) \ $(test_server_mst_interrupt_SOURCES) \ $(test_server_with_client_SOURCES) \ $(test_server_with_client_unix_SOURCES) \ $(test_service_SOURCES) $(test_speedup_SOURCES) \ - $(test_strings_SOURCES) $(test_time_SOURCES) + $(test_strings_SOURCES) $(test_time_SOURCES) $(w32cat_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac DATA = $(dist_pkgcfg_DATA) $(pkgcfg_DATA) ETAGS = etags CTAGS = ctags @@ -535,6 +571,10 @@ EXEEXT = @EXEEXT@ EXT_LIBS = @EXT_LIBS@ EXT_LIB_PATH = @EXT_LIB_PATH@ FGREP = @FGREP@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ GMSGFMT = @GMSGFMT@ GMSGFMT_015 = @GMSGFMT_015@ GNUNETDNS_GROUP = @GNUNETDNS_GROUP@ @@ -545,6 +585,7 @@ GN_LIBINTL = @GN_LIBINTL@ GN_LIB_LDFLAGS = @GN_LIB_LDFLAGS@ GN_PLUGIN_LDFLAGS = @GN_PLUGIN_LDFLAGS@ GN_USER_HOME_DIR = @GN_USER_HOME_DIR@ +GOBJECT_QUERY = @GOBJECT_QUERY@ GREP = @GREP@ HAVE_LIBUNISTRING = @HAVE_LIBUNISTRING@ INCLTDL = @INCLTDL@ @@ -567,6 +608,8 @@ LIBCURL_CPPFLAGS = @LIBCURL_CPPFLAGS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBGTOP_CFLAGS = @LIBGTOP_CFLAGS@ +LIBGTOP_LIBS = @LIBGTOP_LIBS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBLTDL = @LIBLTDL@ @@ -588,6 +631,7 @@ LT_CONFIG_H = @LT_CONFIG_H@ LT_DLLOADERS = @LT_DLLOADERS@ LT_DLPREOPEN = @LT_DLPREOPEN@ MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MONKEYPREFIX = @MONKEYPREFIX@ MSGFMT = @MSGFMT@ @@ -597,6 +641,7 @@ MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@ MYSQL_LDFLAGS = @MYSQL_LDFLAGS@ NM = @NM@ NMEDIT = @NMEDIT@ +NSS_DIR = @NSS_DIR@ OBJC = @OBJC@ OBJCDEPMODE = @OBJCDEPMODE@ OBJCFLAGS = @OBJCFLAGS@ @@ -612,6 +657,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ POSTGRES_CPPFLAGS = @POSTGRES_CPPFLAGS@ POSTGRES_LDFLAGS = @POSTGRES_LDFLAGS@ POSUB = @POSUB@ @@ -643,6 +689,7 @@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ @@ -665,6 +712,7 @@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ +gitcommand = @gitcommand@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ @@ -675,10 +723,9 @@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ -libexecdir = @libexecdir@ +libexecdir = $(pkglibdir)/libexec/ localedir = @localedir@ localstatedir = @localstatedir@ -lt_ECHO = @lt_ECHO@ ltdl_LIBOBJS = @ltdl_LIBOBJS@ ltdl_LTLIBOBJS = @ltdl_LTLIBOBJS@ mandir = @mandir@ @@ -696,6 +743,7 @@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ +svnversioncommand = @svnversioncommand@ sys_symbol_underscore = @sys_symbol_underscore@ sysconfdir = @sysconfdir@ target = @target@ @@ -719,7 +767,7 @@ pkgcfg_DATA = \ @MINGW_TRUE@ libgnunetutilwin.la @MINGW_TRUE@libgnunetutilwin_la_SOURCES = \ -@MINGW_TRUE@ win.cc \ +@MINGW_TRUE@ win.c \ @MINGW_TRUE@ winproc.c @MINGW_TRUE@libgnunetutilwin_la_LDFLAGS = \ @@ -730,9 +778,11 @@ pkgcfg_DATA = \ @MINGW_TRUE@ -lcomdlg32 -lgdi32 -liphlpapi @MINGW_TRUE@WINLIB = libgnunetutilwin.la +@MINGW_TRUE@W32CAT = w32cat @MINGW_FALSE@SERVER_CLIENT_UNIX = test_server_with_client_unix @USE_COVERAGE_TRUE@AM_CFLAGS = --coverage -O0 @USE_COVERAGE_TRUE@XLIB = -lgcov +w32cat_SOURCES = w32cat.c gnunet_config_diff_SOURCES = \ gnunet-config-diff.c @@ -768,6 +818,7 @@ libgnunetutil_la_SOURCES = \ container_slist.c \ crypto_aes.c \ crypto_crc.c \ + crypto_ecc.c \ crypto_hash.c \ crypto_hkdf.c \ crypto_kdf.c \ @@ -804,11 +855,12 @@ libgnunetutil_la_LIBADD = \ $(GCLIBADD) $(WINLIB) \ $(LIBGCRYPT_LIBS) \ $(LTLIBICONV) \ + $(LTLIBINTL) \ -lltdl -lz -lunistring $(XLIB) libgnunetutil_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) \ - -version-info 8:0:0 + -version-info 11:0:2 gnunet_service_resolver_SOURCES = \ gnunet-service-resolver.c @@ -835,11 +887,41 @@ gnunet_rsa_SOURCES = \ gnunet_rsa_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ - $(GN_LIBINTL) + $(GN_LIBINTL) -lgcrypt gnunet_rsa_DEPENDENCIES = \ libgnunetutil.la +gnunet_ecc_SOURCES = \ + gnunet-ecc.c + +gnunet_ecc_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(GN_LIBINTL) -lgcrypt + +gnunet_ecc_DEPENDENCIES = \ + libgnunetutil.la + +gnunet_config_SOURCES = \ + gnunet-config.c + +gnunet_config_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(GN_LIBINTL) + +gnunet_config_DEPENDENCIES = \ + libgnunetutil.la + +gnunet_uri_SOURCES = \ + gnunet-uri.c + +gnunet_uri_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(GN_LIBINTL) + +gnunet_uri_DEPENDENCIES = \ + libgnunetutil.la + plugin_LTLIBRARIES = \ libgnunet_plugin_test.la @@ -850,7 +932,8 @@ libgnunet_plugin_test_la_LDFLAGS = \ $(GN_PLUGIN_LDFLAGS) @HAVE_BENCHMARKS_TRUE@BENCHMARKS = \ -@HAVE_BENCHMARKS_TRUE@ perf_crypto_hash +@HAVE_BENCHMARKS_TRUE@ perf_crypto_hash \ +@HAVE_BENCHMARKS_TRUE@ perf_malloc @ENABLE_TEST_RUN_TRUE@TESTS = $(check_PROGRAMS) test_bio_SOURCES = \ @@ -865,6 +948,9 @@ test_os_start_process_SOURCES = \ test_os_start_process_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la +test_os_start_process_DEPENDENCIES = \ + $(WINCAT) + test_client_SOURCES = \ test_client.c @@ -950,6 +1036,12 @@ test_crypto_crc_SOURCES = \ test_crypto_crc_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la +test_crypto_ecc_SOURCES = \ + test_crypto_ecc.c + +test_crypto_ecc_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la + test_crypto_hash_SOURCES = \ test_crypto_hash.c @@ -1142,6 +1234,12 @@ perf_crypto_hash_SOURCES = \ perf_crypto_hash_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la +perf_malloc_SOURCES = \ + perf_malloc.c + +perf_malloc_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la + EXTRA_DIST = \ test_configuration_data.conf \ test_program_data.conf \ @@ -1153,7 +1251,7 @@ EXTRA_DIST = \ all: all-am .SUFFIXES: -.SUFFIXES: .c .cc .lo .o .obj +.SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ @@ -1188,7 +1286,6 @@ resolver.conf: $(top_builddir)/config.status $(srcdir)/resolver.conf.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) - test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)" @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ @@ -1196,6 +1293,8 @@ install-libLTLIBRARIES: $(lib_LTLIBRARIES) else :; fi; \ done; \ test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } @@ -1228,7 +1327,6 @@ clean-noinstLTLIBRARIES: done install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) @$(NORMAL_INSTALL) - test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)" @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ @@ -1236,6 +1334,8 @@ install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) else :; fi; \ done; \ test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(plugindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(plugindir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \ } @@ -1257,16 +1357,19 @@ clean-pluginLTLIBRARIES: echo "rm -f \"$${dir}/so_locations\""; \ rm -f "$${dir}/so_locations"; \ done -libgnunet_plugin_test.la: $(libgnunet_plugin_test_la_OBJECTS) $(libgnunet_plugin_test_la_DEPENDENCIES) +libgnunet_plugin_test.la: $(libgnunet_plugin_test_la_OBJECTS) $(libgnunet_plugin_test_la_DEPENDENCIES) $(EXTRA_libgnunet_plugin_test_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunet_plugin_test_la_LINK) -rpath $(plugindir) $(libgnunet_plugin_test_la_OBJECTS) $(libgnunet_plugin_test_la_LIBADD) $(LIBS) -libgnunetutil.la: $(libgnunetutil_la_OBJECTS) $(libgnunetutil_la_DEPENDENCIES) +libgnunetutil.la: $(libgnunetutil_la_OBJECTS) $(libgnunetutil_la_DEPENDENCIES) $(EXTRA_libgnunetutil_la_DEPENDENCIES) $(AM_V_CCLD)$(libgnunetutil_la_LINK) -rpath $(libdir) $(libgnunetutil_la_OBJECTS) $(libgnunetutil_la_LIBADD) $(LIBS) -libgnunetutilwin.la: $(libgnunetutilwin_la_OBJECTS) $(libgnunetutilwin_la_DEPENDENCIES) - $(AM_V_CXXLD)$(libgnunetutilwin_la_LINK) $(am_libgnunetutilwin_la_rpath) $(libgnunetutilwin_la_OBJECTS) $(libgnunetutilwin_la_LIBADD) $(LIBS) +libgnunetutilwin.la: $(libgnunetutilwin_la_OBJECTS) $(libgnunetutilwin_la_DEPENDENCIES) $(EXTRA_libgnunetutilwin_la_DEPENDENCIES) + $(AM_V_CCLD)$(libgnunetutilwin_la_LINK) $(am_libgnunetutilwin_la_rpath) $(libgnunetutilwin_la_OBJECTS) $(libgnunetutilwin_la_LIBADD) $(LIBS) install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) - test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)" @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p || test -f $$p1; \ @@ -1315,6 +1418,52 @@ clean-checkPROGRAMS: list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list +install-libexecPROGRAMS: $(libexec_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(libexecdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libexecdir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p || test -f $$p1; \ + then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-libexecPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(libexecdir)" && rm -f $$files + +clean-libexecPROGRAMS: + @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list clean-noinstPROGRAMS: @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ @@ -1324,165 +1473,183 @@ clean-noinstPROGRAMS: list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list -gnunet-config-diff$(EXEEXT): $(gnunet_config_diff_OBJECTS) $(gnunet_config_diff_DEPENDENCIES) +gnunet-config$(EXEEXT): $(gnunet_config_OBJECTS) $(gnunet_config_DEPENDENCIES) $(EXTRA_gnunet_config_DEPENDENCIES) + @rm -f gnunet-config$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gnunet_config_OBJECTS) $(gnunet_config_LDADD) $(LIBS) +gnunet-config-diff$(EXEEXT): $(gnunet_config_diff_OBJECTS) $(gnunet_config_diff_DEPENDENCIES) $(EXTRA_gnunet_config_diff_DEPENDENCIES) @rm -f gnunet-config-diff$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_config_diff_OBJECTS) $(gnunet_config_diff_LDADD) $(LIBS) -gnunet-resolver$(EXEEXT): $(gnunet_resolver_OBJECTS) $(gnunet_resolver_DEPENDENCIES) +gnunet-ecc$(EXEEXT): $(gnunet_ecc_OBJECTS) $(gnunet_ecc_DEPENDENCIES) $(EXTRA_gnunet_ecc_DEPENDENCIES) + @rm -f gnunet-ecc$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gnunet_ecc_OBJECTS) $(gnunet_ecc_LDADD) $(LIBS) +gnunet-resolver$(EXEEXT): $(gnunet_resolver_OBJECTS) $(gnunet_resolver_DEPENDENCIES) $(EXTRA_gnunet_resolver_DEPENDENCIES) @rm -f gnunet-resolver$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_resolver_OBJECTS) $(gnunet_resolver_LDADD) $(LIBS) -gnunet-rsa$(EXEEXT): $(gnunet_rsa_OBJECTS) $(gnunet_rsa_DEPENDENCIES) +gnunet-rsa$(EXEEXT): $(gnunet_rsa_OBJECTS) $(gnunet_rsa_DEPENDENCIES) $(EXTRA_gnunet_rsa_DEPENDENCIES) @rm -f gnunet-rsa$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_rsa_OBJECTS) $(gnunet_rsa_LDADD) $(LIBS) -gnunet-service-resolver$(EXEEXT): $(gnunet_service_resolver_OBJECTS) $(gnunet_service_resolver_DEPENDENCIES) +gnunet-service-resolver$(EXEEXT): $(gnunet_service_resolver_OBJECTS) $(gnunet_service_resolver_DEPENDENCIES) $(EXTRA_gnunet_service_resolver_DEPENDENCIES) @rm -f gnunet-service-resolver$(EXEEXT) $(AM_V_CCLD)$(LINK) $(gnunet_service_resolver_OBJECTS) $(gnunet_service_resolver_LDADD) $(LIBS) -perf_crypto_hash$(EXEEXT): $(perf_crypto_hash_OBJECTS) $(perf_crypto_hash_DEPENDENCIES) +gnunet-uri$(EXEEXT): $(gnunet_uri_OBJECTS) $(gnunet_uri_DEPENDENCIES) $(EXTRA_gnunet_uri_DEPENDENCIES) + @rm -f gnunet-uri$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(gnunet_uri_OBJECTS) $(gnunet_uri_LDADD) $(LIBS) +perf_crypto_hash$(EXEEXT): $(perf_crypto_hash_OBJECTS) $(perf_crypto_hash_DEPENDENCIES) $(EXTRA_perf_crypto_hash_DEPENDENCIES) @rm -f perf_crypto_hash$(EXEEXT) $(AM_V_CCLD)$(LINK) $(perf_crypto_hash_OBJECTS) $(perf_crypto_hash_LDADD) $(LIBS) -test_bio$(EXEEXT): $(test_bio_OBJECTS) $(test_bio_DEPENDENCIES) +perf_malloc$(EXEEXT): $(perf_malloc_OBJECTS) $(perf_malloc_DEPENDENCIES) $(EXTRA_perf_malloc_DEPENDENCIES) + @rm -f perf_malloc$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(perf_malloc_OBJECTS) $(perf_malloc_LDADD) $(LIBS) +test_bio$(EXEEXT): $(test_bio_OBJECTS) $(test_bio_DEPENDENCIES) $(EXTRA_test_bio_DEPENDENCIES) @rm -f test_bio$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_bio_OBJECTS) $(test_bio_LDADD) $(LIBS) -test_client$(EXEEXT): $(test_client_OBJECTS) $(test_client_DEPENDENCIES) +test_client$(EXEEXT): $(test_client_OBJECTS) $(test_client_DEPENDENCIES) $(EXTRA_test_client_DEPENDENCIES) @rm -f test_client$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_client_OBJECTS) $(test_client_LDADD) $(LIBS) -test_common_allocation$(EXEEXT): $(test_common_allocation_OBJECTS) $(test_common_allocation_DEPENDENCIES) +test_common_allocation$(EXEEXT): $(test_common_allocation_OBJECTS) $(test_common_allocation_DEPENDENCIES) $(EXTRA_test_common_allocation_DEPENDENCIES) @rm -f test_common_allocation$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_common_allocation_OBJECTS) $(test_common_allocation_LDADD) $(LIBS) -test_common_endian$(EXEEXT): $(test_common_endian_OBJECTS) $(test_common_endian_DEPENDENCIES) +test_common_endian$(EXEEXT): $(test_common_endian_OBJECTS) $(test_common_endian_DEPENDENCIES) $(EXTRA_test_common_endian_DEPENDENCIES) @rm -f test_common_endian$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_common_endian_OBJECTS) $(test_common_endian_LDADD) $(LIBS) -test_common_logging$(EXEEXT): $(test_common_logging_OBJECTS) $(test_common_logging_DEPENDENCIES) +test_common_logging$(EXEEXT): $(test_common_logging_OBJECTS) $(test_common_logging_DEPENDENCIES) $(EXTRA_test_common_logging_DEPENDENCIES) @rm -f test_common_logging$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_common_logging_OBJECTS) $(test_common_logging_LDADD) $(LIBS) -test_common_logging_dummy$(EXEEXT): $(test_common_logging_dummy_OBJECTS) $(test_common_logging_dummy_DEPENDENCIES) +test_common_logging_dummy$(EXEEXT): $(test_common_logging_dummy_OBJECTS) $(test_common_logging_dummy_DEPENDENCIES) $(EXTRA_test_common_logging_dummy_DEPENDENCIES) @rm -f test_common_logging_dummy$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_common_logging_dummy_OBJECTS) $(test_common_logging_dummy_LDADD) $(LIBS) -test_common_logging_runtime_loglevels$(EXEEXT): $(test_common_logging_runtime_loglevels_OBJECTS) $(test_common_logging_runtime_loglevels_DEPENDENCIES) +test_common_logging_runtime_loglevels$(EXEEXT): $(test_common_logging_runtime_loglevels_OBJECTS) $(test_common_logging_runtime_loglevels_DEPENDENCIES) $(EXTRA_test_common_logging_runtime_loglevels_DEPENDENCIES) @rm -f test_common_logging_runtime_loglevels$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_common_logging_runtime_loglevels_OBJECTS) $(test_common_logging_runtime_loglevels_LDADD) $(LIBS) -test_configuration$(EXEEXT): $(test_configuration_OBJECTS) $(test_configuration_DEPENDENCIES) +test_configuration$(EXEEXT): $(test_configuration_OBJECTS) $(test_configuration_DEPENDENCIES) $(EXTRA_test_configuration_DEPENDENCIES) @rm -f test_configuration$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_configuration_OBJECTS) $(test_configuration_LDADD) $(LIBS) -test_connection$(EXEEXT): $(test_connection_OBJECTS) $(test_connection_DEPENDENCIES) +test_connection$(EXEEXT): $(test_connection_OBJECTS) $(test_connection_DEPENDENCIES) $(EXTRA_test_connection_DEPENDENCIES) @rm -f test_connection$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_connection_OBJECTS) $(test_connection_LDADD) $(LIBS) -test_connection_addressing$(EXEEXT): $(test_connection_addressing_OBJECTS) $(test_connection_addressing_DEPENDENCIES) +test_connection_addressing$(EXEEXT): $(test_connection_addressing_OBJECTS) $(test_connection_addressing_DEPENDENCIES) $(EXTRA_test_connection_addressing_DEPENDENCIES) @rm -f test_connection_addressing$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_connection_addressing_OBJECTS) $(test_connection_addressing_LDADD) $(LIBS) -test_connection_receive_cancel$(EXEEXT): $(test_connection_receive_cancel_OBJECTS) $(test_connection_receive_cancel_DEPENDENCIES) +test_connection_receive_cancel$(EXEEXT): $(test_connection_receive_cancel_OBJECTS) $(test_connection_receive_cancel_DEPENDENCIES) $(EXTRA_test_connection_receive_cancel_DEPENDENCIES) @rm -f test_connection_receive_cancel$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_connection_receive_cancel_OBJECTS) $(test_connection_receive_cancel_LDADD) $(LIBS) -test_connection_timeout$(EXEEXT): $(test_connection_timeout_OBJECTS) $(test_connection_timeout_DEPENDENCIES) +test_connection_timeout$(EXEEXT): $(test_connection_timeout_OBJECTS) $(test_connection_timeout_DEPENDENCIES) $(EXTRA_test_connection_timeout_DEPENDENCIES) @rm -f test_connection_timeout$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_connection_timeout_OBJECTS) $(test_connection_timeout_LDADD) $(LIBS) -test_connection_timeout_no_connect$(EXEEXT): $(test_connection_timeout_no_connect_OBJECTS) $(test_connection_timeout_no_connect_DEPENDENCIES) +test_connection_timeout_no_connect$(EXEEXT): $(test_connection_timeout_no_connect_OBJECTS) $(test_connection_timeout_no_connect_DEPENDENCIES) $(EXTRA_test_connection_timeout_no_connect_DEPENDENCIES) @rm -f test_connection_timeout_no_connect$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_connection_timeout_no_connect_OBJECTS) $(test_connection_timeout_no_connect_LDADD) $(LIBS) -test_connection_transmit_cancel$(EXEEXT): $(test_connection_transmit_cancel_OBJECTS) $(test_connection_transmit_cancel_DEPENDENCIES) +test_connection_transmit_cancel$(EXEEXT): $(test_connection_transmit_cancel_OBJECTS) $(test_connection_transmit_cancel_DEPENDENCIES) $(EXTRA_test_connection_transmit_cancel_DEPENDENCIES) @rm -f test_connection_transmit_cancel$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_connection_transmit_cancel_OBJECTS) $(test_connection_transmit_cancel_LDADD) $(LIBS) -test_container_bloomfilter$(EXEEXT): $(test_container_bloomfilter_OBJECTS) $(test_container_bloomfilter_DEPENDENCIES) +test_container_bloomfilter$(EXEEXT): $(test_container_bloomfilter_OBJECTS) $(test_container_bloomfilter_DEPENDENCIES) $(EXTRA_test_container_bloomfilter_DEPENDENCIES) @rm -f test_container_bloomfilter$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_container_bloomfilter_OBJECTS) $(test_container_bloomfilter_LDADD) $(LIBS) -test_container_heap$(EXEEXT): $(test_container_heap_OBJECTS) $(test_container_heap_DEPENDENCIES) +test_container_heap$(EXEEXT): $(test_container_heap_OBJECTS) $(test_container_heap_DEPENDENCIES) $(EXTRA_test_container_heap_DEPENDENCIES) @rm -f test_container_heap$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_container_heap_OBJECTS) $(test_container_heap_LDADD) $(LIBS) -test_container_meta_data$(EXEEXT): $(test_container_meta_data_OBJECTS) $(test_container_meta_data_DEPENDENCIES) +test_container_meta_data$(EXEEXT): $(test_container_meta_data_OBJECTS) $(test_container_meta_data_DEPENDENCIES) $(EXTRA_test_container_meta_data_DEPENDENCIES) @rm -f test_container_meta_data$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_container_meta_data_OBJECTS) $(test_container_meta_data_LDADD) $(LIBS) -test_container_multihashmap$(EXEEXT): $(test_container_multihashmap_OBJECTS) $(test_container_multihashmap_DEPENDENCIES) +test_container_multihashmap$(EXEEXT): $(test_container_multihashmap_OBJECTS) $(test_container_multihashmap_DEPENDENCIES) $(EXTRA_test_container_multihashmap_DEPENDENCIES) @rm -f test_container_multihashmap$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_container_multihashmap_OBJECTS) $(test_container_multihashmap_LDADD) $(LIBS) -test_container_slist$(EXEEXT): $(test_container_slist_OBJECTS) $(test_container_slist_DEPENDENCIES) +test_container_slist$(EXEEXT): $(test_container_slist_OBJECTS) $(test_container_slist_DEPENDENCIES) $(EXTRA_test_container_slist_DEPENDENCIES) @rm -f test_container_slist$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_container_slist_OBJECTS) $(test_container_slist_LDADD) $(LIBS) -test_crypto_aes$(EXEEXT): $(test_crypto_aes_OBJECTS) $(test_crypto_aes_DEPENDENCIES) +test_crypto_aes$(EXEEXT): $(test_crypto_aes_OBJECTS) $(test_crypto_aes_DEPENDENCIES) $(EXTRA_test_crypto_aes_DEPENDENCIES) @rm -f test_crypto_aes$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_crypto_aes_OBJECTS) $(test_crypto_aes_LDADD) $(LIBS) -test_crypto_aes_weak$(EXEEXT): $(test_crypto_aes_weak_OBJECTS) $(test_crypto_aes_weak_DEPENDENCIES) +test_crypto_aes_weak$(EXEEXT): $(test_crypto_aes_weak_OBJECTS) $(test_crypto_aes_weak_DEPENDENCIES) $(EXTRA_test_crypto_aes_weak_DEPENDENCIES) @rm -f test_crypto_aes_weak$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_crypto_aes_weak_OBJECTS) $(test_crypto_aes_weak_LDADD) $(LIBS) -test_crypto_crc$(EXEEXT): $(test_crypto_crc_OBJECTS) $(test_crypto_crc_DEPENDENCIES) +test_crypto_crc$(EXEEXT): $(test_crypto_crc_OBJECTS) $(test_crypto_crc_DEPENDENCIES) $(EXTRA_test_crypto_crc_DEPENDENCIES) @rm -f test_crypto_crc$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_crypto_crc_OBJECTS) $(test_crypto_crc_LDADD) $(LIBS) -test_crypto_hash$(EXEEXT): $(test_crypto_hash_OBJECTS) $(test_crypto_hash_DEPENDENCIES) +test_crypto_ecc$(EXEEXT): $(test_crypto_ecc_OBJECTS) $(test_crypto_ecc_DEPENDENCIES) $(EXTRA_test_crypto_ecc_DEPENDENCIES) + @rm -f test_crypto_ecc$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_crypto_ecc_OBJECTS) $(test_crypto_ecc_LDADD) $(LIBS) +test_crypto_hash$(EXEEXT): $(test_crypto_hash_OBJECTS) $(test_crypto_hash_DEPENDENCIES) $(EXTRA_test_crypto_hash_DEPENDENCIES) @rm -f test_crypto_hash$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_crypto_hash_OBJECTS) $(test_crypto_hash_LDADD) $(LIBS) -test_crypto_hkdf$(EXEEXT): $(test_crypto_hkdf_OBJECTS) $(test_crypto_hkdf_DEPENDENCIES) +test_crypto_hkdf$(EXEEXT): $(test_crypto_hkdf_OBJECTS) $(test_crypto_hkdf_DEPENDENCIES) $(EXTRA_test_crypto_hkdf_DEPENDENCIES) @rm -f test_crypto_hkdf$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_crypto_hkdf_OBJECTS) $(test_crypto_hkdf_LDADD) $(LIBS) -test_crypto_ksk$(EXEEXT): $(test_crypto_ksk_OBJECTS) $(test_crypto_ksk_DEPENDENCIES) +test_crypto_ksk$(EXEEXT): $(test_crypto_ksk_OBJECTS) $(test_crypto_ksk_DEPENDENCIES) $(EXTRA_test_crypto_ksk_DEPENDENCIES) @rm -f test_crypto_ksk$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_crypto_ksk_OBJECTS) $(test_crypto_ksk_LDADD) $(LIBS) -test_crypto_random$(EXEEXT): $(test_crypto_random_OBJECTS) $(test_crypto_random_DEPENDENCIES) +test_crypto_random$(EXEEXT): $(test_crypto_random_OBJECTS) $(test_crypto_random_DEPENDENCIES) $(EXTRA_test_crypto_random_DEPENDENCIES) @rm -f test_crypto_random$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_crypto_random_OBJECTS) $(test_crypto_random_LDADD) $(LIBS) -test_crypto_rsa$(EXEEXT): $(test_crypto_rsa_OBJECTS) $(test_crypto_rsa_DEPENDENCIES) +test_crypto_rsa$(EXEEXT): $(test_crypto_rsa_OBJECTS) $(test_crypto_rsa_DEPENDENCIES) $(EXTRA_test_crypto_rsa_DEPENDENCIES) @rm -f test_crypto_rsa$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_crypto_rsa_OBJECTS) $(test_crypto_rsa_LDADD) $(LIBS) -test_disk$(EXEEXT): $(test_disk_OBJECTS) $(test_disk_DEPENDENCIES) +test_disk$(EXEEXT): $(test_disk_OBJECTS) $(test_disk_DEPENDENCIES) $(EXTRA_test_disk_DEPENDENCIES) @rm -f test_disk$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_disk_OBJECTS) $(test_disk_LDADD) $(LIBS) -test_getopt$(EXEEXT): $(test_getopt_OBJECTS) $(test_getopt_DEPENDENCIES) +test_getopt$(EXEEXT): $(test_getopt_OBJECTS) $(test_getopt_DEPENDENCIES) $(EXTRA_test_getopt_DEPENDENCIES) @rm -f test_getopt$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_getopt_OBJECTS) $(test_getopt_LDADD) $(LIBS) -test_os_network$(EXEEXT): $(test_os_network_OBJECTS) $(test_os_network_DEPENDENCIES) +test_os_network$(EXEEXT): $(test_os_network_OBJECTS) $(test_os_network_DEPENDENCIES) $(EXTRA_test_os_network_DEPENDENCIES) @rm -f test_os_network$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_os_network_OBJECTS) $(test_os_network_LDADD) $(LIBS) -test_os_priority$(EXEEXT): $(test_os_priority_OBJECTS) $(test_os_priority_DEPENDENCIES) +test_os_priority$(EXEEXT): $(test_os_priority_OBJECTS) $(test_os_priority_DEPENDENCIES) $(EXTRA_test_os_priority_DEPENDENCIES) @rm -f test_os_priority$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_os_priority_OBJECTS) $(test_os_priority_LDADD) $(LIBS) -test_os_start_process$(EXEEXT): $(test_os_start_process_OBJECTS) $(test_os_start_process_DEPENDENCIES) +test_os_start_process$(EXEEXT): $(test_os_start_process_OBJECTS) $(test_os_start_process_DEPENDENCIES) $(EXTRA_test_os_start_process_DEPENDENCIES) @rm -f test_os_start_process$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_os_start_process_OBJECTS) $(test_os_start_process_LDADD) $(LIBS) -test_peer$(EXEEXT): $(test_peer_OBJECTS) $(test_peer_DEPENDENCIES) +test_peer$(EXEEXT): $(test_peer_OBJECTS) $(test_peer_DEPENDENCIES) $(EXTRA_test_peer_DEPENDENCIES) @rm -f test_peer$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_peer_OBJECTS) $(test_peer_LDADD) $(LIBS) -test_plugin$(EXEEXT): $(test_plugin_OBJECTS) $(test_plugin_DEPENDENCIES) +test_plugin$(EXEEXT): $(test_plugin_OBJECTS) $(test_plugin_DEPENDENCIES) $(EXTRA_test_plugin_DEPENDENCIES) @rm -f test_plugin$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_plugin_OBJECTS) $(test_plugin_LDADD) $(LIBS) -test_program$(EXEEXT): $(test_program_OBJECTS) $(test_program_DEPENDENCIES) +test_program$(EXEEXT): $(test_program_OBJECTS) $(test_program_DEPENDENCIES) $(EXTRA_test_program_DEPENDENCIES) @rm -f test_program$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_program_OBJECTS) $(test_program_LDADD) $(LIBS) -test_pseudonym$(EXEEXT): $(test_pseudonym_OBJECTS) $(test_pseudonym_DEPENDENCIES) +test_pseudonym$(EXEEXT): $(test_pseudonym_OBJECTS) $(test_pseudonym_DEPENDENCIES) $(EXTRA_test_pseudonym_DEPENDENCIES) @rm -f test_pseudonym$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_pseudonym_OBJECTS) $(test_pseudonym_LDADD) $(LIBS) -test_resolver_api$(EXEEXT): $(test_resolver_api_OBJECTS) $(test_resolver_api_DEPENDENCIES) +test_resolver_api$(EXEEXT): $(test_resolver_api_OBJECTS) $(test_resolver_api_DEPENDENCIES) $(EXTRA_test_resolver_api_DEPENDENCIES) @rm -f test_resolver_api$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_resolver_api_OBJECTS) $(test_resolver_api_LDADD) $(LIBS) -test_scheduler$(EXEEXT): $(test_scheduler_OBJECTS) $(test_scheduler_DEPENDENCIES) +test_scheduler$(EXEEXT): $(test_scheduler_OBJECTS) $(test_scheduler_DEPENDENCIES) $(EXTRA_test_scheduler_DEPENDENCIES) @rm -f test_scheduler$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_scheduler_OBJECTS) $(test_scheduler_LDADD) $(LIBS) -test_scheduler_delay$(EXEEXT): $(test_scheduler_delay_OBJECTS) $(test_scheduler_delay_DEPENDENCIES) +test_scheduler_delay$(EXEEXT): $(test_scheduler_delay_OBJECTS) $(test_scheduler_delay_DEPENDENCIES) $(EXTRA_test_scheduler_delay_DEPENDENCIES) @rm -f test_scheduler_delay$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_scheduler_delay_OBJECTS) $(test_scheduler_delay_LDADD) $(LIBS) -test_server$(EXEEXT): $(test_server_OBJECTS) $(test_server_DEPENDENCIES) +test_server$(EXEEXT): $(test_server_OBJECTS) $(test_server_DEPENDENCIES) $(EXTRA_test_server_DEPENDENCIES) @rm -f test_server$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_server_OBJECTS) $(test_server_LDADD) $(LIBS) -test_server_disconnect$(EXEEXT): $(test_server_disconnect_OBJECTS) $(test_server_disconnect_DEPENDENCIES) +test_server_disconnect$(EXEEXT): $(test_server_disconnect_OBJECTS) $(test_server_disconnect_DEPENDENCIES) $(EXTRA_test_server_disconnect_DEPENDENCIES) @rm -f test_server_disconnect$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_server_disconnect_OBJECTS) $(test_server_disconnect_LDADD) $(LIBS) -test_server_mst_interrupt$(EXEEXT): $(test_server_mst_interrupt_OBJECTS) $(test_server_mst_interrupt_DEPENDENCIES) +test_server_mst_interrupt$(EXEEXT): $(test_server_mst_interrupt_OBJECTS) $(test_server_mst_interrupt_DEPENDENCIES) $(EXTRA_test_server_mst_interrupt_DEPENDENCIES) @rm -f test_server_mst_interrupt$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_server_mst_interrupt_OBJECTS) $(test_server_mst_interrupt_LDADD) $(LIBS) -test_server_with_client$(EXEEXT): $(test_server_with_client_OBJECTS) $(test_server_with_client_DEPENDENCIES) +test_server_with_client$(EXEEXT): $(test_server_with_client_OBJECTS) $(test_server_with_client_DEPENDENCIES) $(EXTRA_test_server_with_client_DEPENDENCIES) @rm -f test_server_with_client$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_server_with_client_OBJECTS) $(test_server_with_client_LDADD) $(LIBS) -test_server_with_client_unix$(EXEEXT): $(test_server_with_client_unix_OBJECTS) $(test_server_with_client_unix_DEPENDENCIES) +test_server_with_client_unix$(EXEEXT): $(test_server_with_client_unix_OBJECTS) $(test_server_with_client_unix_DEPENDENCIES) $(EXTRA_test_server_with_client_unix_DEPENDENCIES) @rm -f test_server_with_client_unix$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_server_with_client_unix_OBJECTS) $(test_server_with_client_unix_LDADD) $(LIBS) -test_service$(EXEEXT): $(test_service_OBJECTS) $(test_service_DEPENDENCIES) +test_service$(EXEEXT): $(test_service_OBJECTS) $(test_service_DEPENDENCIES) $(EXTRA_test_service_DEPENDENCIES) @rm -f test_service$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_service_OBJECTS) $(test_service_LDADD) $(LIBS) -test_speedup$(EXEEXT): $(test_speedup_OBJECTS) $(test_speedup_DEPENDENCIES) +test_speedup$(EXEEXT): $(test_speedup_OBJECTS) $(test_speedup_DEPENDENCIES) $(EXTRA_test_speedup_DEPENDENCIES) @rm -f test_speedup$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_speedup_OBJECTS) $(test_speedup_LDADD) $(LIBS) -test_strings$(EXEEXT): $(test_strings_OBJECTS) $(test_strings_DEPENDENCIES) +test_strings$(EXEEXT): $(test_strings_OBJECTS) $(test_strings_DEPENDENCIES) $(EXTRA_test_strings_DEPENDENCIES) @rm -f test_strings$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_strings_OBJECTS) $(test_strings_LDADD) $(LIBS) -test_time$(EXEEXT): $(test_time_OBJECTS) $(test_time_DEPENDENCIES) +test_time$(EXEEXT): $(test_time_OBJECTS) $(test_time_DEPENDENCIES) $(EXTRA_test_time_DEPENDENCIES) @rm -f test_time$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_time_OBJECTS) $(test_time_LDADD) $(LIBS) +w32cat$(EXEEXT): $(w32cat_OBJECTS) $(w32cat_DEPENDENCIES) $(EXTRA_w32cat_DEPENDENCIES) + @rm -f w32cat$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(w32cat_OBJECTS) $(w32cat_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) @@ -1505,6 +1672,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/container_slist.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crypto_aes.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crypto_crc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crypto_ecc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crypto_hash.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crypto_hkdf.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crypto_kdf.Plo@am__quote@ @@ -1515,9 +1683,12 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt_helpers.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-config-diff.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-config.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-ecc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-resolver.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-rsa.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-service-resolver.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gnunet-uri.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/helper.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/load.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/network.Plo@am__quote@ @@ -1526,6 +1697,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/os_priority.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/peer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/perf_crypto_hash.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/perf_malloc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/program.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pseudonym.Plo@am__quote@ @@ -1561,6 +1733,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_crypto_aes.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_crypto_aes_weak.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_crypto_crc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_crypto_ecc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_crypto_hash.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_crypto_hkdf.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_crypto_ksk.Po@am__quote@ @@ -1589,56 +1762,30 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_strings.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_time.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/time.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/w32cat.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/win.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/winproc.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(COMPILE) -c $< +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo -@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< - -.cc.o: -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< - -.cc.obj: -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` - -.cc.lo: -@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo -@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $< +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo @@ -1647,8 +1794,11 @@ clean-libtool: -rm -rf .libs _libs install-dist_pkgcfgDATA: $(dist_pkgcfg_DATA) @$(NORMAL_INSTALL) - test -z "$(pkgcfgdir)" || $(MKDIR_P) "$(DESTDIR)$(pkgcfgdir)" @list='$(dist_pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkgcfgdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkgcfgdir)" || exit 1; \ + fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ @@ -1662,13 +1812,14 @@ uninstall-dist_pkgcfgDATA: @$(NORMAL_UNINSTALL) @list='$(dist_pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ - test -n "$$files" || exit 0; \ - echo " ( cd '$(DESTDIR)$(pkgcfgdir)' && rm -f" $$files ")"; \ - cd "$(DESTDIR)$(pkgcfgdir)" && rm -f $$files + dir='$(DESTDIR)$(pkgcfgdir)'; $(am__uninstall_files_from_dir) install-pkgcfgDATA: $(pkgcfg_DATA) @$(NORMAL_INSTALL) - test -z "$(pkgcfgdir)" || $(MKDIR_P) "$(DESTDIR)$(pkgcfgdir)" @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkgcfgdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkgcfgdir)" || exit 1; \ + fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ @@ -1682,9 +1833,7 @@ uninstall-pkgcfgDATA: @$(NORMAL_UNINSTALL) @list='$(pkgcfg_DATA)'; test -n "$(pkgcfgdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ - test -n "$$files" || exit 0; \ - echo " ( cd '$(DESTDIR)$(pkgcfgdir)' && rm -f" $$files ")"; \ - cd "$(DESTDIR)$(pkgcfgdir)" && rm -f $$files + dir='$(DESTDIR)$(pkgcfgdir)'; $(am__uninstall_files_from_dir) ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ @@ -1819,14 +1968,15 @@ check-TESTS: $(TESTS) fi; \ dashes=`echo "$$dashes" | sed s/./=/g`; \ if test "$$failed" -eq 0; then \ - echo "$$grn$$dashes"; \ + col="$$grn"; \ else \ - echo "$$red$$dashes"; \ + col="$$red"; \ fi; \ - echo "$$banner"; \ - test -z "$$skipped" || echo "$$skipped"; \ - test -z "$$report" || echo "$$report"; \ - echo "$$dashes$$std"; \ + echo "$${col}$$dashes$${std}"; \ + echo "$${col}$$banner$${std}"; \ + test -z "$$skipped" || echo "$${col}$$skipped$${std}"; \ + test -z "$$report" || echo "$${col}$$report$${std}"; \ + echo "$${col}$$dashes$${std}"; \ test "$$failed" -eq 0; \ else :; fi @@ -1868,7 +2018,7 @@ all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(DATA) install-binPROGRAMS: install-libLTLIBRARIES installdirs: - for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(pkgcfgdir)" "$(DESTDIR)$(pkgcfgdir)"; do \ + for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(pkgcfgdir)" "$(DESTDIR)$(pkgcfgdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am @@ -1881,10 +2031,15 @@ install-am: all-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 + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi mostlyclean-generic: clean-generic: @@ -1899,8 +2054,9 @@ maintainer-clean-generic: clean: clean-am clean-am: clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ - clean-libLTLIBRARIES clean-libtool clean-noinstLTLIBRARIES \ - clean-noinstPROGRAMS clean-pluginLTLIBRARIES mostlyclean-am + clean-libLTLIBRARIES clean-libexecPROGRAMS clean-libtool \ + clean-noinstLTLIBRARIES clean-noinstPROGRAMS \ + clean-pluginLTLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) @@ -1927,7 +2083,8 @@ install-dvi: install-dvi-am install-dvi-am: -install-exec-am: install-binPROGRAMS install-libLTLIBRARIES +install-exec-am: install-binPROGRAMS install-libLTLIBRARIES \ + install-libexecPROGRAMS install-html: install-html-am @@ -1968,30 +2125,31 @@ ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-dist_pkgcfgDATA \ - uninstall-libLTLIBRARIES uninstall-pkgcfgDATA \ - uninstall-pluginLTLIBRARIES + uninstall-libLTLIBRARIES uninstall-libexecPROGRAMS \ + uninstall-pkgcfgDATA uninstall-pluginLTLIBRARIES .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS all all-am check check-TESTS check-am clean \ clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ - clean-libLTLIBRARIES clean-libtool clean-noinstLTLIBRARIES \ - clean-noinstPROGRAMS clean-pluginLTLIBRARIES ctags distclean \ - distclean-compile distclean-generic distclean-libtool \ - distclean-tags distdir dvi dvi-am html html-am info info-am \ - install install-am install-binPROGRAMS install-data \ - install-data-am install-dist_pkgcfgDATA install-dvi \ - install-dvi-am install-exec install-exec-am install-html \ - install-html-am install-info install-info-am \ - install-libLTLIBRARIES install-man install-pdf install-pdf-am \ + clean-libLTLIBRARIES clean-libexecPROGRAMS clean-libtool \ + clean-noinstLTLIBRARIES clean-noinstPROGRAMS \ + clean-pluginLTLIBRARIES ctags distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-binPROGRAMS install-data install-data-am \ + install-dist_pkgcfgDATA install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-libLTLIBRARIES \ + install-libexecPROGRAMS install-man install-pdf install-pdf-am \ install-pkgcfgDATA install-pluginLTLIBRARIES 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-binPROGRAMS uninstall-dist_pkgcfgDATA \ - uninstall-libLTLIBRARIES uninstall-pkgcfgDATA \ - uninstall-pluginLTLIBRARIES + uninstall-libLTLIBRARIES uninstall-libexecPROGRAMS \ + uninstall-pkgcfgDATA uninstall-pluginLTLIBRARIES # Tell versions [3.59,3.63) of GNU make to not export all variables. diff --git a/src/util/bandwidth.c b/src/util/bandwidth.c index 9d67949..60cb505 100644 --- a/src/util/bandwidth.c +++ b/src/util/bandwidth.c @@ -24,8 +24,7 @@ * @author Christian Grothoff */ #include "platform.h" -#include "gnunet_bandwidth_lib.h" -#include "gnunet_server_lib.h" +#include "gnunet_util_lib.h" #define LOG(kind,...) GNUNET_log_from (kind, "util-bandwidth", __VA_ARGS__) @@ -83,9 +82,9 @@ GNUNET_BANDWIDTH_value_get_available_until (struct GNUNET_BANDWIDTH_Value32NBO b = ntohl (bps.value__); LOG (GNUNET_ERROR_TYPE_DEBUG, - "Bandwidth has %llu bytes available until deadline in %llums\n", + "Bandwidth has %llu bytes available until deadline in %s\n", (unsigned long long) ((b * deadline.rel_value + 500LL) / 1000LL), - deadline.rel_value); + GNUNET_STRINGS_relative_time_to_string (deadline, GNUNET_YES)); return (b * deadline.rel_value + 500LL) / 1000LL; } diff --git a/src/util/client.c b/src/util/client.c index c29b48e..69380c9 100644 --- a/src/util/client.c +++ b/src/util/client.c @@ -27,11 +27,8 @@ * connections between clients and service providers. */ #include "platform.h" -#include "gnunet_common.h" -#include "gnunet_client_lib.h" #include "gnunet_protocols.h" -#include "gnunet_server_lib.h" -#include "gnunet_scheduler_lib.h" +#include "gnunet_util_lib.h" /** @@ -240,6 +237,11 @@ struct GNUNET_CLIENT_Connection int in_receive; /** + * Is this the first message we are sending to the service? + */ + int first_message; + + /** * How often have we tried to connect? */ unsigned int attempts; @@ -261,12 +263,22 @@ try_unixpath (const char *service_name, #if AF_UNIX struct GNUNET_CONNECTION_Handle *connection; char *unixpath; + struct sockaddr_un s_un; unixpath = NULL; if ((GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg, service_name, "UNIXPATH", &unixpath)) && (0 < strlen (unixpath))) { /* We have a non-NULL unixpath, need to validate it */ + if (strlen (unixpath) >= sizeof (s_un.sun_path)) + { + LOG (GNUNET_ERROR_TYPE_WARNING, + _("UNIXPATH `%s' too long, maximum length is %llu\n"), unixpath, + (unsigned long long) sizeof (s_un.sun_path)); + unixpath = GNUNET_NETWORK_shorten_unixpath (unixpath); + LOG (GNUNET_ERROR_TYPE_INFO, + _("Using `%s' instead\n"), unixpath); + } connection = GNUNET_CONNECTION_create_from_connect_to_unixpath (cfg, unixpath); if (NULL != connection) { @@ -412,6 +424,7 @@ GNUNET_CLIENT_connect (const char *service_name, return NULL; connection = do_connect (service_name, cfg, 0); client = GNUNET_malloc (sizeof (struct GNUNET_CLIENT_Connection)); + client->first_message = GNUNET_YES; client->attempts = 1; client->connection = connection; client->service_name = GNUNET_strdup (service_name); @@ -738,40 +751,43 @@ GNUNET_CLIENT_service_test (const char *service, { LOG (GNUNET_ERROR_TYPE_WARNING, _("UNIXPATH `%s' too long, maximum length is %llu\n"), unixpath, - sizeof (s_un.sun_path)); + (unsigned long long) sizeof (s_un.sun_path)); + unixpath = GNUNET_NETWORK_shorten_unixpath (unixpath); + LOG (GNUNET_ERROR_TYPE_INFO, + _("Using `%s' instead\n"), unixpath); } - else + } + if (NULL != unixpath) + { + sock = GNUNET_NETWORK_socket_create (PF_UNIX, SOCK_STREAM, 0); + if (NULL != sock) { - sock = GNUNET_NETWORK_socket_create (PF_UNIX, SOCK_STREAM, 0); - if (NULL != sock) - { - memset (&s_un, 0, sizeof (s_un)); - s_un.sun_family = AF_UNIX; - slen = strlen (unixpath) + 1; - if (slen >= sizeof (s_un.sun_path)) - slen = sizeof (s_un.sun_path) - 1; - memcpy (s_un.sun_path, unixpath, slen); - s_un.sun_path[slen] = '\0'; - slen = sizeof (struct sockaddr_un); + memset (&s_un, 0, sizeof (s_un)); + s_un.sun_family = AF_UNIX; + slen = strlen (unixpath) + 1; + if (slen >= sizeof (s_un.sun_path)) + slen = sizeof (s_un.sun_path) - 1; + memcpy (s_un.sun_path, unixpath, slen); + s_un.sun_path[slen] = '\0'; + slen = sizeof (struct sockaddr_un); #if LINUX - s_un.sun_path[0] = '\0'; + s_un.sun_path[0] = '\0'; #endif #if HAVE_SOCKADDR_IN_SIN_LEN - s_un.sun_len = (u_char) slen; + s_un.sun_len = (u_char) slen; #endif - if (GNUNET_OK != - GNUNET_NETWORK_socket_bind (sock, (const struct sockaddr *) &s_un, - slen)) - { - /* failed to bind => service must be running */ - GNUNET_free (unixpath); - (void) GNUNET_NETWORK_socket_close (sock); - GNUNET_SCHEDULER_add_continuation (task, task_cls, - GNUNET_SCHEDULER_REASON_PREREQ_DONE); - return; - } - (void) GNUNET_NETWORK_socket_close (sock); - } + if (GNUNET_OK != + GNUNET_NETWORK_socket_bind (sock, (const struct sockaddr *) &s_un, + slen)) + { + /* failed to bind => service must be running */ + GNUNET_free (unixpath); + (void) GNUNET_NETWORK_socket_close (sock); + GNUNET_SCHEDULER_add_continuation (task, task_cls, + GNUNET_SCHEDULER_REASON_PREREQ_DONE); + return; + } + (void) GNUNET_NETWORK_socket_close (sock); /* let's try IP */ } } @@ -927,10 +943,19 @@ client_delayed_retry (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_CLIENT_TransmitHandle *th = cls; struct GNUNET_TIME_Relative delay; - + th->reconnect_task = GNUNET_SCHEDULER_NO_TASK; + if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) + { + /* give up, was shutdown */ + th->client->th = NULL; + th->notify (th->notify_cls, 0, NULL); + GNUNET_free (th); + return; + } th->client->connection = do_connect (th->client->service_name, th->client->cfg, th->client->attempts++); + th->client->first_message = GNUNET_YES; if (NULL == th->client->connection) { /* could happen if we're out of sockets */ @@ -942,9 +967,9 @@ client_delayed_retry (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) (th->client->back_off, 2), GNUNET_TIME_UNIT_SECONDS); LOG (GNUNET_ERROR_TYPE_DEBUG, - "Transmission failed %u times, trying again in %llums.\n", + "Transmission failed %u times, trying again in %s.\n", MAX_ATTEMPTS - th->attempts_left, - (unsigned long long) delay.rel_value); + GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES)); th->reconnect_task = GNUNET_SCHEDULER_add_delayed (delay, &client_delayed_retry, th); return; @@ -989,7 +1014,8 @@ client_notify (void *cls, size_t size, void *buf) delay = GNUNET_TIME_absolute_get_remaining (th->timeout); delay.rel_value /= 2; if ((GNUNET_YES != th->auto_retry) || (0 == --th->attempts_left) || - (delay.rel_value < 1)) + (delay.rel_value < 1)|| + (0 != (GNUNET_SCHEDULER_get_reason() & GNUNET_SCHEDULER_REASON_SHUTDOWN))) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmission failed %u times, giving up.\n", @@ -1015,9 +1041,9 @@ client_notify (void *cls, size_t size, void *buf) (client->back_off, 2), GNUNET_TIME_UNIT_SECONDS); LOG (GNUNET_ERROR_TYPE_DEBUG, - "Transmission failed %u times, trying again in %llums.\n", + "Transmission failed %u times, trying again in %s.\n", MAX_ATTEMPTS - th->attempts_left, - (unsigned long long) delay.rel_value); + GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES)); client->th = th; th->reconnect_task = GNUNET_SCHEDULER_add_delayed (delay, &client_delayed_retry, th); @@ -1070,7 +1096,9 @@ GNUNET_CLIENT_notify_transmit_ready (struct GNUNET_CLIENT_Connection *client, th->client = client; th->size = size; th->timeout = GNUNET_TIME_relative_to_absolute (timeout); - th->auto_retry = auto_retry; + /* always auto-retry on first message to service */ + th->auto_retry = (GNUNET_YES == client->first_message) ? GNUNET_YES : auto_retry; + client->first_message = GNUNET_NO; th->notify = notify; th->notify_cls = notify_cls; th->attempts_left = MAX_ATTEMPTS; diff --git a/src/util/common_allocation.c b/src/util/common_allocation.c index 5e1f75e..dfa65d5 100644 --- a/src/util/common_allocation.c +++ b/src/util/common_allocation.c @@ -23,9 +23,14 @@ * @brief wrapper around malloc/free * @author Christian Grothoff */ - #include "platform.h" #include "gnunet_common.h" +#if HAVE_MALLOC_H +#include <malloc.h> +#endif +#if HAVE_MALLOC_MALLOC_H +#include <malloc/malloc.h> +#endif #define LOG(kind,...) GNUNET_log_from (kind, "util",__VA_ARGS__) @@ -182,6 +187,22 @@ GNUNET_xrealloc_ (void *ptr, size_t n, const char *filename, int linenumber) } +# if __BYTE_ORDER == __LITTLE_ENDIAN +#define BAADFOOD_STR "\x0D\xF0\xAD\xBA" +#endif +# if __BYTE_ORDER == __BIG_ENDIAN +#define BAADFOOD_STR "\xBA\xAD\xF0\x0D" +#endif + +#if WINDOWS +#define M_SIZE(p) _msize (p) +#endif +#if HAVE_MALLOC_USABLE_SIZE +#define M_SIZE(p) malloc_usable_size (p) +#elif HAVE_MALLOC_SIZE +#define M_SIZE(p) malloc_size (p) +#endif + /** * Free memory. Merely a wrapper for the case that we * want to keep track of allocations. @@ -198,6 +219,20 @@ GNUNET_xfree_ (void *ptr, const char *filename, int linenumber) ptr = &((size_t *) ptr)[-1]; mem_used -= *((size_t *) ptr); #endif +#if defined(M_SIZE) +#if ENABLE_POISONING + { + const uint64_t baadfood = GNUNET_ntohll (0xBAADF00DBAADF00DLL); + uint64_t *base = ptr; + size_t s = M_SIZE (ptr); + size_t i; + + for (i=0;i<s/8;i++) + base[i] = baadfood; + memcpy (&base[s/8], &baadfood, s % 8); + } +#endif +#endif free (ptr); } @@ -221,6 +256,21 @@ GNUNET_xstrdup_ (const char *str, const char *filename, int linenumber) } +#if ! HAVE_STRNLEN +static size_t +strnlen (const char *s, + size_t n) +{ + const char *e; + + e = memchr (s, '\0', n); + if (NULL == e) + return n; + return e - s; +} +#endif + + /** * Dup partially a string (same semantics as strndup). * @@ -236,11 +286,13 @@ GNUNET_xstrndup_ (const char *str, size_t len, const char *filename, { char *res; + if (0 == len) + return GNUNET_strdup (""); GNUNET_assert_at (str != NULL, filename, linenumber); - len = GNUNET_MIN (len, strlen (str)); + len = strnlen (str, len); res = GNUNET_xmalloc_ (len + 1, filename, linenumber); memcpy (res, str, len); - res[len] = '\0'; + /* res[len] = '\0'; 'malloc' zeros out anyway */ return res; } diff --git a/src/util/common_logging.c b/src/util/common_logging.c index 2c0fd57..000c338 100644 --- a/src/util/common_logging.c +++ b/src/util/common_logging.c @@ -64,6 +64,19 @@ #define DATE_STR_SIZE 64 /** + * How many log files to keep? + */ +#define ROTATION_KEEP 3 + +#ifndef PATH_MAX +/** + * Assumed maximum path length (for the log file name). + */ +#define PATH_MAX 4096 +#endif + + +/** * Linked list of active loggers. */ struct CustomLogger @@ -122,6 +135,11 @@ static char *component; static char *component_nopid; /** + * Format string describing the name of the log file. + */ +static char *log_file_name; + +/** * Minimum log level. */ static enum GNUNET_ErrorType min_level; @@ -134,7 +152,7 @@ static struct CustomLogger *loggers; /** * Number of log calls to ignore. */ -unsigned int skip_log; +int skip_log = 0; /** * File descriptor to use for "stderr", or NULL for none. @@ -190,40 +208,41 @@ struct LogDef /** * Dynamic array of logging definitions */ -struct LogDef *logdefs = NULL; +static struct LogDef *logdefs; /** * Allocated size of logdefs array (in units) */ -int logdefs_size = 0; +static int logdefs_size; /** * The number of units used in logdefs array. */ -int logdefs_len = 0; +static int logdefs_len; /** * GNUNET_YES if GNUNET_LOG environment variable is already parsed. */ -int gnunet_log_parsed = GNUNET_NO; +static int gnunet_log_parsed; /** * GNUNET_YES if GNUNET_FORCE_LOG environment variable is already parsed. */ -int gnunet_force_log_parsed = GNUNET_NO; +static int gnunet_force_log_parsed; /** * GNUNET_YES if at least one definition with forced == 1 is available. */ -int gnunet_force_log_present = GNUNET_NO; +static int gnunet_force_log_present; #ifdef WINDOWS /** * Contains the number of performance counts per second. */ -LARGE_INTEGER performance_frequency; +static LARGE_INTEGER performance_frequency; #endif + /** * Convert a textual description of a loglevel * to the respective GNUNET_GE_KIND. @@ -234,7 +253,7 @@ LARGE_INTEGER performance_frequency; static enum GNUNET_ErrorType get_type (const char *log) { - if (log == NULL) + if (NULL == log) return GNUNET_ERROR_TYPE_UNSPECIFIED; if (0 == strcasecmp (log, _("DEBUG"))) return GNUNET_ERROR_TYPE_DEBUG; @@ -249,6 +268,7 @@ get_type (const char *log) return GNUNET_ERROR_TYPE_INVALID; } + #if !defined(GNUNET_CULL_LOGGING) /** * Utility function - reallocates logdefs array to be twice as large. @@ -275,6 +295,112 @@ GNUNET_abort () /** + * Rotate logs, deleting the oldest log. + * + * @param new_name new name to add to the rotation + */ +static void +log_rotate (const char *new_name) +{ + static char *rotation[ROTATION_KEEP]; + static unsigned int rotation_off; + char *discard; + + if ('\0' == *new_name) + return; /* not a real log file name */ + discard = rotation[rotation_off % ROTATION_KEEP]; + if (NULL != discard) + { + /* Note: can't log errors during logging (recursion!), so this + operation MUST silently fail... */ + (void) UNLINK (discard); + GNUNET_free (discard); + } + rotation[rotation_off % ROTATION_KEEP] = GNUNET_strdup (new_name); + rotation_off++; +} + + +/** + * Setup the log file. + * + * @param tm timestamp for which we should setup logging + * @return GNUNET_OK on success, GNUNET_SYSERR on error + */ +static int +setup_log_file (const struct tm *tm) +{ + static char last_fn[PATH_MAX + 1]; + char fn[PATH_MAX + 1]; + int dirwarn; + int altlog_fd; + int dup_return; + FILE *altlog; + char *leftsquare; + + if (NULL == log_file_name) + return GNUNET_SYSERR; + if (0 == strftime (fn, sizeof (fn), log_file_name, tm)) + return GNUNET_SYSERR; + leftsquare = strrchr (fn, '['); + if ( (NULL != leftsquare) && (']' == leftsquare[1]) ) + { + char *logfile_copy = GNUNET_strdup (fn); + logfile_copy[leftsquare - fn] = '\0'; + logfile_copy[leftsquare - fn + 1] = '\0'; + snprintf (fn, PATH_MAX, "%s%d%s", + logfile_copy, getpid (), &logfile_copy[leftsquare - fn + 2]); + GNUNET_free (logfile_copy); + } + if (0 == strcmp (fn, last_fn)) + return GNUNET_OK; /* no change */ + log_rotate (last_fn); + strcpy (last_fn, fn); + dirwarn = (GNUNET_OK != GNUNET_DISK_directory_create_for_file (fn)); +#if WINDOWS + altlog_fd = OPEN (fn, O_APPEND | + O_BINARY | + O_WRONLY | O_CREAT, + _S_IREAD | _S_IWRITE); +#else + altlog_fd = OPEN (fn, O_APPEND | + O_WRONLY | O_CREAT, + S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); +#endif + if (-1 != altlog_fd) + { + if (NULL != GNUNET_stderr) + fclose (GNUNET_stderr); + dup_return = dup2 (altlog_fd, 2); + (void) close (altlog_fd); + if (-1 != dup_return) + { + altlog = fdopen (2, "ab"); + if (NULL == altlog) + { + (void) close (2); + altlog_fd = -1; + } + } + else + { + altlog_fd = -1; + } + } + if (-1 == altlog_fd) + { + GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", fn); + if (dirwarn) + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + _("Failed to create or access directory for log file `%s'\n"), + fn); + return GNUNET_SYSERR; + } + GNUNET_stderr = altlog; + return GNUNET_OK; +} + +/** * Utility function - adds a parsed definition to logdefs array. * * @param component see struct LogDef, can't be NULL @@ -296,25 +422,25 @@ add_definition (char *component, char *file, char *function, int from_line, if (logdefs_size == logdefs_len) resize_logdefs (); memset (&n, 0, sizeof (n)); - if (strlen (component) == 0) + if (0 == strlen (component)) component = (char *) ".*"; r = regcomp (&n.component_regex, (const char *) component, REG_NOSUB); - if (r != 0) + if (0 != r) { return r; } - if (strlen (file) == 0) + if (0 == strlen (file)) file = (char *) ".*"; r = regcomp (&n.file_regex, (const char *) file, REG_NOSUB); - if (r != 0) + if (0 != r) { regfree (&n.component_regex); return r; } - if ((NULL == function) || (strlen (function) == 0)) + if ((NULL == function) || (0 == strlen (function))) function = (char *) ".*"; r = regcomp (&n.function_regex, (const char *) function, REG_NOSUB); - if (r != 0) + if (0 != r) { regfree (&n.component_regex); regfree (&n.file_regex); @@ -350,14 +476,14 @@ GNUNET_get_log_call_status (int caller_level, const char *comp, int i; int force_only; - if (comp == NULL) + if (NULL == comp) /* Use default component */ comp = component_nopid; /* We have no definitions to override globally configured log level, * so just use it right away. */ - if (min_level >= 0 && gnunet_force_log_present == GNUNET_NO) + if ( (min_level >= 0) && (GNUNET_NO == gnunet_force_log_present) ) return caller_level <= min_level; /* Only look for forced definitions? */ @@ -365,11 +491,11 @@ GNUNET_get_log_call_status (int caller_level, const char *comp, for (i = 0; i < logdefs_len; i++) { ld = &logdefs[i]; - if ((!force_only || ld->force) && + if (( (!force_only) || ld->force) && (line >= ld->from_line && line <= ld->to_line) && - (regexec (&ld->component_regex, comp, 0, NULL, 0) == 0) && - (regexec (&ld->file_regex, file, 0, NULL, 0) == 0) && - (regexec (&ld->function_regex, function, 0, NULL, 0) == 0)) + (0 == regexec (&ld->component_regex, comp, 0, NULL, 0)) && + (0 == regexec (&ld->file_regex, file, 0, NULL, 0)) && + (0 == regexec (&ld->function_regex, function, 0, NULL, 0))) { /* We're finished */ return caller_level <= ld->level; @@ -426,7 +552,7 @@ parse_definitions (const char *constname, int force) int keep_looking = 1; tmp = getenv (constname); - if (tmp == NULL) + if (NULL == tmp) return 0; def = GNUNET_strdup (tmp); from_line = 0; @@ -454,17 +580,17 @@ parse_definitions (const char *constname, int force) { errno = 0; from_line = strtol (start, &t, 10); - if (errno != 0 || from_line < 0) + if ( (0 != errno) || (from_line < 0) ) { GNUNET_free (def); return counter; } - if (t < p && t[0] == '-') + if ( (t < p) && ('-' == t[0]) ) { errno = 0; start = t + 1; to_line = strtol (start, &t, 10); - if (errno != 0 || to_line < 0 || t != p) + if ( (0 != errno) || (to_line < 0) || (t != p) ) { GNUNET_free (def); return counter; @@ -481,7 +607,7 @@ parse_definitions (const char *constname, int force) break; } start = p + 1; - state += 1; + state++; break; case '\0': /* found EOL */ keep_looking = 0; @@ -493,15 +619,15 @@ parse_definitions (const char *constname, int force) p[0] = '\0'; state = 0; level = get_type ((const char *) start); - if (level == GNUNET_ERROR_TYPE_INVALID || - level == GNUNET_ERROR_TYPE_UNSPECIFIED || - 0 != add_definition (comp, file, function, from_line, to_line, - level, force)) + if ( (GNUNET_ERROR_TYPE_INVALID == level) || + (GNUNET_ERROR_TYPE_UNSPECIFIED == level) || + (0 != add_definition (comp, file, function, from_line, to_line, + level, force)) ) { GNUNET_free (def); return counter; } - counter += 1; + counter++; start = p + 1; break; default: @@ -515,16 +641,17 @@ parse_definitions (const char *constname, int force) return counter; } + /** * Utility function - parses GNUNET_LOG and GNUNET_FORCE_LOG. */ static void parse_all_definitions () { - if (gnunet_log_parsed == GNUNET_NO) + if (GNUNET_NO == gnunet_log_parsed) parse_definitions ("GNUNET_LOG", 0); gnunet_log_parsed = GNUNET_YES; - if (gnunet_force_log_parsed == GNUNET_NO) + if (GNUNET_NO == gnunet_force_log_parsed) gnunet_force_log_present = parse_definitions ("GNUNET_FORCE_LOG", 1) > 0 ? GNUNET_YES : GNUNET_NO; gnunet_force_log_parsed = GNUNET_YES; @@ -543,11 +670,9 @@ parse_all_definitions () int GNUNET_log_setup (const char *comp, const char *loglevel, const char *logfile) { - FILE *altlog; - int dirwarn; - char *fn; - const char *env_logfile = NULL; - int altlog_fd; + const char *env_logfile; + const struct tm *tm; + time_t t; min_level = get_type (loglevel); #if !defined(GNUNET_CULL_LOGGING) @@ -562,61 +687,20 @@ GNUNET_log_setup (const char *comp, const char *loglevel, const char *logfile) component_nopid = GNUNET_strdup (comp); env_logfile = getenv ("GNUNET_FORCE_LOGFILE"); - if ((env_logfile != NULL) && (strlen (env_logfile) > 0)) + if ((NULL != env_logfile) && (strlen (env_logfile) > 0)) logfile = env_logfile; - - if (logfile == NULL) + if (NULL == logfile) return GNUNET_OK; - fn = GNUNET_STRINGS_filename_expand (logfile); - if (NULL == fn) + GNUNET_free_non_null (log_file_name); + log_file_name = GNUNET_STRINGS_filename_expand (logfile); + if (NULL == log_file_name) return GNUNET_SYSERR; - dirwarn = (GNUNET_OK != GNUNET_DISK_directory_create_for_file (fn)); -#if WINDOWS - altlog_fd = OPEN (fn, O_APPEND | - O_BINARY | - O_WRONLY | O_CREAT, - _S_IREAD | _S_IWRITE); -#else - altlog_fd = OPEN (fn, O_APPEND | - O_WRONLY | O_CREAT, - S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); -#endif - if (altlog_fd != -1) - { - int dup_return; - if (GNUNET_stderr != NULL) - fclose (GNUNET_stderr); - dup_return = dup2 (altlog_fd, 2); - (void) close (altlog_fd); - if (dup_return != -1) - { - altlog = fdopen (2, "ab"); - if (altlog == NULL) - { - (void) close (2); - altlog_fd = -1; - } - } - else - { - altlog_fd = -1; - } - } - if (altlog_fd == -1) - { - GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", fn); - if (dirwarn) - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - _("Failed to create or access directory for log file `%s'\n"), - fn); - GNUNET_free (fn); - return GNUNET_SYSERR; - } - GNUNET_free (fn); - GNUNET_stderr = altlog; - return GNUNET_OK; + t = time (NULL); + tm = gmtime (&t); + return setup_log_file (tm); } + /** * Add a custom logger. * @@ -635,6 +719,7 @@ GNUNET_logger_add (GNUNET_Logger logger, void *logger_cls) loggers = entry; } + /** * Remove a custom logger. * @@ -663,6 +748,10 @@ GNUNET_logger_remove (GNUNET_Logger logger, void *logger_cls) GNUNET_free (pos); } +#if WINDOWS +CRITICAL_SECTION output_message_cs; +#endif + /** * Actually output the log message. @@ -677,8 +766,10 @@ output_message (enum GNUNET_ErrorType kind, const char *comp, const char *datestr, const char *msg) { struct CustomLogger *pos; - - if (GNUNET_stderr != NULL) +#if WINDOWS + EnterCriticalSection (&output_message_cs); +#endif + if (NULL != GNUNET_stderr) { FPRINTF (GNUNET_stderr, "%s %s %s %s", datestr, comp, GNUNET_error_type_to_string (kind), msg); @@ -690,6 +781,9 @@ output_message (enum GNUNET_ErrorType kind, const char *comp, pos->logger (pos->logger_cls, kind, comp, datestr, msg); pos = pos->next; } +#if WINDOWS + LeaveCriticalSection (&output_message_cs); +#endif } @@ -704,7 +798,7 @@ flush_bulk (const char *datestr) char msg[DATE_STR_SIZE + BULK_TRACK_SIZE + 256]; int rev; char *last; - char *ft; + const char *ft; if ((last_bulk_time.abs_value == 0) || (last_bulk_repeat == 0)) return; @@ -720,11 +814,10 @@ flush_bulk (const char *datestr) last[0] = '\0'; } ft = GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration - (last_bulk_time)); + (last_bulk_time), GNUNET_YES); snprintf (msg, sizeof (msg), _("Message `%.*s' repeated %u times in the last %s\n"), BULK_TRACK_SIZE, last_bulk, last_bulk_repeat, ft); - GNUNET_free (ft); if (rev == 1) last[0] = '\n'; output_message (last_bulk_kind, last_bulk_comp, datestr, msg); @@ -736,25 +829,37 @@ flush_bulk (const char *datestr) /** * Ignore the next n calls to the log function. * - * @param n number of log calls to ignore + * @param n number of log calls to ignore (could be negative) * @param check_reset GNUNET_YES to assert that the log skip counter is currently zero */ void -GNUNET_log_skip (unsigned int n, int check_reset) +GNUNET_log_skip (int n, int check_reset) { - if (n == 0) - { - int ok; + int ok; + if (0 == n) + { ok = (0 == skip_log); skip_log = 0; if (check_reset) - GNUNET_assert (ok); + GNUNET_break (ok); } else + { skip_log += n; + } } +/** + * Get the number of log calls that are going to be skipped + * + * @return number of log calls to be ignored + */ +int +GNUNET_get_log_skip () +{ + return skip_log; +} /** * Output a log message using the default mechanism. @@ -770,8 +875,6 @@ mylog (enum GNUNET_ErrorType kind, const char *comp, const char *message, { char date[DATE_STR_SIZE]; char date2[DATE_STR_SIZE]; - time_t timetmp; - struct timeval timeofday; struct tm *tmptr; size_t size; va_list vacp; @@ -780,32 +883,46 @@ mylog (enum GNUNET_ErrorType kind, const char *comp, const char *message, size = VSNPRINTF (NULL, 0, message, vacp) + 1; GNUNET_assert (0 != size); va_end (vacp); + memset (date, 0, DATE_STR_SIZE); { char buf[size]; +#ifdef WINDOWS + LARGE_INTEGER pc; + time_t timetmp; - VSNPRINTF (buf, size, message, va); time (&timetmp); - memset (date, 0, DATE_STR_SIZE); tmptr = localtime (&timetmp); - gettimeofday (&timeofday, NULL); - if (NULL != tmptr) + pc.QuadPart = 0; + QueryPerformanceCounter (&pc); + if (NULL == tmptr) + { + strcpy (date, "localtime error"); + } + else { -#ifdef WINDOWS - LARGE_INTEGER pc; - - pc.QuadPart = 0; - QueryPerformanceCounter (&pc); strftime (date2, DATE_STR_SIZE, "%b %d %H:%M:%S-%%020llu", tmptr); snprintf (date, sizeof (date), date2, - (long long) (pc.QuadPart / - (performance_frequency.QuadPart / 1000))); + (long long) (pc.QuadPart / + (performance_frequency.QuadPart / 1000))); + } #else + struct timeval timeofday; + + gettimeofday (&timeofday, NULL); + tmptr = localtime (&timeofday.tv_sec); + if (NULL == tmptr) + { + strcpy (date, "localtime error"); + } + else + { strftime (date2, DATE_STR_SIZE, "%b %d %H:%M:%S-%%06u", tmptr); snprintf (date, sizeof (date), date2, timeofday.tv_usec); -#endif } - else - strcpy (date, "localtime error"); +#endif + VSNPRINTF (buf, size, message, va); + if (NULL != tmptr) + (void) setup_log_file (tmptr); if ((0 != (kind & GNUNET_ERROR_TYPE_BULK)) && (last_bulk_time.abs_value != 0) && (0 == strncmp (buf, last_bulk, sizeof (last_bulk)))) @@ -895,6 +1012,43 @@ GNUNET_error_type_to_string (enum GNUNET_ErrorType kind) /** + * Convert a short hash to a string (for printing debug messages). + * This is one of the very few calls in the entire API that is + * NOT reentrant! + * + * @param hc the short hash code + * @return string form; will be overwritten by next call to GNUNET_h2s. + */ +const char * +GNUNET_short_h2s (const struct GNUNET_CRYPTO_ShortHashCode * hc) +{ + static struct GNUNET_CRYPTO_ShortHashAsciiEncoded ret; + + GNUNET_CRYPTO_short_hash_to_enc (hc, &ret); + ret.short_encoding[8] = '\0'; + return (const char *) ret.short_encoding; +} + + +/** + * Convert a short hash to a string (for printing debug messages). + * This is one of the very few calls in the entire API that is + * NOT reentrant! + * + * @param hc the short hash code + * @return string form; will be overwritten by next call to GNUNET_h2s_full. + */ +const char * +GNUNET_short_h2s_full (const struct GNUNET_CRYPTO_ShortHashCode * hc) +{ + static struct GNUNET_CRYPTO_ShortHashAsciiEncoded ret; + + GNUNET_CRYPTO_short_hash_to_enc (hc, &ret); + ret.short_encoding[sizeof (ret) - 1] = '\0'; + return (const char *) ret.short_encoding; +} + +/** * Convert a hash to a string (for printing debug messages). * This is one of the very few calls in the entire API that is * NOT reentrant! @@ -903,7 +1057,7 @@ GNUNET_error_type_to_string (enum GNUNET_ErrorType kind) * @return string form; will be overwritten by next call to GNUNET_h2s. */ const char * -GNUNET_h2s (const GNUNET_HashCode * hc) +GNUNET_h2s (const struct GNUNET_HashCode * hc) { static struct GNUNET_CRYPTO_HashAsciiEncoded ret; @@ -912,6 +1066,7 @@ GNUNET_h2s (const GNUNET_HashCode * hc) return (const char *) ret.encoding; } + /** * Convert a hash to a string (for printing debug messages). * This is one of the very few calls in the entire API that is @@ -921,7 +1076,7 @@ GNUNET_h2s (const GNUNET_HashCode * hc) * @return string form; will be overwritten by next call to GNUNET_h2s_full. */ const char * -GNUNET_h2s_full (const GNUNET_HashCode * hc) +GNUNET_h2s_full (const struct GNUNET_HashCode * hc) { static struct GNUNET_CRYPTO_HashAsciiEncoded ret; @@ -930,6 +1085,7 @@ GNUNET_h2s_full (const GNUNET_HashCode * hc) return (const char *) ret.encoding; } + /** * Convert a peer identity to a string (for printing debug messages). * This is one of the very few calls in the entire API that is @@ -949,6 +1105,7 @@ GNUNET_i2s (const struct GNUNET_PeerIdentity *pid) return (const char *) ret.encoding; } + /** * Convert a peer identity to a string (for printing debug messages). * This is one of the very few calls in the entire API that is @@ -1033,6 +1190,45 @@ GNUNET_a2s (const struct sockaddr *addr, socklen_t addrlen) /** + * Log error message about missing configuration option. + * + * @param kind log level + * @param section section with missing option + * @param option name of missing option + */ +void +GNUNET_log_config_missing (enum GNUNET_ErrorType kind, + const char *section, + const char *option) +{ + GNUNET_log (kind, + _("Configuration fails to specify option `%s' in section `%s'!\n"), + option, + section); +} + + +/** + * Log error message about invalid configuration option value. + * + * @param kind log level + * @param section section with invalid option + * @param option name of invalid option + * @param required what is required that is invalid about the option + */ +void +GNUNET_log_config_invalid (enum GNUNET_ErrorType kind, + const char *section, + const char *option, + const char *required) +{ + GNUNET_log (kind, + _("Configuration specifies invalid value for option `%s' in section `%s': %s\n"), + option, section, required); +} + + +/** * Initializer */ void __attribute__ ((constructor)) GNUNET_util_cl_init () @@ -1041,6 +1237,10 @@ void __attribute__ ((constructor)) GNUNET_util_cl_init () #ifdef MINGW GNInitWinEnv (NULL); #endif +#if WINDOWS + if (!InitializeCriticalSectionAndSpinCount (&output_message_cs, 0x00000400))
+ GNUNET_abort (); +#endif } @@ -1049,6 +1249,9 @@ void __attribute__ ((constructor)) GNUNET_util_cl_init () */ void __attribute__ ((destructor)) GNUNET_util_cl_fini () { +#if WINDOWS + DeleteCriticalSection (&output_message_cs); +#endif #ifdef MINGW GNShutdownWinEnv (); #endif diff --git a/src/util/configuration.c b/src/util/configuration.c index 308672f..72fe0e7 100644 --- a/src/util/configuration.c +++ b/src/util/configuration.c @@ -140,118 +140,223 @@ GNUNET_CONFIGURATION_destroy (struct GNUNET_CONFIGURATION_Handle *cfg) /** - * Parse a configuration file, add all of the options in the - * file to the configuration environment. + * De-serializes configuration * * @param cfg configuration to update - * @param filename name of the configuration file - * @return GNUNET_OK on success, GNUNET_SYSERR on error + * @param mem the memory block of serialized configuration + * @param size the size of the memory block + * @param allow_inline set to GNUNET_YES if we recursively load configuration + * from inlined configurations; GNUNET_NO if not and raise warnings + * when we come across them + * @return GNUNET_OK on success, GNUNET_ERROR on error */ int -GNUNET_CONFIGURATION_parse (struct GNUNET_CONFIGURATION_Handle *cfg, - const char *filename) +GNUNET_CONFIGURATION_deserialize (struct GNUNET_CONFIGURATION_Handle *cfg, + const char *mem, + const size_t size, + int allow_inline) { - int dirty; - char line[256]; - char tag[64]; - char value[192]; - FILE *fp; + char *line; + char *line_orig; + size_t line_size; + char *pos; unsigned int nr; - int i; + size_t r_bytes; + size_t to_read; + size_t i; int emptyline; int ret; char *section; - char *fn; + char *eq; + char *tag; + char *value; - fn = GNUNET_STRINGS_filename_expand (filename); - if (fn == NULL) - return GNUNET_SYSERR; - dirty = cfg->dirty; /* back up value! */ - if (NULL == (fp = FOPEN (fn, "r"))) - { - LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fopen", fn); - GNUNET_free (fn); - return GNUNET_SYSERR; - } - GNUNET_free (fn); + LOG (GNUNET_ERROR_TYPE_DEBUG, "Deserializing config file\n"); ret = GNUNET_OK; section = GNUNET_strdup (""); - memset (line, 0, 256); nr = 0; - while (NULL != fgets (line, 255, fp)) + r_bytes = 0; + line_orig = NULL; + while (r_bytes < size) { + GNUNET_free_non_null (line_orig); + /* fgets-like behaviour on buffer */ + to_read = size - r_bytes; + pos = memchr (&mem[r_bytes], '\n', to_read); + if (NULL == pos) + { + line_orig = GNUNET_strndup (&mem[r_bytes], line_size = to_read); + r_bytes += line_size; + } + else + { + line_orig = GNUNET_strndup (&mem[r_bytes], line_size = (pos - &mem[r_bytes])); + r_bytes += line_size + 1; + } + line = line_orig; + /* increment line number */ nr++; - for (i = 0; i < 255; i++) + /* tabs and '\r' are whitespace */ + emptyline = GNUNET_YES; + for (i = 0; i < line_size; i++) + { if (line[i] == '\t') line[i] = ' '; - if (line[0] == '\n' || line[0] == '#' || line[0] == '%' || line[0] == '\r') - continue; - emptyline = 1; - for (i = 0; (i < 255 && line[i] != 0); i++) - if (line[i] != ' ' && line[i] != '\n' && line[i] != '\r') - emptyline = 0; - if (emptyline == 1) + if (line[i] == '\r') + line[i] = ' '; + if (' ' != line[i]) + emptyline = GNUNET_NO; + } + /* ignore empty lines */ + if (GNUNET_YES == emptyline) continue; + /* remove tailing whitespace */ - for (i = strlen (line) - 1; (i >= 0) && (isspace ((unsigned char) line[i])); - i--) + for (i = line_size - 1; (i >= 1) && (isspace ((unsigned char) line[i]));i--) line[i] = '\0'; - if (1 == SSCANF (line, "@INLINE@ %191[^\n]", value)) - { + + /* remove leading whitespace */ + for (; line[0] != '\0' && (isspace ((unsigned char) line[0])); line++); + + /* ignore comments */ + if ( ('#' == line[0]) || ('%' == line[0]) ) + continue; + + /* handle special "@INLINE@" directive */ + if (0 == strncasecmp (line, + "@INLINE@ ", + strlen ("@INLINE@ "))) + { /* @INLINE@ value */ - if (GNUNET_OK != GNUNET_CONFIGURATION_parse (cfg, value)) - ret = GNUNET_SYSERR; /* failed to parse included config */ + value = &line[strlen ("@INLINE@ ")]; + if (GNUNET_YES == allow_inline) + { + if (GNUNET_OK != GNUNET_CONFIGURATION_parse (cfg, value)) + { + ret = GNUNET_SYSERR; /* failed to parse included config */ + break; + } + } + else + { + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Ignoring parsing @INLINE@ configurations, not allowed!\n"); + ret = GNUNET_SYSERR; + break; + } + continue; } - else if (1 == SSCANF (line, "[%99[^]]]", value)) + if ( ('[' == line[0]) && (']' == line[line_size - 1]) ) { /* [value] */ + line[line_size - 1] = '\0'; + value = &line[1]; GNUNET_free (section); section = GNUNET_strdup (value); + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Config section `%s'\n", + section); + continue; } - else if (2 == SSCANF (line, " %63[^= ] = %191[^\n]", tag, value)) + if (NULL != (eq = strchr (line, '='))) { /* tag = value */ - /* Strip LF */ - i = strlen (value) - 1; - while ((i >= 0) && (isspace ((unsigned char) value[i]))) - value[i--] = '\0'; + tag = GNUNET_strndup (line, eq - line); + /* remove tailing whitespace */ + for (i = strlen (tag) - 1; (i >= 1) && (isspace ((unsigned char) tag[i]));i--) + tag[i] = '\0'; + + /* Strip whitespace */ + value = eq + 1; + while (isspace ((unsigned char) value[0])) + value++; + for (i = strlen (value) - 1; (i >= 1) && (isspace ((unsigned char) value[i]));i--) + value[i] = '\0'; + /* remove quotes */ i = 0; - if (value[0] == '"') + if ( ('"' == value[0]) && + ('"' == value[strlen (value) - 1]) ) { - i = 1; - while ((value[i] != '\0') && (value[i] != '"')) - i++; - if (value[i] == '"') - { - value[i] = '\0'; - i = 1; - } - else - i = 0; + value[strlen (value) - 1] = '\0'; + value++; } + LOG (GNUNET_ERROR_TYPE_DEBUG, "Config value %s=\"%s\"\n", tag, value); GNUNET_CONFIGURATION_set_value_string (cfg, section, tag, &value[i]); + GNUNET_free (tag); + continue; } - else if (1 == SSCANF (line, " %63[^= ] =[^\n]", tag)) - { - /* tag = */ - GNUNET_CONFIGURATION_set_value_string (cfg, section, tag, ""); - } - else - { - /* parse error */ - LOG (GNUNET_ERROR_TYPE_WARNING, - _("Syntax error in configuration file `%s' at line %u.\n"), filename, - nr); - ret = GNUNET_SYSERR; - break; - } + /* parse error */ + LOG (GNUNET_ERROR_TYPE_WARNING, + _("Syntax error while deserializing in line %u\n"), + nr); + ret = GNUNET_SYSERR; + break; + } + LOG (GNUNET_ERROR_TYPE_DEBUG, "Finished deserializing config\n"); + GNUNET_free_non_null (line_orig); + GNUNET_free (section); + GNUNET_assert ( (GNUNET_OK != ret) || (r_bytes == size) ); + return ret; +} + + +/** + * Parse a configuration file, add all of the options in the + * file to the configuration environment. + * + * @param cfg configuration to update + * @param filename name of the configuration file + * @return GNUNET_OK on success, GNUNET_SYSERR on error + */ +int +GNUNET_CONFIGURATION_parse (struct GNUNET_CONFIGURATION_Handle *cfg, + const char *filename) +{ + uint64_t fs64; + size_t fs; + char *fn; + char *mem; + int dirty; + int ret; + + LOG (GNUNET_ERROR_TYPE_DEBUG, "Asked to parse config file `%s'\n", filename); + fn = GNUNET_STRINGS_filename_expand (filename); + LOG (GNUNET_ERROR_TYPE_DEBUG, "Config file name expanded to `%s'\n", fn); + if (fn == NULL) + return GNUNET_SYSERR; + dirty = cfg->dirty; /* back up value! */ + if (GNUNET_SYSERR == + GNUNET_DISK_file_size (fn, &fs64, GNUNET_YES, GNUNET_YES)) + { + LOG (GNUNET_ERROR_TYPE_WARNING, + "Error while determining the file size of %s\n", fn); + GNUNET_free (fn); + return GNUNET_SYSERR; + } + if (fs64 > SIZE_MAX) + { + GNUNET_break (0); /* File size is more than the heap size */ + GNUNET_free (fn); + return GNUNET_SYSERR; + } + fs = fs64; + mem = GNUNET_malloc (fs); + if (fs != GNUNET_DISK_fn_read (fn, mem, fs)) + { + LOG (GNUNET_ERROR_TYPE_WARNING, + "Error while reading file %s\n", fn); + GNUNET_free (fn); + GNUNET_free (mem); + return GNUNET_SYSERR; } - GNUNET_assert (0 == FCLOSE (fp)); + LOG (GNUNET_ERROR_TYPE_DEBUG, "Deserializing contents of file `%s'\n", fn); + GNUNET_free (fn); + ret = GNUNET_CONFIGURATION_deserialize (cfg, mem, fs, GNUNET_YES); + GNUNET_free (mem); /* restore dirty flag - anything we set in the meantime * came from disk */ cfg->dirty = dirty; - GNUNET_free (section); return ret; } @@ -271,88 +376,140 @@ GNUNET_CONFIGURATION_is_dirty (const struct GNUNET_CONFIGURATION_Handle *cfg) /** - * Write configuration file. + * Serializes the given configuration. * - * @param cfg configuration to write - * @param filename where to write the configuration - * @return GNUNET_OK on success, GNUNET_SYSERR on error + * @param cfg configuration to serialize + * @param size will be set to the size of the serialized memory block + * @return the memory block where the serialized configuration is + * present. This memory should be freed by the caller */ -int -GNUNET_CONFIGURATION_write (struct GNUNET_CONFIGURATION_Handle *cfg, - const char *filename) +char * +GNUNET_CONFIGURATION_serialize (const struct GNUNET_CONFIGURATION_Handle *cfg, + size_t *size) { struct ConfigSection *sec; struct ConfigEntry *ent; - FILE *fp; - int error; - char *fn; + char *mem; + char *cbuf; char *val; char *pos; + int len; + size_t m_size; + size_t c_size; - fn = GNUNET_STRINGS_filename_expand (filename); - if (fn == NULL) - return GNUNET_SYSERR; - if (GNUNET_OK != GNUNET_DISK_directory_create_for_file (fn)) - { - GNUNET_free (fn); - return GNUNET_SYSERR; - } - if (NULL == (fp = FOPEN (fn, "w"))) - { - LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fopen", fn); - GNUNET_free (fn); - return GNUNET_SYSERR; - } - GNUNET_free (fn); - error = 0; + + /* Pass1 : calculate the buffer size required */ + m_size = 0; sec = cfg->sections; - while (sec != NULL) + while (NULL != sec) { - if (0 > FPRINTF (fp, "[%s]\n", sec->name)) + /* For each section we need to add 3 charaters: {'[',']','\n'} */ + m_size += strlen (sec->name) + 3; + ent = sec->entries; + while (NULL != ent) { - error = 1; - break; + if (NULL != ent->val) + { + /* if val has any '\n' then they occupy +1 character as '\n'->'\\','n' */ + pos = ent->val; + while (NULL != (pos = strstr (pos, "\n"))) + { + m_size++; + pos++; + } + /* For each key = value pair we need to add 4 characters (2 + spaces and 1 equal-to character and 1 new line) */ + m_size += strlen (ent->key) + strlen (ent->val) + 4; + } + ent = ent->next; } + /* A new line after section end */ + m_size++; + sec = sec->next; + } + + /* Pass2: Allocate memory and write the configuration to it */ + mem = GNUNET_malloc (m_size); + sec = cfg->sections; + c_size = 0; + *size = c_size; + while (NULL != sec) + { + len = GNUNET_asprintf (&cbuf, "[%s]\n", sec->name); + GNUNET_assert (0 < len); + memcpy (mem + c_size, cbuf, len); + c_size += len; + GNUNET_free (cbuf); ent = sec->entries; - while (ent != NULL) + while (NULL != ent) { - if (ent->val != NULL) + if (NULL != ent->val) { - val = GNUNET_malloc (strlen (ent->val) * 2 + 1); - strcpy (val, ent->val); + val = GNUNET_malloc (strlen (ent->val) * 2 + 1); + strcpy (val, ent->val); while (NULL != (pos = strstr (val, "\n"))) { memmove (&pos[2], &pos[1], strlen (&pos[1])); pos[0] = '\\'; pos[1] = 'n'; } - if (0 > FPRINTF (fp, "%s = %s\n", ent->key, val)) - { - error = 1; - GNUNET_free (val); - break; - } - GNUNET_free (val); + len = GNUNET_asprintf (&cbuf, "%s = %s\n", ent->key, val); + GNUNET_free (val); + memcpy (mem + c_size, cbuf, len); + c_size += len; + GNUNET_free (cbuf); } ent = ent->next; } - if (error != 0) - break; - if (0 > FPRINTF (fp, "%s\n", "")) - { - error = 1; - break; - } + memcpy (mem + c_size, "\n", 1); + c_size ++; sec = sec->next; } - if (error != 0) - LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fprintf", filename); - GNUNET_assert (0 == FCLOSE (fp)); - if (error != 0) + GNUNET_assert (c_size == m_size); + *size = c_size; + return mem; +} + + +/** + * Write configuration file. + * + * @param cfg configuration to write + * @param filename where to write the configuration + * @return GNUNET_OK on success, GNUNET_SYSERR on error + */ +int +GNUNET_CONFIGURATION_write (struct GNUNET_CONFIGURATION_Handle *cfg, + const char *filename) +{ + char *fn; + char *cfg_buf; + size_t size; + + fn = GNUNET_STRINGS_filename_expand (filename); + if (fn == NULL) + return GNUNET_SYSERR; + if (GNUNET_OK != GNUNET_DISK_directory_create_for_file (fn)) { + GNUNET_free (fn); + return GNUNET_SYSERR; + } + cfg_buf = GNUNET_CONFIGURATION_serialize (cfg, &size); + if (size != GNUNET_DISK_fn_write (fn, cfg_buf, size, + GNUNET_DISK_PERM_USER_READ + | GNUNET_DISK_PERM_USER_WRITE + | GNUNET_DISK_PERM_GROUP_READ + | GNUNET_DISK_PERM_GROUP_WRITE)) + { + GNUNET_free (fn); + GNUNET_free (cfg_buf); + LOG (GNUNET_ERROR_TYPE_WARNING, + "Writing configration to file: %s failed\n", filename); cfg->dirty = GNUNET_SYSERR; /* last write failed */ return GNUNET_SYSERR; } + GNUNET_free (fn); + GNUNET_free (cfg_buf); cfg->dirty = GNUNET_NO; /* last write succeeded */ return GNUNET_OK; } @@ -579,8 +736,8 @@ findEntry (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, * @param value value to copy (of the default conf.) */ static void -compareEntries (void *cls, const char *section, const char *option, - const char *value) +compare_entries (void *cls, const char *section, const char *option, + const char *value) { struct DiffHandle *dh = cls; struct ConfigEntry *entNew; @@ -593,6 +750,28 @@ compareEntries (void *cls, const char *section, const char *option, /** + * Compute configuration with only entries that have been changed + * + * @param cfgDefault original configuration + * @param cfgNew new configuration + * @return configuration with only the differences, never NULL + */ +struct GNUNET_CONFIGURATION_Handle * +GNUNET_CONFIGURATION_get_diff (const struct GNUNET_CONFIGURATION_Handle + *cfgDefault, + const struct GNUNET_CONFIGURATION_Handle + *cfgNew) +{ + struct DiffHandle diffHandle; + + diffHandle.cfgDiff = GNUNET_CONFIGURATION_create (); + diffHandle.cfgDefault = cfgDefault; + GNUNET_CONFIGURATION_iterate (cfgNew, &compare_entries, &diffHandle); + return diffHandle.cfgDiff; +} + + +/** * Write only configuration entries that have been changed to configuration file * @param cfgDefault default configuration * @param cfgNew new configuration @@ -606,13 +785,11 @@ GNUNET_CONFIGURATION_write_diffs (const struct GNUNET_CONFIGURATION_Handle *cfgNew, const char *filename) { int ret; - struct DiffHandle diffHandle; + struct GNUNET_CONFIGURATION_Handle *diff; - diffHandle.cfgDiff = GNUNET_CONFIGURATION_create (); - diffHandle.cfgDefault = cfgDefault; - GNUNET_CONFIGURATION_iterate (cfgNew, compareEntries, &diffHandle); - ret = GNUNET_CONFIGURATION_write (diffHandle.cfgDiff, filename); - GNUNET_CONFIGURATION_destroy (diffHandle.cfgDiff); + diff = GNUNET_CONFIGURATION_get_diff (cfgDefault, cfgNew); + ret = GNUNET_CONFIGURATION_write (diff, filename); + GNUNET_CONFIGURATION_destroy (diff); return ret; } @@ -632,12 +809,14 @@ GNUNET_CONFIGURATION_set_value_string (struct GNUNET_CONFIGURATION_Handle *cfg, { struct ConfigSection *sec; struct ConfigEntry *e; + char *nv; e = findEntry (cfg, section, option); if (e != NULL) { + nv = GNUNET_strdup (value); GNUNET_free_non_null (e->val); - e->val = GNUNET_strdup (value); + e->val = nv; return; } sec = findSection (cfg, section); @@ -768,13 +947,16 @@ GNUNET_CONFIGURATION_get_value_string (const struct GNUNET_CONFIGURATION_Handle { struct ConfigEntry *e; + LOG (GNUNET_ERROR_TYPE_DEBUG, "Asked to retrieve string `%s' in section `%s'\n", option, section); e = findEntry (cfg, section, option); if ((e == NULL) || (e->val == NULL)) { + LOG (GNUNET_ERROR_TYPE_DEBUG, "Failed to retrieve the string\n"); *value = NULL; return GNUNET_SYSERR; } *value = GNUNET_strdup (e->val); + LOG (GNUNET_ERROR_TYPE_DEBUG, "Retrieved string `%s'\n", e->val); return GNUNET_OK; } @@ -861,8 +1043,13 @@ GNUNET_CONFIGURATION_expand_dollar (const struct GNUNET_CONFIGURATION_Handle const char *post; const char *env; + LOG (GNUNET_ERROR_TYPE_DEBUG, "Asked to $-expand %s\n", orig); + if (orig[0] != '$') + { + LOG (GNUNET_ERROR_TYPE_DEBUG, "Doesn't start with $ - not expanding\n"); return orig; + } i = 0; while ((orig[i] != '/') && (orig[i] != '\\') && (orig[i] != '\0')) i++; @@ -875,16 +1062,21 @@ GNUNET_CONFIGURATION_expand_dollar (const struct GNUNET_CONFIGURATION_Handle orig[i] = '\0'; post = &orig[i + 1]; } + LOG (GNUNET_ERROR_TYPE_DEBUG, "Split into `%s' and `%s'\n", orig, post); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "PATHS", &orig[1], &prefix)) { + LOG (GNUNET_ERROR_TYPE_DEBUG, "Filename for `%s' is not in PATHS config section\n", &orig[1]); if (NULL == (env = getenv (&orig[1]))) { + LOG (GNUNET_ERROR_TYPE_DEBUG, "`%s' is not an environment variable\n", &orig[1]); orig[i] = DIR_SEPARATOR; + LOG (GNUNET_ERROR_TYPE_DEBUG, "Expanded to `%s' (returning orig)\n", orig); return orig; } prefix = GNUNET_strdup (env); } + LOG (GNUNET_ERROR_TYPE_DEBUG, "Prefix is `%s'\n", prefix); result = GNUNET_malloc (strlen (prefix) + strlen (post) + 2); strcpy (result, prefix); if ((strlen (prefix) == 0) || @@ -893,6 +1085,7 @@ GNUNET_CONFIGURATION_expand_dollar (const struct GNUNET_CONFIGURATION_Handle strcat (result, post); GNUNET_free (prefix); GNUNET_free (orig); + LOG (GNUNET_ERROR_TYPE_DEBUG, "Expanded to `%s'\n", result); return result; } @@ -914,16 +1107,21 @@ GNUNET_CONFIGURATION_get_value_filename (const struct const char *option, char **value) { char *tmp; - + + LOG (GNUNET_ERROR_TYPE_DEBUG, "Asked to retrieve filename `%s' in section `%s'\n", option, section); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, section, option, &tmp)) { + LOG (GNUNET_ERROR_TYPE_DEBUG, "Failed to retrieve filename\n"); *value = NULL; return GNUNET_SYSERR; } + LOG (GNUNET_ERROR_TYPE_DEBUG, "Retrieved filename `%s', $-expanding\n", tmp); tmp = GNUNET_CONFIGURATION_expand_dollar (cfg, tmp); + LOG (GNUNET_ERROR_TYPE_DEBUG, "Expanded to filename `%s', *nix-expanding\n", tmp); *value = GNUNET_STRINGS_filename_expand (tmp); GNUNET_free (tmp); + LOG (GNUNET_ERROR_TYPE_DEBUG, "Filename result is `%s'\n", *value); if (*value == NULL) return GNUNET_SYSERR; return GNUNET_OK; diff --git a/src/util/connection.c b/src/util/connection.c index 31e6399..c4795ce 100644 --- a/src/util/connection.c +++ b/src/util/connection.c @@ -247,7 +247,14 @@ struct GNUNET_CONNECTION_Handle * termination as a signal (because only then will the leaked * socket be freed!) */ - int16_t persist; + int8_t persist; + + /** + * Usually 0. Set to 1 if this handle is in used and should + * 'GNUNET_CONNECTION_destroy' be called right now, the action needs + * to be deferred by setting it to -1. + */ + int8_t destroy_later; }; @@ -556,6 +563,7 @@ connect_fail_continuation (struct GNUNET_CONNECTION_Handle *connection) GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == connection->write_task); /* signal errors for jobs that used to wait on the connection */ + connection->destroy_later = 1; if (NULL != connection->receiver) signal_receive_error (connection, ECONNREFUSED); if (NULL != connection->nth.notify_ready) @@ -565,6 +573,14 @@ connect_fail_continuation (struct GNUNET_CONNECTION_Handle *connection) connection->nth.timeout_task = GNUNET_SCHEDULER_NO_TASK; signal_transmit_error (connection, ECONNREFUSED); } + if (-1 == connection->destroy_later) + { + /* do it now */ + connection->destroy_later = 0; + GNUNET_CONNECTION_destroy (connection); + return; + } + connection->destroy_later = 0; } @@ -744,10 +760,6 @@ try_connect_using_address (void *cls, const struct sockaddr *addr, { /* maybe refused / unsupported address, try next */ LOG_STRERROR (GNUNET_ERROR_TYPE_INFO, "connect"); -#if 0 - LOG (GNUNET_ERROR_TYPE_INFO, _("Failed to connect to `%s' (%p)\n"), - GNUNET_a2s (ap->addr, ap->addrlen), connection); -#endif GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (ap->sock)); GNUNET_free (ap); return; @@ -852,8 +864,9 @@ GNUNET_CONNECTION_create_from_connect_to_unixpath (const struct GNUNET_free (connection); return NULL; } - if (GNUNET_OK != - GNUNET_NETWORK_socket_connect (connection->sock, connection->addr, connection->addrlen)) + if ( (GNUNET_OK != + GNUNET_NETWORK_socket_connect (connection->sock, connection->addr, connection->addrlen)) && + (EINPROGRESS != errno) ) { /* Just return; we expect everything to work eventually so don't fail HARD */ GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (connection->sock)); @@ -941,6 +954,11 @@ GNUNET_CONNECTION_destroy (struct GNUNET_CONNECTION_Handle *connection) { struct AddressProbe *pos; + if (0 != connection->destroy_later) + { + connection->destroy_later = -1; + return; + } LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down connection (%p)\n", connection); GNUNET_assert (NULL == connection->nth.notify_ready); GNUNET_assert (NULL == connection->receiver); diff --git a/src/util/container_bloomfilter.c b/src/util/container_bloomfilter.c index 8c226f6..1a2c876 100644 --- a/src/util/container_bloomfilter.c +++ b/src/util/container_bloomfilter.c @@ -231,7 +231,7 @@ static void decrementBit (char *bitArray, unsigned int bitIdx, const struct GNUNET_DISK_FileHandle *fh) { - OFF_T fileSlot; + OFF_T fileslot; unsigned char value; unsigned int high; unsigned int low; @@ -240,9 +240,13 @@ decrementBit (char *bitArray, unsigned int bitIdx, if (GNUNET_DISK_handle_invalid (fh)) return; /* cannot decrement! */ /* Each char slot in the counter file holds two 4 bit counters */ - fileSlot = bitIdx / 2; + fileslot = bitIdx / 2; targetLoc = bitIdx % 2; - GNUNET_DISK_file_seek (fh, fileSlot, GNUNET_DISK_SEEK_SET); + if (GNUNET_SYSERR == GNUNET_DISK_file_seek (fh, fileslot, GNUNET_DISK_SEEK_SET)) + { + GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "seek"); + return; + } if (1 != GNUNET_DISK_file_read (fh, &value, 1)) value = 0; low = value & 0xF; @@ -268,7 +272,11 @@ decrementBit (char *bitArray, unsigned int bitIdx, } } value = ((high << 4) | low); - GNUNET_DISK_file_seek (fh, fileSlot, GNUNET_DISK_SEEK_SET); + if (GNUNET_SYSERR == GNUNET_DISK_file_seek (fh, fileslot, GNUNET_DISK_SEEK_SET)) + { + GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "seek"); + return; + } GNUNET_assert (1 == GNUNET_DISK_file_write (fh, &value, 1)); } @@ -340,9 +348,9 @@ typedef int (*BitIterator) (void *cls, */ static void iterateBits (const struct GNUNET_CONTAINER_BloomFilter *bf, - BitIterator callback, void *arg, const GNUNET_HashCode * key) + BitIterator callback, void *arg, const struct GNUNET_HashCode * key) { - GNUNET_HashCode tmp[2]; + struct GNUNET_HashCode tmp[2]; int bitCount; unsigned int round; unsigned int slot = 0; @@ -354,7 +362,7 @@ iterateBits (const struct GNUNET_CONTAINER_BloomFilter *bf, GNUNET_assert (bf->bitArraySize * 8LL > bf->bitArraySize); while (bitCount > 0) { - while (slot < (sizeof (GNUNET_HashCode) / sizeof (uint32_t))) + while (slot < (sizeof (struct GNUNET_HashCode) / sizeof (uint32_t))) { if (GNUNET_YES != callback (arg, bf, @@ -368,7 +376,7 @@ iterateBits (const struct GNUNET_CONTAINER_BloomFilter *bf, } if (bitCount > 0) { - GNUNET_CRYPTO_hash (&tmp[round & 1], sizeof (GNUNET_HashCode), + GNUNET_CRYPTO_hash (&tmp[round & 1], sizeof (struct GNUNET_HashCode), &tmp[(round + 1) & 1]); round++; slot = 0; @@ -696,7 +704,7 @@ GNUNET_CONTAINER_bloomfilter_clear (struct GNUNET_CONTAINER_BloomFilter *bf) */ int GNUNET_CONTAINER_bloomfilter_test (const struct GNUNET_CONTAINER_BloomFilter - *bf, const GNUNET_HashCode * e) + *bf, const struct GNUNET_HashCode * e) { int res; @@ -716,7 +724,7 @@ GNUNET_CONTAINER_bloomfilter_test (const struct GNUNET_CONTAINER_BloomFilter */ void GNUNET_CONTAINER_bloomfilter_add (struct GNUNET_CONTAINER_BloomFilter *bf, - const GNUNET_HashCode * e) + const struct GNUNET_HashCode * e) { if (NULL == bf) return; @@ -801,7 +809,7 @@ GNUNET_CONTAINER_bloomfilter_or2 (struct GNUNET_CONTAINER_BloomFilter *bf, */ void GNUNET_CONTAINER_bloomfilter_remove (struct GNUNET_CONTAINER_BloomFilter *bf, - const GNUNET_HashCode * e) + const struct GNUNET_HashCode * e) { if (NULL == bf) return; @@ -827,7 +835,7 @@ GNUNET_CONTAINER_bloomfilter_resize (struct GNUNET_CONTAINER_BloomFilter *bf, void *iterator_cls, size_t size, unsigned int k) { - GNUNET_HashCode hc; + struct GNUNET_HashCode hc; unsigned int i; GNUNET_free (bf->bitArray); diff --git a/src/util/container_heap.c b/src/util/container_heap.c index b9cab1e..e2a2700 100644 --- a/src/util/container_heap.c +++ b/src/util/container_heap.c @@ -400,6 +400,8 @@ GNUNET_CONTAINER_heap_remove_root (struct GNUNET_CONTAINER_Heap *heap) heap->root = root->left_child; insert_node (heap, heap->root, root->right_child); } + if (heap->walk_pos == root) + heap->walk_pos = heap->root; GNUNET_free (root); #if EXTRA_CHECKS GNUNET_assert (((heap->size == 0) && (heap->root == NULL)) || diff --git a/src/util/container_meta_data.c b/src/util/container_meta_data.c index b1051c8..a868e81 100644 --- a/src/util/container_meta_data.c +++ b/src/util/container_meta_data.c @@ -40,11 +40,16 @@ struct MetaItem { /** - * This is a linked list. + * This is a doubly linked list. */ struct MetaItem *next; /** + * This is a doubly linked list. + */ + struct MetaItem *prev; + + /** * Name of the extracting plugin. */ char *plugin_name; @@ -82,9 +87,14 @@ struct MetaItem struct GNUNET_CONTAINER_MetaData { /** - * Linked list of the meta data items. + * Head of linked list of the meta data items. */ - struct MetaItem *items; + struct MetaItem *items_head; + + /** + * Tail of linked list of the meta data items. + */ + struct MetaItem *items_tail; /** * Complete serialized and compressed buffer of the items. @@ -120,15 +130,15 @@ GNUNET_CONTAINER_meta_data_create () /** * Free meta data item. * - * @param item item to free + * @param mi item to free */ static void -meta_item_free (struct MetaItem *item) +meta_item_free (struct MetaItem *mi) { - GNUNET_free_non_null (item->plugin_name); - GNUNET_free_non_null (item->mime_type); - GNUNET_free_non_null (item->data); - GNUNET_free (item); + GNUNET_free_non_null (mi->plugin_name); + GNUNET_free_non_null (mi->mime_type); + GNUNET_free_non_null (mi->data); + GNUNET_free (mi); } @@ -141,7 +151,7 @@ meta_item_free (struct MetaItem *item) static void invalidate_sbuf (struct GNUNET_CONTAINER_MetaData *md) { - if (md->sbuf == NULL) + if (NULL == md->sbuf) return; GNUNET_free (md->sbuf); md->sbuf = NULL; @@ -157,14 +167,14 @@ invalidate_sbuf (struct GNUNET_CONTAINER_MetaData *md) void GNUNET_CONTAINER_meta_data_destroy (struct GNUNET_CONTAINER_MetaData *md) { - struct MetaItem *item; + struct MetaItem *pos; - if (md == NULL) + if (NULL == md) return; - while (NULL != (item = md->items)) + while (NULL != (pos = md->items_head)) { - md->items = item->next; - meta_item_free (item); + GNUNET_CONTAINER_DLL_remove (md->items_head, md->items_tail, pos); + meta_item_free (pos); } GNUNET_free_non_null (md->sbuf); GNUNET_free (md); @@ -179,21 +189,20 @@ GNUNET_CONTAINER_meta_data_destroy (struct GNUNET_CONTAINER_MetaData *md) void GNUNET_CONTAINER_meta_data_clear (struct GNUNET_CONTAINER_MetaData *md) { - struct MetaItem *item; + struct MetaItem *mi; - if (md == NULL) + if (NULL == md) return; - while (NULL != (item = md->items)) + while (NULL != (mi = md->items_head)) { - md->items = item->next; - meta_item_free (item); + GNUNET_CONTAINER_DLL_remove (md->items_head, md->items_tail, mi); + meta_item_free (mi); } GNUNET_free_non_null (md->sbuf); memset (md, 0, sizeof (struct GNUNET_CONTAINER_MetaData)); } - /** * Test if two MDs are equal. We consider them equal if * the meta types, formats and content match (we do not @@ -218,13 +227,10 @@ GNUNET_CONTAINER_meta_data_test_equal (const struct GNUNET_CONTAINER_MetaData return GNUNET_YES; if (md1->item_count != md2->item_count) return GNUNET_NO; - - i = md1->items; - while (NULL != i) + for (i = md1->items_head; NULL != i; i = i->next) { found = GNUNET_NO; - j = md2->items; - while (NULL != j) + for (j = md2->items_head; NULL != j; j = j->next) { if ((i->type == j->type) && (i->format == j->format) && (i->data_size == j->data_size) && @@ -233,11 +239,11 @@ GNUNET_CONTAINER_meta_data_test_equal (const struct GNUNET_CONTAINER_MetaData found = GNUNET_YES; break; } - j = j->next; + if (j->data_size < i->data_size) + break; /* elements are sorted by (decreasing) size... */ } - if (found == GNUNET_NO) + if (GNUNET_NO == found) return GNUNET_NO; - i = i->next; } return GNUNET_YES; } @@ -257,7 +263,7 @@ GNUNET_CONTAINER_meta_data_test_equal (const struct GNUNET_CONTAINER_MetaData * @param data_mime_type mime-type of data (not of the original file); * can be NULL (if mime-type is not known) * @param data actual meta-data found - * @param data_len number of bytes in data + * @param data_size number of bytes in data * @return GNUNET_OK on success, GNUNET_SYSERR if this entry already exists * data_mime_type and plugin_name are not considered for "exists" checks */ @@ -267,64 +273,61 @@ GNUNET_CONTAINER_meta_data_insert (struct GNUNET_CONTAINER_MetaData *md, enum EXTRACTOR_MetaType type, enum EXTRACTOR_MetaFormat format, const char *data_mime_type, const char *data, - size_t data_len) + size_t data_size) { - struct MetaItem *prev; struct MetaItem *pos; - struct MetaItem *i; + struct MetaItem *mi; char *p; - prev = NULL; - pos = md->items; - while (NULL != pos) + for (pos = md->items_head; NULL != pos; pos = pos->next) { - if (pos->data_size < data_len) - break; - if ((pos->type == type) && (pos->data_size == data_len) && - (0 == memcmp (pos->data, data, data_len))) + if (pos->data_size < data_size) + break; /* elements are sorted by size in the list */ + if ((pos->type == type) && (pos->data_size == data_size) && + (0 == memcmp (pos->data, data, data_size))) { - if ((pos->mime_type == NULL) && (data_mime_type != NULL)) + if ((NULL == pos->mime_type) && (NULL != data_mime_type)) { pos->mime_type = GNUNET_strdup (data_mime_type); invalidate_sbuf (md); } - if ((pos->format == EXTRACTOR_METAFORMAT_C_STRING) && - (format == EXTRACTOR_METAFORMAT_UTF8)) + if ((EXTRACTOR_METAFORMAT_C_STRING == pos->format) && + (EXTRACTOR_METAFORMAT_UTF8 == format)) { pos->format = EXTRACTOR_METAFORMAT_UTF8; invalidate_sbuf (md); } return GNUNET_SYSERR; } - prev = pos; - pos = pos->next; } md->item_count++; - i = GNUNET_malloc (sizeof (struct MetaItem)); - i->type = type; - i->format = format; - i->data_size = data_len; - i->next = pos; - if (prev == NULL) - md->items = i; + mi = GNUNET_malloc (sizeof (struct MetaItem)); + mi->type = type; + mi->format = format; + mi->data_size = data_size; + if (NULL == pos) + GNUNET_CONTAINER_DLL_insert_tail (md->items_head, + md->items_tail, + mi); else - prev->next = i; - i->mime_type = - (data_mime_type == NULL) ? NULL : GNUNET_strdup (data_mime_type); - i->plugin_name = (plugin_name == NULL) ? NULL : GNUNET_strdup (plugin_name); - i->data = GNUNET_malloc (data_len); - memcpy (i->data, data, data_len); - /* change OS native dir separators to unix '/' and others to '_' */ - if ( (type == EXTRACTOR_METATYPE_FILENAME) || - (type == EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME) ) + GNUNET_CONTAINER_DLL_insert_after (md->items_head, + md->items_tail, + pos->prev, + mi); + mi->mime_type = + (NULL == data_mime_type) ? NULL : GNUNET_strdup (data_mime_type); + mi->plugin_name = (NULL == plugin_name) ? NULL : GNUNET_strdup (plugin_name); + mi->data = GNUNET_malloc (data_size); + memcpy (mi->data, data, data_size); + /* change all dir separators to POSIX style ('/') */ + if ( (EXTRACTOR_METATYPE_FILENAME == type) || + (EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME == type) ) { - p = i->data; - while ((*p != '\0') && (p < i->data + data_len)) + p = mi->data; + while (('\0' != *p) && (p < mi->data + data_size)) { - if (*p == DIR_SEPARATOR) + if ('\\' == *p) *p = '/'; - else if (*p == '\\') - *p = '_'; p++; } } @@ -346,18 +349,18 @@ GNUNET_CONTAINER_meta_data_insert (struct GNUNET_CONTAINER_MetaData *md, * @param data_mime_type mime-type of data (not of the original file); * can be NULL (if mime-type is not known) * @param data actual meta-data found - * @param data_len number of bytes in data + * @param data_size number of bytes in data * @return 0 (to continue) */ static int merge_helper (void *cls, const char *plugin_name, enum EXTRACTOR_MetaType type, enum EXTRACTOR_MetaFormat format, const char *data_mime_type, - const char *data, size_t data_len) + const char *data, size_t data_size) { struct GNUNET_CONTAINER_MetaData *md = cls; (void) GNUNET_CONTAINER_meta_data_insert (md, plugin_name, type, format, - data_mime_type, data, data_len); + data_mime_type, data, data_size); return 0; } @@ -384,37 +387,31 @@ GNUNET_CONTAINER_meta_data_merge (struct GNUNET_CONTAINER_MetaData *md, * @param type type of the item to remove * @param data specific value to remove, NULL to remove all * entries of the given type - * @param data_len number of bytes in data + * @param data_size number of bytes in data * @return GNUNET_OK on success, GNUNET_SYSERR if the item does not exist in md */ int GNUNET_CONTAINER_meta_data_delete (struct GNUNET_CONTAINER_MetaData *md, enum EXTRACTOR_MetaType type, - const char *data, size_t data_len) + const char *data, size_t data_size) { struct MetaItem *pos; - struct MetaItem *prev; - prev = NULL; - pos = md->items; - while (NULL != pos) + for (pos = md->items_head; NULL != pos; pos = pos->next) { + if (pos->data_size < data_size) + break; /* items are sorted by (decreasing) size */ if ((pos->type == type) && - ((data == NULL) || - ((pos->data_size == data_len) && - (0 == memcmp (pos->data, data, data_len))))) + ((NULL == data) || + ((pos->data_size == data_size) && + (0 == memcmp (pos->data, data, data_size))))) { - if (prev == NULL) - md->items = pos->next; - else - prev->next = pos->next; + GNUNET_CONTAINER_DLL_remove (md->items_head, md->items_tail, pos); meta_item_free (pos); md->item_count--; invalidate_sbuf (md); return GNUNET_OK; } - prev = pos; - pos = pos->next; } return GNUNET_SYSERR; } @@ -430,7 +427,7 @@ void GNUNET_CONTAINER_meta_data_add_publication_date (struct GNUNET_CONTAINER_MetaData *md) { - char *dat; + const char *dat; struct GNUNET_TIME_Absolute t; t = GNUNET_TIME_absolute_get (); @@ -441,7 +438,6 @@ GNUNET_CONTAINER_meta_data_add_publication_date (struct EXTRACTOR_METATYPE_PUBLICATION_DATE, EXTRACTOR_METAFORMAT_UTF8, "text/plain", dat, strlen (dat) + 1); - GNUNET_free (dat); } @@ -460,19 +456,15 @@ GNUNET_CONTAINER_meta_data_iterate (const struct GNUNET_CONTAINER_MetaData *md, { struct MetaItem *pos; - if (md == NULL) + if (NULL == md) return 0; - if (iter == NULL) + if (NULL == iter) return md->item_count; - pos = md->items; - while (NULL != pos) - { + for (pos = md->items_head; NULL != pos; pos = pos->next) if (0 != iter (iter_cls, pos->plugin_name, pos->type, pos->format, pos->mime_type, pos->data, pos->data_size)) return md->item_count; - pos = pos->next; - } return md->item_count; } @@ -493,17 +485,13 @@ GNUNET_CONTAINER_meta_data_get_by_type (const struct GNUNET_CONTAINER_MetaData { struct MetaItem *pos; - if (md == NULL) + if (NULL == md) return NULL; - pos = md->items; - while (NULL != pos) - { + for (pos = md->items_head; NULL != pos; pos = pos->next) if ((type == pos->type) && ((pos->format == EXTRACTOR_METAFORMAT_UTF8) || (pos->format == EXTRACTOR_METAFORMAT_C_STRING))) return GNUNET_strdup (pos->data); - pos = pos->next; - } return NULL; } @@ -528,18 +516,16 @@ GNUNET_CONTAINER_meta_data_get_first_by_types (const struct va_list args; enum EXTRACTOR_MetaType type; - if (md == NULL) + if (NULL == md) return NULL; ret = NULL; va_start (args, md); while (1) { type = va_arg (args, enum EXTRACTOR_MetaType); - - if (type == -1) + if (-1 == type) break; - ret = GNUNET_CONTAINER_meta_data_get_by_type (md, type); - if (ret != NULL) + if (NULL != (ret = GNUNET_CONTAINER_meta_data_get_by_type (md, type))) break; } va_end (args); @@ -562,25 +548,23 @@ GNUNET_CONTAINER_meta_data_get_thumbnail (const struct GNUNET_CONTAINER_MetaData struct MetaItem *pos; struct MetaItem *match; - if (md == NULL) + if (NULL == md) return 0; match = NULL; - pos = md->items; - while (NULL != pos) + for (pos = md->items_head; NULL != pos; pos = pos->next) { if ((NULL != pos->mime_type) && (0 == strncasecmp ("image/", pos->mime_type, strlen ("image/"))) && - (pos->format == EXTRACTOR_METAFORMAT_BINARY)) + (EXTRACTOR_METAFORMAT_BINARY == pos->format)) { - if (match == NULL) + if (NULL == match) match = pos; else if ((match->type != EXTRACTOR_METATYPE_THUMBNAIL) && (pos->type == EXTRACTOR_METATYPE_THUMBNAIL)) match = pos; } - pos = pos->next; } - if ((match == NULL) || (match->data_size == 0)) + if ((NULL == match) || (0 == match->data_size)) return 0; *thumb = GNUNET_malloc (match->data_size); memcpy (*thumb, match->data, match->data_size); @@ -601,17 +585,13 @@ GNUNET_CONTAINER_meta_data_duplicate (const struct GNUNET_CONTAINER_MetaData struct GNUNET_CONTAINER_MetaData *ret; struct MetaItem *pos; - if (md == NULL) + if (NULL == md) return NULL; ret = GNUNET_CONTAINER_meta_data_create (); - pos = md->items; - while (NULL != pos) - { + for (pos = md->items_tail; NULL != pos; pos = pos->prev) GNUNET_CONTAINER_meta_data_insert (ret, pos->plugin_name, pos->type, pos->format, pos->mime_type, pos->data, pos->data_size); - pos = pos->next; - } return ret; } @@ -781,10 +761,10 @@ GNUNET_CONTAINER_meta_data_serialize (const struct GNUNET_CONTAINER_MetaData if (max < sizeof (struct MetaDataHeader)) return GNUNET_SYSERR; /* far too small */ - if (md == NULL) + if (NULL == md) return 0; - if (md->sbuf != NULL) + if (NULL != md->sbuf) { /* try to use serialization cache */ if (md->sbuf_size <= max) @@ -800,16 +780,14 @@ GNUNET_CONTAINER_meta_data_serialize (const struct GNUNET_CONTAINER_MetaData } dst = NULL; msize = 0; - pos = md->items; - while (NULL != pos) + for (pos = md->items_tail; NULL != pos; pos = pos->prev) { msize += sizeof (struct MetaDataEntry); msize += pos->data_size; - if (pos->plugin_name != NULL) + if (NULL != pos->plugin_name) msize += strlen (pos->plugin_name) + 1; - if (pos->mime_type != NULL) + if (NULL != pos->mime_type) msize += strlen (pos->mime_type) + 1; - pos = pos->next; } size = (size_t) msize; if (size != msize) @@ -826,8 +804,7 @@ GNUNET_CONTAINER_meta_data_serialize (const struct GNUNET_CONTAINER_MetaData mdata = (char *) &ent[md->item_count]; off = size - (md->item_count * sizeof (struct MetaDataEntry)); i = 0; - pos = md->items; - while (NULL != pos) + for (pos = md->items_head; NULL != pos; pos = pos->next) { ent[i].type = htonl ((uint32_t) pos->type); ent[i].format = htonl ((uint32_t) pos->format); @@ -851,22 +828,20 @@ GNUNET_CONTAINER_meta_data_serialize (const struct GNUNET_CONTAINER_MetaData if (pos->mime_type != NULL) memcpy (&mdata[off], pos->mime_type, mlen); i++; - pos = pos->next; } - GNUNET_assert (off == 0); + GNUNET_assert (0 == off); clen = 0; cdata = NULL; left = size; i = 0; - pos = md->items; - while (pos != NULL) + for (pos = md->items_head; NULL != pos; pos = pos->next) { comp = GNUNET_NO; if (0 == (opt & GNUNET_CONTAINER_META_DATA_SERIALIZE_NO_COMPRESS)) comp = try_compression ((const char *) &ent[i], left, &cdata, &clen); - if ((md->sbuf == NULL) && (i == 0)) + if ((NULL == md->sbuf) && (0 == i)) { /* fill 'sbuf'; this "modifies" md, but since this is only * an internal cache we will cast away the 'const' instead @@ -892,12 +867,12 @@ GNUNET_CONTAINER_meta_data_serialize (const struct GNUNET_CONTAINER_MetaData } if (((left + sizeof (struct MetaDataHeader)) <= max) || - ((comp == GNUNET_YES) && (clen <= max))) + ((GNUNET_YES == comp) && (clen <= max))) { /* success, this now fits! */ if (GNUNET_YES == comp) { - if (dst == NULL) + if (NULL == dst) dst = GNUNET_malloc (clen + sizeof (struct MetaDataHeader)); hdr = (struct MetaDataHeader *) dst; hdr->version = htonl (2 | HEADER_COMPRESSED); @@ -905,12 +880,13 @@ GNUNET_CONTAINER_meta_data_serialize (const struct GNUNET_CONTAINER_MetaData hdr->entries = htonl (md->item_count - i); memcpy (&dst[sizeof (struct MetaDataHeader)], cdata, clen); GNUNET_free (cdata); + cdata = NULL; GNUNET_free (ent); rlen = clen + sizeof (struct MetaDataHeader); } else { - if (dst == NULL) + if (NULL == dst) dst = GNUNET_malloc (left + sizeof (struct MetaDataHeader)); hdr = (struct MetaDataHeader *) dst; hdr->version = htonl (2); @@ -922,7 +898,10 @@ GNUNET_CONTAINER_meta_data_serialize (const struct GNUNET_CONTAINER_MetaData } if (NULL != *target) { - memcpy (*target, dst, clen + sizeof (struct MetaDataHeader)); + if (GNUNET_YES == comp) + memcpy (*target, dst, clen + sizeof (struct MetaDataHeader)); + else + memcpy (*target, dst, left + sizeof (struct MetaDataHeader)); GNUNET_free (dst); } else @@ -943,11 +922,14 @@ GNUNET_CONTAINER_meta_data_serialize (const struct GNUNET_CONTAINER_MetaData * end and try again without it */ left -= sizeof (struct MetaDataEntry); left -= pos->data_size; - if (pos->plugin_name != NULL) + if (NULL != pos->plugin_name) left -= strlen (pos->plugin_name) + 1; - if (pos->mime_type != NULL) + if (NULL != pos->mime_type) left -= strlen (pos->mime_type) + 1; - pos = pos->next; + + GNUNET_free_non_null (cdata); + cdata = NULL; + i++; } GNUNET_free (ent); @@ -956,7 +938,7 @@ GNUNET_CONTAINER_meta_data_serialize (const struct GNUNET_CONTAINER_MetaData ihdr.version = htonl (2); ihdr.entries = htonl (0); ihdr.size = htonl (0); - if (*target == NULL) + if (NULL == *target) *target = GNUNET_malloc (sizeof (struct MetaDataHeader)); memcpy (*target, &ihdr, sizeof (struct MetaDataHeader)); return sizeof (struct MetaDataHeader); @@ -976,13 +958,13 @@ GNUNET_CONTAINER_meta_data_get_serialized_size (const struct ssize_t ret; char *ptr; - if (md->sbuf != NULL) + if (NULL != md->sbuf) return md->sbuf_size; ptr = NULL; ret = GNUNET_CONTAINER_meta_data_serialize (md, &ptr, GNUNET_MAX_MALLOC_CHECKED, GNUNET_CONTAINER_META_DATA_SERIALIZE_FULL); - if (ret != -1) + if (-1 != ret) GNUNET_free (ptr); return ret; } @@ -1008,14 +990,9 @@ decompress (const char *input, size_t inputSize, size_t outputSize) output = GNUNET_malloc (olen); if (Z_OK == uncompress ((Bytef *) output, &olen, (const Bytef *) input, inputSize)) - { return output; - } - else - { - GNUNET_free (output); - return NULL; - } + GNUNET_free (output); + return NULL; } @@ -1056,9 +1033,9 @@ GNUNET_CONTAINER_meta_data_deserialize (const char *input, size_t size) version = ntohl (hdr.version) & HEADER_VERSION_MASK; compressed = (ntohl (hdr.version) & HEADER_COMPRESSED) != 0; - if (version == 1) + if (1 == version) return NULL; /* null pointer */ - if (version != 2) + if (2 != version) { GNUNET_break_op (0); /* unsupported version */ return NULL; @@ -1084,7 +1061,7 @@ GNUNET_CONTAINER_meta_data_deserialize (const char *input, size_t size) data = decompress ((const char *) &input[sizeof (struct MetaDataHeader)], size - sizeof (struct MetaDataHeader), dataSize); - if (data == NULL) + if (NULL == data) { GNUNET_break_op (0); return NULL; @@ -1110,9 +1087,9 @@ GNUNET_CONTAINER_meta_data_deserialize (const char *input, size_t size) memcpy (&ent, &cdata[i * sizeof (struct MetaDataEntry)], sizeof (struct MetaDataEntry)); format = (enum EXTRACTOR_MetaFormat) ntohl (ent.format); - if ((format != EXTRACTOR_METAFORMAT_UTF8) && - (format != EXTRACTOR_METAFORMAT_C_STRING) && - (format != EXTRACTOR_METAFORMAT_BINARY)) + if ((EXTRACTOR_METAFORMAT_UTF8 != format) && + (EXTRACTOR_METAFORMAT_C_STRING != format) && + (EXTRACTOR_METAFORMAT_BINARY != format)) { GNUNET_break_op (0); break; @@ -1127,10 +1104,10 @@ GNUNET_CONTAINER_meta_data_deserialize (const char *input, size_t size) } left -= dlen; meta_data = &mdata[left]; - if ((format == EXTRACTOR_METAFORMAT_UTF8) || - (format == EXTRACTOR_METAFORMAT_C_STRING)) + if ((EXTRACTOR_METAFORMAT_UTF8 == format) || + (EXTRACTOR_METAFORMAT_C_STRING == format)) { - if ((dlen == 0) || (mdata[left + dlen - 1] != '\0')) + if ((0 == dlen) || ('\0' != mdata[left + dlen - 1])) { GNUNET_break_op (0); break; @@ -1142,12 +1119,12 @@ GNUNET_CONTAINER_meta_data_deserialize (const char *input, size_t size) break; } left -= plen; - if ((plen > 0) && (mdata[left + plen - 1] != '\0')) + if ((plen > 0) && ('\0' != mdata[left + plen - 1])) { GNUNET_break_op (0); break; } - if (plen == 0) + if (0 == plen) plugin_name = NULL; else plugin_name = &mdata[left]; @@ -1158,12 +1135,12 @@ GNUNET_CONTAINER_meta_data_deserialize (const char *input, size_t size) break; } left -= mlen; - if ((mlen > 0) && (mdata[left + mlen - 1] != '\0')) + if ((mlen > 0) && ('\0' != mdata[left + mlen - 1])) { GNUNET_break_op (0); break; } - if (mlen == 0) + if (0 == mlen) mime_type = NULL; else mime_type = &mdata[left]; diff --git a/src/util/container_multihashmap.c b/src/util/container_multihashmap.c index 7e53a64..a23f967 100644 --- a/src/util/container_multihashmap.c +++ b/src/util/container_multihashmap.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - (C) 2008 Christian Grothoff (and other contributing authors) + (C) 2008, 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published @@ -31,15 +31,34 @@ #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) /** - * An entry in the hash map. + * An entry in the hash map with the full key. */ -struct MapEntry +struct BigMapEntry { /** + * Value of the entry. + */ + void *value; + + /** + * If there is a hash collision, we create a linked list. + */ + struct BigMapEntry *next; + + /** * Key for the entry. */ - GNUNET_HashCode key; + struct GNUNET_HashCode key; + +}; + + +/** + * An entry in the hash map with just a pointer to the key. + */ +struct SmallMapEntry +{ /** * Value of the entry. @@ -49,10 +68,33 @@ struct MapEntry /** * If there is a hash collision, we create a linked list. */ - struct MapEntry *next; + struct SmallMapEntry *next; + + /** + * Key for the entry. + */ + const struct GNUNET_HashCode *key; }; + +/** + * Entry in the map. + */ +union MapEntry +{ + /** + * Variant used if map entries only contain a pointer to the key. + */ + struct SmallMapEntry *sme; + + /** + * Variant used if map entries contain the full key. + */ + struct BigMapEntry *bme; +}; + + /** * Internal representation of the hash map. */ @@ -62,7 +104,7 @@ struct GNUNET_CONTAINER_MultiHashMap /** * All of our buckets. */ - struct MapEntry **map; + union MapEntry *map; /** * Number of entries in the map. @@ -73,6 +115,12 @@ struct GNUNET_CONTAINER_MultiHashMap * Length of the "map" array. */ unsigned int map_length; + + /** + * GNUNET_NO if the map entries are of type 'struct BigMapEntry', + * GNUNET_YES if the map entries are of type 'struct SmallMapEntry'. + */ + int use_small_entries; }; @@ -80,18 +128,29 @@ struct GNUNET_CONTAINER_MultiHashMap * Create a multi hash map. * * @param len initial size (map will grow as needed) + * @param do_not_copy_keys GNUNET_NO is always safe and should be used by default; + * GNUNET_YES means that on 'put', the 'key' does not have + * to be copied as the destination of the pointer is + * guaranteed to be life as long as the value is stored in + * the hashmap. This can significantly reduce memory + * consumption, but of course is also a recipie for + * heap corruption if the assumption is not true. Only + * use this if (1) memory use is important in this case and + * (2) you have triple-checked that the invariant holds * @return NULL on error */ struct GNUNET_CONTAINER_MultiHashMap * -GNUNET_CONTAINER_multihashmap_create (unsigned int len) +GNUNET_CONTAINER_multihashmap_create (unsigned int len, + int do_not_copy_keys) { - struct GNUNET_CONTAINER_MultiHashMap *ret; + struct GNUNET_CONTAINER_MultiHashMap *map; GNUNET_assert (len > 0); - ret = GNUNET_malloc (sizeof (struct GNUNET_CONTAINER_MultiHashMap)); - ret->map = GNUNET_malloc (len * sizeof (struct MapEntry *)); - ret->map_length = len; - return ret; + map = GNUNET_malloc (sizeof (struct GNUNET_CONTAINER_MultiHashMap)); + map->map = GNUNET_malloc (len * sizeof (union MapEntry)); + map->map_length = len; + map->use_small_entries = do_not_copy_keys; + return map; } @@ -106,14 +165,36 @@ GNUNET_CONTAINER_multihashmap_destroy (struct GNUNET_CONTAINER_MultiHashMap *map) { unsigned int i; - struct MapEntry *e; + union MapEntry me; for (i = 0; i < map->map_length; i++) { - while (NULL != (e = map->map[i])) + me = map->map[i]; + if (map->use_small_entries) + { + struct SmallMapEntry *sme; + struct SmallMapEntry *nxt; + + nxt = me.sme; + while (NULL != (sme = nxt)) + { + nxt = sme->next; + GNUNET_free (sme); + } + me.sme = NULL; + } + else { - map->map[i] = e->next; - GNUNET_free (e); + struct BigMapEntry *bme; + struct BigMapEntry *nxt; + + nxt = me.bme; + while (NULL != (bme = nxt)) + { + nxt = bme->next; + GNUNET_free (bme); + } + me.bme = NULL; } } GNUNET_free (map->map); @@ -124,16 +205,16 @@ GNUNET_CONTAINER_multihashmap_destroy (struct GNUNET_CONTAINER_MultiHashMap /** * Compute the index of the bucket for the given key. * - * @param m hash map for which to compute the index + * @param map hash map for which to compute the index * @param key what key should the index be computed for - * @return offset into the "map" array of "m" + * @return offset into the "map" array of "map" */ static unsigned int -idx_of (const struct GNUNET_CONTAINER_MultiHashMap *m, - const GNUNET_HashCode * key) +idx_of (const struct GNUNET_CONTAINER_MultiHashMap *map, + const struct GNUNET_HashCode *key) { - GNUNET_assert (m != NULL); - return (*(unsigned int *) key) % m->map_length; + GNUNET_assert (map != NULL); + return (*(unsigned int *) key) % map->map_length; } @@ -163,16 +244,26 @@ GNUNET_CONTAINER_multihashmap_size (const struct GNUNET_CONTAINER_MultiHashMap */ void * GNUNET_CONTAINER_multihashmap_get (const struct GNUNET_CONTAINER_MultiHashMap - *map, const GNUNET_HashCode * key) + *map, const struct GNUNET_HashCode *key) { - struct MapEntry *e; + union MapEntry me; - e = map->map[idx_of (map, key)]; - while (e != NULL) + me = map->map[idx_of (map, key)]; + if (map->use_small_entries) { - if (0 == memcmp (key, &e->key, sizeof (GNUNET_HashCode))) - return e->value; - e = e->next; + struct SmallMapEntry *sme; + + for (sme = me.sme; NULL != sme; sme = sme->next) + if (0 == memcmp (key, sme->key, sizeof (struct GNUNET_HashCode))) + return sme->value; + } + else + { + struct BigMapEntry *bme; + + for (bme = me.bme; NULL != bme; bme = bme->next) + if (0 == memcmp (key, &bme->key, sizeof (struct GNUNET_HashCode))) + return bme->value; } return NULL; } @@ -195,25 +286,48 @@ GNUNET_CONTAINER_multihashmap_iterate (const struct { int count; unsigned int i; - struct MapEntry *e; - struct MapEntry *n; - GNUNET_HashCode kc; + union MapEntry me; + struct GNUNET_HashCode kc; count = 0; - GNUNET_assert (map != NULL); + GNUNET_assert (NULL != map); for (i = 0; i < map->map_length; i++) { - n = map->map[i]; - while (NULL != (e = n)) + me = map->map[i]; + if (map->use_small_entries) { - n = e->next; - if (NULL != it) + struct SmallMapEntry *sme; + struct SmallMapEntry *nxt; + + nxt = me.sme; + while (NULL != (sme = nxt)) { - kc = e->key; - if (GNUNET_OK != it (it_cls, &kc, e->value)) - return GNUNET_SYSERR; + nxt = sme->next; + if (NULL != it) + { + if (GNUNET_OK != it (it_cls, sme->key, sme->value)) + return GNUNET_SYSERR; + } + count++; + } + } + else + { + struct BigMapEntry *bme; + struct BigMapEntry *nxt; + + nxt = me.bme; + while (NULL != (bme = nxt)) + { + nxt = bme->next; + if (NULL != it) + { + kc = bme->key; + if (GNUNET_OK != it (it_cls, &kc, bme->value)) + return GNUNET_SYSERR; + } + count++; } - count++; } } return count; @@ -233,30 +347,57 @@ GNUNET_CONTAINER_multihashmap_iterate (const struct */ int GNUNET_CONTAINER_multihashmap_remove (struct GNUNET_CONTAINER_MultiHashMap *map, - const GNUNET_HashCode * key, void *value) + const struct GNUNET_HashCode *key, + void *value) { - struct MapEntry *e; - struct MapEntry *p; + union MapEntry me; unsigned int i; i = idx_of (map, key); - p = NULL; - e = map->map[i]; - while (e != NULL) + me = map->map[i]; + if (map->use_small_entries) + { + struct SmallMapEntry *sme; + struct SmallMapEntry *p; + + p = NULL; + for (sme = me.sme; NULL != sme; sme = sme->next) + { + if ((0 == memcmp (key, sme->key, sizeof (struct GNUNET_HashCode))) && + (value == sme->value)) + { + if (NULL == p) + map->map[i].sme = sme->next; + else + p->next = sme->next; + GNUNET_free (sme); + map->size--; + return GNUNET_YES; + } + p = sme; + } + } + else { - if ((0 == memcmp (key, &e->key, sizeof (GNUNET_HashCode))) && - (value == e->value)) + struct BigMapEntry *bme; + struct BigMapEntry *p; + + p = NULL; + for (bme = me.bme; NULL != bme; bme = bme->next) { - if (p == NULL) - map->map[i] = e->next; - else - p->next = e->next; - GNUNET_free (e); - map->size--; - return GNUNET_YES; + if ((0 == memcmp (key, &bme->key, sizeof (struct GNUNET_HashCode))) && + (value == bme->value)) + { + if (NULL == p) + map->map[i].bme = bme->next; + else + p->next = bme->next; + GNUNET_free (bme); + map->size--; + return GNUNET_YES; + } + p = bme; } - p = e; - e = e->next; } return GNUNET_NO; } @@ -272,37 +413,73 @@ GNUNET_CONTAINER_multihashmap_remove (struct GNUNET_CONTAINER_MultiHashMap *map, */ int GNUNET_CONTAINER_multihashmap_remove_all (struct GNUNET_CONTAINER_MultiHashMap - *map, const GNUNET_HashCode * key) + *map, const struct GNUNET_HashCode *key) { - struct MapEntry *e; - struct MapEntry *p; + union MapEntry me; unsigned int i; int ret; ret = 0; i = idx_of (map, key); - p = NULL; - e = map->map[i]; - while (e != NULL) - { - if (0 == memcmp (key, &e->key, sizeof (GNUNET_HashCode))) + me = map->map[i]; + if (map->use_small_entries) + { + struct SmallMapEntry *sme; + struct SmallMapEntry *p; + + p = NULL; + sme = me.sme; + while (NULL != sme) { - if (p == NULL) - map->map[i] = e->next; - else - p->next = e->next; - GNUNET_free (e); - map->size--; - if (p == NULL) - e = map->map[i]; + if (0 == memcmp (key, sme->key, sizeof (struct GNUNET_HashCode))) + { + if (NULL == p) + map->map[i].sme = sme->next; + else + p->next = sme->next; + GNUNET_free (sme); + map->size--; + if (NULL == p) + sme = map->map[i].sme; + else + sme = p->next; + ret++; + } else - e = p->next; - ret++; + { + p = sme; + sme = sme->next; + } } - else + } + else + { + struct BigMapEntry *bme; + struct BigMapEntry *p; + + p = NULL; + bme = me.bme; + while (NULL != bme) { - p = e; - e = e->next; + if (0 == memcmp (key, &bme->key, sizeof (struct GNUNET_HashCode))) + { + if (NULL == p) + map->map[i].bme = bme->next; + else + p->next = bme->next; + GNUNET_free (bme); + map->size--; + if (NULL == p) + bme = map->map[i].bme; + else + bme = p->next; + ret++; + } + else + { + p = bme; + bme = bme->next; + } } } return ret; @@ -321,16 +498,26 @@ GNUNET_CONTAINER_multihashmap_remove_all (struct GNUNET_CONTAINER_MultiHashMap int GNUNET_CONTAINER_multihashmap_contains (const struct GNUNET_CONTAINER_MultiHashMap *map, - const GNUNET_HashCode * key) + const struct GNUNET_HashCode *key) { - struct MapEntry *e; + union MapEntry me; - e = map->map[idx_of (map, key)]; - while (e != NULL) + me = map->map[idx_of (map, key)]; + if (map->use_small_entries) { - if (0 == memcmp (key, &e->key, sizeof (GNUNET_HashCode))) - return GNUNET_YES; - e = e->next; + struct SmallMapEntry *sme; + + for (sme = me.sme; NULL != sme; sme = sme->next) + if (0 == memcmp (key, sme->key, sizeof (struct GNUNET_HashCode))) + return GNUNET_YES; + } + else + { + struct BigMapEntry *bme; + + for (bme = me.bme; NULL != bme; bme = bme->next) + if (0 == memcmp (key, &bme->key, sizeof (struct GNUNET_HashCode))) + return GNUNET_YES; } return GNUNET_NO; } @@ -349,18 +536,29 @@ GNUNET_CONTAINER_multihashmap_contains (const struct int GNUNET_CONTAINER_multihashmap_contains_value (const struct GNUNET_CONTAINER_MultiHashMap - *map, const GNUNET_HashCode * key, + *map, const struct GNUNET_HashCode *key, const void *value) { - struct MapEntry *e; + union MapEntry me; - e = map->map[idx_of (map, key)]; - while (e != NULL) + me = map->map[idx_of (map, key)]; + if (map->use_small_entries) { - if ((0 == memcmp (key, &e->key, sizeof (GNUNET_HashCode))) && - (e->value == value)) - return GNUNET_YES; - e = e->next; + struct SmallMapEntry *sme; + + for (sme = me.sme; NULL != sme; sme = sme->next) + if ( (0 == memcmp (key, sme->key, sizeof (struct GNUNET_HashCode))) && + (sme->value == value) ) + return GNUNET_YES; + } + else + { + struct BigMapEntry *bme; + + for (bme = me.bme; NULL != bme; bme = bme->next) + if ( (0 == memcmp (key, &bme->key, sizeof (struct GNUNET_HashCode))) && + (bme->value == value) ) + return GNUNET_YES; } return GNUNET_NO; } @@ -374,9 +572,8 @@ GNUNET_CONTAINER_multihashmap_contains_value (const struct static void grow (struct GNUNET_CONTAINER_MultiHashMap *map) { - struct MapEntry **old_map; - struct MapEntry **new_map; - struct MapEntry *e; + union MapEntry *old_map; + union MapEntry *new_map; unsigned int old_len; unsigned int new_len; unsigned int idx; @@ -385,17 +582,34 @@ grow (struct GNUNET_CONTAINER_MultiHashMap *map) old_map = map->map; old_len = map->map_length; new_len = old_len * 2; - new_map = GNUNET_malloc (sizeof (struct MapEntry *) * new_len); + new_map = GNUNET_malloc (sizeof (union MapEntry) * new_len); map->map_length = new_len; map->map = new_map; for (i = 0; i < old_len; i++) { - while (NULL != (e = old_map[i])) + if (map->use_small_entries) + { + struct SmallMapEntry *sme; + + while (NULL != (sme = old_map[i].sme)) + { + old_map[i].sme = sme->next; + idx = idx_of (map, sme->key); + sme->next = new_map[idx].sme; + new_map[idx].sme = sme; + } + } + else { - old_map[i] = e->next; - idx = idx_of (map, &e->key); - e->next = new_map[idx]; - new_map[idx] = e; + struct BigMapEntry *bme; + + while (NULL != (bme = old_map[i].bme)) + { + old_map[i].bme = bme->next; + idx = idx_of (map, &bme->key); + bme->next = new_map[idx].bme; + new_map[idx].bme = bme; + } } } GNUNET_free (old_map); @@ -416,27 +630,43 @@ grow (struct GNUNET_CONTAINER_MultiHashMap *map) */ int GNUNET_CONTAINER_multihashmap_put (struct GNUNET_CONTAINER_MultiHashMap *map, - const GNUNET_HashCode * key, void *value, + const struct GNUNET_HashCode *key, + void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt) { - struct MapEntry *e; + union MapEntry me; unsigned int i; i = idx_of (map, key); if ((opt != GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE) && (opt != GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) { - e = map->map[i]; - while (e != NULL) + me = map->map[i]; + if (map->use_small_entries) { - if (0 == memcmp (key, &e->key, sizeof (GNUNET_HashCode))) - { - if (opt == GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY) - return GNUNET_SYSERR; - e->value = value; - return GNUNET_NO; - } - e = e->next; + struct SmallMapEntry *sme; + + for (sme = me.sme; NULL != sme; sme = sme->next) + if (0 == memcmp (key, sme->key, sizeof (struct GNUNET_HashCode))) + { + if (opt == GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY) + return GNUNET_SYSERR; + sme->value = value; + return GNUNET_NO; + } + } + else + { + struct BigMapEntry *bme; + + for (bme = me.bme; NULL != bme; bme = bme->next) + if (0 == memcmp (key, &bme->key, sizeof (struct GNUNET_HashCode))) + { + if (opt == GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY) + return GNUNET_SYSERR; + bme->value = value; + return GNUNET_NO; + } } } if (map->size / 3 >= map->map_length / 4) @@ -444,11 +674,26 @@ GNUNET_CONTAINER_multihashmap_put (struct GNUNET_CONTAINER_MultiHashMap *map, grow (map); i = idx_of (map, key); } - e = GNUNET_malloc (sizeof (struct MapEntry)); - e->key = *key; - e->value = value; - e->next = map->map[i]; - map->map[i] = e; + if (map->use_small_entries) + { + struct SmallMapEntry *sme; + + sme = GNUNET_malloc (sizeof (struct SmallMapEntry)); + sme->key = key; + sme->value = value; + sme->next = map->map[i].sme; + map->map[i].sme = sme; + } + else + { + struct BigMapEntry *bme; + + bme = GNUNET_malloc (sizeof (struct BigMapEntry)); + bme->key = *key; + bme->value = value; + bme->next = map->map[i].bme; + map->map[i].bme = bme; + } map->size++; return GNUNET_OK; } @@ -467,24 +712,46 @@ GNUNET_CONTAINER_multihashmap_put (struct GNUNET_CONTAINER_MultiHashMap *map, int GNUNET_CONTAINER_multihashmap_get_multiple (const struct GNUNET_CONTAINER_MultiHashMap *map, - const GNUNET_HashCode * key, + const struct GNUNET_HashCode *key, GNUNET_CONTAINER_HashMapIterator it, void *it_cls) { int count; - struct MapEntry *e; - struct MapEntry *n; + union MapEntry me; count = 0; - n = map->map[idx_of (map, key)]; - while (NULL != (e = n)) + me = map->map[idx_of (map, key)]; + if (map->use_small_entries) + { + struct SmallMapEntry *sme; + struct SmallMapEntry *nxt; + + nxt = me.sme; + while (NULL != (sme = nxt)) + { + nxt = sme->next; + if (0 != memcmp (key, sme->key, sizeof (struct GNUNET_HashCode))) + continue; + if ((it != NULL) && (GNUNET_OK != it (it_cls, key, sme->value))) + return GNUNET_SYSERR; + count++; + } + } + else { - n = e->next; - if (0 != memcmp (key, &e->key, sizeof (GNUNET_HashCode))) - continue; - if ((it != NULL) && (GNUNET_OK != it (it_cls, key, e->value))) - return GNUNET_SYSERR; - count++; + struct BigMapEntry *bme; + struct BigMapEntry *nxt; + + nxt = me.bme; + while (NULL != (bme = nxt)) + { + nxt = bme->next; + if (0 != memcmp (key, &bme->key, sizeof (struct GNUNET_HashCode))) + continue; + if ((it != NULL) && (GNUNET_OK != it (it_cls, key, bme->value))) + return GNUNET_SYSERR; + count++; + } } return count; } diff --git a/src/util/crypto_crc.c b/src/util/crypto_crc.c index 8bccf6b..ea50b63 100644 --- a/src/util/crypto_crc.c +++ b/src/util/crypto_crc.c @@ -27,7 +27,6 @@ * @brief implementation of CRC16 and CRC32 * @author Christian Grothoff */ - #include "platform.h" #include "gnunet_common.h" #include "gnunet_crypto_lib.h" @@ -51,7 +50,7 @@ static uLong crc_table[256]; /* * This routine writes each crc_table entry exactly once, - * with the ccorrect final value. Thus, it is safe to call + * with the correct final value. Thus, it is safe to call * even on a table that someone else is using concurrently. */ static void diff --git a/src/util/crypto_ecc.c b/src/util/crypto_ecc.c new file mode 100644 index 0000000..7f88c3e --- /dev/null +++ b/src/util/crypto_ecc.c @@ -0,0 +1,1082 @@ +/* + This file is part of GNUnet. + (C) 2001, 2002, 2003, 2004, 2005, 2006, 2009, 2012 Christian Grothoff (and other contributing authors) + + GNUnet 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. + + GNUnet 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 GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/** + * @file util/crypto_ecc.c + * @brief public key cryptography (ECC) with libgcrypt + * @author Christian Grothoff + */ +#include "platform.h" +#include <gcrypt.h> +#include "gnunet_common.h" +#include "gnunet_util_lib.h" + +#define EXTRA_CHECKS ALLOW_EXTRA_CHECKS || 1 + +#define CURVE "NIST P-521" + +#define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) + +#define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall) + +#define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename) + +/** + * Log an error message at log-level 'level' that indicates + * a failure of the command 'cmd' with the message given + * by gcry_strerror(rc). + */ +#define LOG_GCRY(level, cmd, rc) do { LOG(level, _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, gcry_strerror(rc)); } while(0); + + +/** + * The private information of an ECC private key. + */ +struct GNUNET_CRYPTO_EccPrivateKey +{ + + /** + * Libgcrypt S-expression for the ECC key. + */ + gcry_sexp_t sexp; +}; + + +/** + * Free memory occupied by ECC key + * + * @param privatekey pointer to the memory to free + */ +void +GNUNET_CRYPTO_ecc_key_free (struct GNUNET_CRYPTO_EccPrivateKey *privatekey) +{ + gcry_sexp_release (privatekey->sexp); + GNUNET_free (privatekey); +} + + +/** + * Extract values from an S-expression. + * + * @param array where to store the result(s) + * @param sexp S-expression to parse + * @param topname top-level name in the S-expression that is of interest + * @param elems names of the elements to extract + * @return 0 on success + */ +static int +key_from_sexp (gcry_mpi_t * array, gcry_sexp_t sexp, const char *topname, + const char *elems) +{ + gcry_sexp_t list; + gcry_sexp_t l2; + const char *s; + unsigned int i; + unsigned int idx; + + list = gcry_sexp_find_token (sexp, topname, 0); + if (! list) + return 1; + l2 = gcry_sexp_cadr (list); + gcry_sexp_release (list); + list = l2; + if (! list) + return 2; + + idx = 0; + for (s = elems; *s; s++, idx++) + { + l2 = gcry_sexp_find_token (list, s, 1); + if (! l2) + { + for (i = 0; i < idx; i++) + { + gcry_free (array[i]); + array[i] = NULL; + } + gcry_sexp_release (list); + return 3; /* required parameter not found */ + } + array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG); + gcry_sexp_release (l2); + if (! array[idx]) + { + for (i = 0; i < idx; i++) + { + gcry_free (array[i]); + array[i] = NULL; + } + gcry_sexp_release (list); + return 4; /* required parameter is invalid */ + } + } + gcry_sexp_release (list); + return 0; +} + + +/** + * Extract the public key for the given private key. + * + * @param priv the private key + * @param pub where to write the public key + */ +void +GNUNET_CRYPTO_ecc_key_get_public (const struct GNUNET_CRYPTO_EccPrivateKey *priv, + struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded *pub) +{ + gcry_mpi_t skey; + size_t size; + int rc; + + memset (pub, 0, sizeof (struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded)); + rc = key_from_sexp (&skey, priv->sexp, "public-key", "q"); + if (rc) + rc = key_from_sexp (&skey, priv->sexp, "private-key", "q"); + if (rc) + rc = key_from_sexp (&skey, priv->sexp, "ecc", "q"); + GNUNET_assert (0 == rc); + pub->size = htons (sizeof (struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded)); + size = GNUNET_CRYPTO_ECC_MAX_PUBLIC_KEY_LENGTH; + GNUNET_assert (0 == + gcry_mpi_print (GCRYMPI_FMT_USG, pub->key, size, &size, + skey)); + pub->len = htons (size); + gcry_mpi_release (skey); +} + + +/** + * Convert a public key to a string. + * + * @param pub key to convert + * @return string representing 'pub' + */ +char * +GNUNET_CRYPTO_ecc_public_key_to_string (struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded *pub) +{ + char *pubkeybuf; + size_t keylen = (sizeof (struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded)) * 8; + char *end; + + if (keylen % 5 > 0) + keylen += 5 - keylen % 5; + keylen /= 5; + pubkeybuf = GNUNET_malloc (keylen + 1); + end = GNUNET_STRINGS_data_to_string ((unsigned char *) pub, + sizeof (struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded), + pubkeybuf, + keylen); + if (NULL == end) + { + GNUNET_free (pubkeybuf); + return NULL; + } + *end = '\0'; + return pubkeybuf; +} + + +/** + * Convert a string representing a public key to a public key. + * + * @param enc encoded public key + * @param enclen number of bytes in enc (without 0-terminator) + * @param pub where to store the public key + * @return GNUNET_OK on success + */ +int +GNUNET_CRYPTO_ecc_public_key_from_string (const char *enc, + size_t enclen, + struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded *pub) +{ + size_t keylen = (sizeof (struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded)) * 8; + + if (keylen % 5 > 0) + keylen += 5 - keylen % 5; + keylen /= 5; + if (enclen != keylen) + return GNUNET_SYSERR; + + if (GNUNET_OK != GNUNET_STRINGS_string_to_data (enc, enclen, + (unsigned char*) pub, + sizeof (struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded))) + return GNUNET_SYSERR; + if ( (ntohs (pub->size) != sizeof (struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded)) || + (ntohs (pub->len) > GNUNET_CRYPTO_ECC_SIGNATURE_DATA_ENCODING_LENGTH) ) + return GNUNET_SYSERR; + return GNUNET_OK; +} + + +/** + * Convert the given public key from the network format to the + * S-expression that can be used by libgcrypt. + * + * @param publicKey public key to decode + * @return NULL on error + */ +static gcry_sexp_t +decode_public_key (const struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded *publicKey) +{ + gcry_sexp_t result; + gcry_mpi_t q; + size_t size; + size_t erroff; + int rc; + + if (ntohs (publicKey->len) > GNUNET_CRYPTO_ECC_SIGNATURE_DATA_ENCODING_LENGTH) + { + GNUNET_break (0); + return NULL; + } + size = ntohs (publicKey->len); + if (0 != (rc = gcry_mpi_scan (&q, GCRYMPI_FMT_USG, publicKey->key, size, &size))) + { + LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); + return NULL; + } + + rc = gcry_sexp_build (&result, &erroff, + "(public-key(ecdsa(curve \"" CURVE "\")(q %m)))", + q); + gcry_mpi_release (q); + if (0 != rc) + { + LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc); /* erroff gives more info */ + return NULL; + } + // FIXME: is this key expected to pass pk_testkey? +#if 0 +#if EXTRA_CHECKS + if (0 != (rc = gcry_pk_testkey (result))) + { + LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc); + gcry_sexp_release (result); + return NULL; + } +#endif +#endif + return result; +} + + +/** + * Encode the private key in a format suitable for + * storing it into a file. + * + * @param key key to encode + * @return encoding of the private key. + * The first 4 bytes give the size of the array, as usual. + */ +struct GNUNET_CRYPTO_EccPrivateKeyBinaryEncoded * +GNUNET_CRYPTO_ecc_encode_key (const struct GNUNET_CRYPTO_EccPrivateKey *key) +{ + struct GNUNET_CRYPTO_EccPrivateKeyBinaryEncoded *retval; + char buf[65536]; + uint16_t be; + size_t size; + +#if EXTRA_CHECKS + if (0 != gcry_pk_testkey (key->sexp)) + { + GNUNET_break (0); + return NULL; + } +#endif + size = gcry_sexp_sprint (key->sexp, + GCRYSEXP_FMT_DEFAULT, + &buf[2], sizeof (buf) - sizeof (uint16_t)); + if (0 == size) + { + GNUNET_break (0); + return NULL; + } + GNUNET_assert (size < 65536 - sizeof (uint16_t)); + be = htons ((uint16_t) size + (sizeof (be))); + memcpy (buf, &be, sizeof (be)); + size += sizeof (be); + retval = GNUNET_malloc (size); + memcpy (retval, buf, size); + return retval; +} + + +/** + * Decode the private key from the file-format back + * to the "normal", internal format. + * + * @param buf the buffer where the private key data is stored + * @param len the length of the data in 'buffer' + * @return NULL on error + */ +struct GNUNET_CRYPTO_EccPrivateKey * +GNUNET_CRYPTO_ecc_decode_key (const char *buf, + size_t len) +{ + struct GNUNET_CRYPTO_EccPrivateKey *ret; + uint16_t be; + gcry_sexp_t sexp; + int rc; + size_t erroff; + + if (len < sizeof (uint16_t)) + return NULL; + memcpy (&be, buf, sizeof (be)); + if (len != ntohs (be)) + return NULL; + if (0 != (rc = gcry_sexp_sscan (&sexp, + &erroff, + &buf[2], + len - sizeof (uint16_t)))) + { + LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_scan", rc); + return NULL; + } + if (0 != (rc = gcry_pk_testkey (sexp))) + { + LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc); + return NULL; + } + ret = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccPrivateKey)); + ret->sexp = sexp; + return ret; +} + + +/** + * Create a new private key. Caller must free return value. + * + * @return fresh private key + */ +struct GNUNET_CRYPTO_EccPrivateKey * +GNUNET_CRYPTO_ecc_key_create () +{ + struct GNUNET_CRYPTO_EccPrivateKey *ret; + gcry_sexp_t s_key; + gcry_sexp_t s_keyparam; + int rc; + + if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL, + "(genkey(ecdsa(curve \"" CURVE "\")))"))) + { + LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc); + return NULL; + } + if (0 != (rc = gcry_pk_genkey (&s_key, s_keyparam))) + { + LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc); + gcry_sexp_release (s_keyparam); + return NULL; + } + gcry_sexp_release (s_keyparam); +#if EXTRA_CHECKS + if (0 != (rc = gcry_pk_testkey (s_key))) + { + LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc); + gcry_sexp_release (s_key); + return NULL; + } +#endif + ret = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccPrivateKey)); + ret->sexp = s_key; + return ret; +} + + +/** + * Try to read the private key from the given file. + * + * @param filename file to read the key from + * @return NULL on error + */ +static struct GNUNET_CRYPTO_EccPrivateKey * +try_read_key (const char *filename) +{ + struct GNUNET_CRYPTO_EccPrivateKey *ret; + struct GNUNET_DISK_FileHandle *fd; + OFF_T fs; + + if (GNUNET_YES != GNUNET_DISK_file_test (filename)) + return NULL; + + /* key file exists already, read it! */ + if (NULL == (fd = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ, + GNUNET_DISK_PERM_NONE))) + { + LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "open", filename); + return NULL; + } + if (GNUNET_OK != (GNUNET_DISK_file_handle_size (fd, &fs))) + { + LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "stat", filename); + (void) GNUNET_DISK_file_close (fd); + return NULL; + } + if (0 == fs) + { + GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fd)); + return NULL; + } + if (fs > UINT16_MAX) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + _("File `%s' does not contain a valid private key (too long, %llu bytes). Deleting it.\n"), + filename, + (unsigned long long) fs); + GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fd)); + if (0 != UNLINK (filename)) + LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "unlink", filename); + return NULL; + } + { + char enc[fs]; + + GNUNET_break (fs == GNUNET_DISK_file_read (fd, enc, fs)); + if (NULL == (ret = GNUNET_CRYPTO_ecc_decode_key ((char *) enc, fs))) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + _("File `%s' does not contain a valid private key (failed decode, %llu bytes). Deleting it.\n"), + filename, + (unsigned long long) fs); + GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fd)); + if (0 != UNLINK (filename)) + LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "unlink", filename); + return NULL; + } + } + GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fd)); + return ret; +} + + +/** + * Wait for a short time (we're trying to lock a file or want + * to give another process a shot at finishing a disk write, etc.). + * Sleeps for 100ms (as that should be long enough for virtually all + * modern systems to context switch and allow another process to do + * some 'real' work). + */ +static void +short_wait () +{ + struct GNUNET_TIME_Relative timeout; + + timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 100); + (void) GNUNET_NETWORK_socket_select (NULL, NULL, NULL, timeout); +} + + +/** + * Create a new private key by reading it from a file. If the + * files does not exist, create a new key and write it to the + * file. Caller must free return value. Note that this function + * can not guarantee that another process might not be trying + * the same operation on the same file at the same time. + * If the contents of the file + * are invalid the old file is deleted and a fresh key is + * created. + * + * @return new private key, NULL on error (for example, + * permission denied) + */ +struct GNUNET_CRYPTO_EccPrivateKey * +GNUNET_CRYPTO_ecc_key_create_from_file (const char *filename) +{ + struct GNUNET_CRYPTO_EccPrivateKey *ret; + struct GNUNET_CRYPTO_EccPrivateKeyBinaryEncoded *enc; + uint16_t len; + struct GNUNET_DISK_FileHandle *fd; + unsigned int cnt; + int ec; + uint64_t fs; + struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded pub; + struct GNUNET_PeerIdentity pid; + + if (GNUNET_SYSERR == GNUNET_DISK_directory_create_for_file (filename)) + return NULL; + while (GNUNET_YES != GNUNET_DISK_file_test (filename)) + { + fd = GNUNET_DISK_file_open (filename, + GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE + | GNUNET_DISK_OPEN_FAILIFEXISTS, + GNUNET_DISK_PERM_USER_READ | + GNUNET_DISK_PERM_USER_WRITE); + if (NULL == fd) + { + if (errno == EEXIST) + { + if (GNUNET_YES != GNUNET_DISK_file_test (filename)) + { + /* must exist but not be accessible, fail for good! */ + if (0 != ACCESS (filename, R_OK)) + LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "access", filename); + else + GNUNET_break (0); /* what is going on!? */ + return NULL; + } + continue; + } + LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "open", filename); + return NULL; + } + cnt = 0; + + while (GNUNET_YES != + GNUNET_DISK_file_lock (fd, 0, + sizeof (struct GNUNET_CRYPTO_EccPrivateKeyBinaryEncoded), + GNUNET_YES)) + { + short_wait (); + if (0 == ++cnt % 10) + { + ec = errno; + LOG (GNUNET_ERROR_TYPE_ERROR, + _("Could not acquire lock on file `%s': %s...\n"), filename, + STRERROR (ec)); + } + } + LOG (GNUNET_ERROR_TYPE_INFO, + _("Creating a new private key. This may take a while.\n")); + ret = GNUNET_CRYPTO_ecc_key_create (); + GNUNET_assert (ret != NULL); + enc = GNUNET_CRYPTO_ecc_encode_key (ret); + GNUNET_assert (enc != NULL); + GNUNET_assert (ntohs (enc->size) == + GNUNET_DISK_file_write (fd, enc, ntohs (enc->size))); + GNUNET_free (enc); + + GNUNET_DISK_file_sync (fd); + if (GNUNET_YES != + GNUNET_DISK_file_unlock (fd, 0, + sizeof (struct GNUNET_CRYPTO_EccPrivateKeyBinaryEncoded))) + LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename); + GNUNET_assert (GNUNET_YES == GNUNET_DISK_file_close (fd)); + GNUNET_CRYPTO_ecc_key_get_public (ret, &pub); + GNUNET_CRYPTO_hash (&pub, sizeof (pub), &pid.hashPubKey); + return ret; + } + /* key file exists already, read it! */ + fd = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ, + GNUNET_DISK_PERM_NONE); + if (NULL == fd) + { + LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "open", filename); + return NULL; + } + cnt = 0; + while (1) + { + if (GNUNET_YES != + GNUNET_DISK_file_lock (fd, 0, + sizeof (struct GNUNET_CRYPTO_EccPrivateKeyBinaryEncoded), + GNUNET_NO)) + { + if (0 == ++cnt % 60) + { + ec = errno; + LOG (GNUNET_ERROR_TYPE_ERROR, + _("Could not acquire lock on file `%s': %s...\n"), filename, + STRERROR (ec)); + LOG (GNUNET_ERROR_TYPE_ERROR, + _ + ("This may be ok if someone is currently generating a private key.\n")); + } + short_wait (); + continue; + } + if (GNUNET_YES != GNUNET_DISK_file_test (filename)) + { + /* eh, what!? File we opened is now gone!? */ + LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "stat", filename); + if (GNUNET_YES != + GNUNET_DISK_file_unlock (fd, 0, + sizeof (struct GNUNET_CRYPTO_EccPrivateKeyBinaryEncoded))) + LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename); + GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fd)); + + return NULL; + } + if (GNUNET_OK != GNUNET_DISK_file_size (filename, &fs, GNUNET_YES, GNUNET_YES)) + fs = 0; + if (fs < sizeof (struct GNUNET_CRYPTO_EccPrivateKeyBinaryEncoded)) + { + /* maybe we got the read lock before the key generating + * process had a chance to get the write lock; give it up! */ + if (GNUNET_YES != + GNUNET_DISK_file_unlock (fd, 0, + sizeof (struct GNUNET_CRYPTO_EccPrivateKeyBinaryEncoded))) + LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename); + if (0 == ++cnt % 10) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + _ + ("When trying to read key file `%s' I found %u bytes but I need at least %u.\n"), + filename, (unsigned int) fs, + (unsigned int) sizeof (struct GNUNET_CRYPTO_EccPrivateKeyBinaryEncoded)); + LOG (GNUNET_ERROR_TYPE_ERROR, + _ + ("This may be ok if someone is currently generating a key.\n")); + } + short_wait (); /* wait a bit longer! */ + continue; + } + break; + } + enc = GNUNET_malloc (fs); + GNUNET_assert (fs == GNUNET_DISK_file_read (fd, enc, fs)); + len = ntohs (enc->size); + ret = NULL; + if ((len != fs) || + (NULL == (ret = GNUNET_CRYPTO_ecc_decode_key ((char *) enc, len)))) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + _("File `%s' does not contain a valid private key. Deleting it.\n"), + filename); + if (0 != UNLINK (filename)) + { + LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "unlink", filename); + } + } + GNUNET_free (enc); + if (GNUNET_YES != + GNUNET_DISK_file_unlock (fd, 0, + sizeof (struct GNUNET_CRYPTO_EccPrivateKeyBinaryEncoded))) + LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename); + GNUNET_assert (GNUNET_YES == GNUNET_DISK_file_close (fd)); + if (ret != NULL) + { + GNUNET_CRYPTO_ecc_key_get_public (ret, &pub); + GNUNET_CRYPTO_hash (&pub, sizeof (pub), &pid.hashPubKey); + } + return ret; +} + + +/** + * Handle to cancel private key generation and state for the + * key generation operation. + */ +struct GNUNET_CRYPTO_EccKeyGenerationContext +{ + + /** + * Continuation to call upon completion. + */ + GNUNET_CRYPTO_EccKeyCallback cont; + + /** + * Closure for 'cont'. + */ + void *cont_cls; + + /** + * Name of the file. + */ + char *filename; + + /** + * Handle to the helper process which does the key generation. + */ + struct GNUNET_OS_Process *gnunet_ecc; + + /** + * Handle to 'stdout' of gnunet-ecc. We 'read' on stdout to detect + * process termination (instead of messing with SIGCHLD). + */ + struct GNUNET_DISK_PipeHandle *gnunet_ecc_out; + + /** + * Location where we store the private key if it already existed. + * (if this is used, 'filename', 'gnunet_ecc' and 'gnunet_ecc_out' will + * not be used). + */ + struct GNUNET_CRYPTO_EccPrivateKey *pk; + + /** + * Task reading from 'gnunet_ecc_out' to wait for process termination. + */ + GNUNET_SCHEDULER_TaskIdentifier read_task; + +}; + + +/** + * Abort ECC key generation. + * + * @param gc key generation context to abort + */ +void +GNUNET_CRYPTO_ecc_key_create_stop (struct GNUNET_CRYPTO_EccKeyGenerationContext *gc) +{ + if (GNUNET_SCHEDULER_NO_TASK != gc->read_task) + { + GNUNET_SCHEDULER_cancel (gc->read_task); + gc->read_task = GNUNET_SCHEDULER_NO_TASK; + } + if (NULL != gc->gnunet_ecc) + { + (void) GNUNET_OS_process_kill (gc->gnunet_ecc, SIGKILL); + GNUNET_break (GNUNET_OK == + GNUNET_OS_process_wait (gc->gnunet_ecc)); + GNUNET_OS_process_destroy (gc->gnunet_ecc); + GNUNET_DISK_pipe_close (gc->gnunet_ecc_out); + } + + if (NULL != gc->filename) + { + if (0 != UNLINK (gc->filename)) + GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", gc->filename); + GNUNET_free (gc->filename); + } + if (NULL != gc->pk) + GNUNET_CRYPTO_ecc_key_free (gc->pk); + GNUNET_free (gc); +} + + +/** + * Task called upon shutdown or process termination of 'gnunet-ecc' during + * ECC key generation. Check where we are and perform the appropriate + * action. + * + * @param cls the 'struct GNUNET_CRYPTO_EccKeyGenerationContext' + * @param tc scheduler context + */ +static void +check_key_generation_completion (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + struct GNUNET_CRYPTO_EccKeyGenerationContext *gc = cls; + struct GNUNET_CRYPTO_EccPrivateKey *pk; + + gc->read_task = GNUNET_SCHEDULER_NO_TASK; + if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) + { + gc->cont (gc->cont_cls, NULL, _("interrupted by shutdown")); + GNUNET_CRYPTO_ecc_key_create_stop (gc); + return; + } + GNUNET_assert (GNUNET_OK == + GNUNET_OS_process_wait (gc->gnunet_ecc)); + GNUNET_OS_process_destroy (gc->gnunet_ecc); + gc->gnunet_ecc = NULL; + if (NULL == (pk = try_read_key (gc->filename))) + { + GNUNET_break (0); + gc->cont (gc->cont_cls, NULL, _("gnunet-ecc failed")); + GNUNET_CRYPTO_ecc_key_create_stop (gc); + return; + } + gc->cont (gc->cont_cls, pk, NULL); + GNUNET_DISK_pipe_close (gc->gnunet_ecc_out); + GNUNET_free (gc->filename); + GNUNET_free (gc); +} + + +/** + * Return the private ECC key which already existed on disk + * (asynchronously) to the caller. + * + * @param cls the 'struct GNUNET_CRYPTO_EccKeyGenerationContext' + * @param tc scheduler context (unused) + */ +static void +async_return_key (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + struct GNUNET_CRYPTO_EccKeyGenerationContext *gc = cls; + + gc->cont (gc->cont_cls, + gc->pk, + NULL); + GNUNET_free (gc); +} + + +/** + * Create a new private key by reading it from a file. If the files + * does not exist, create a new key and write it to the file. If the + * contents of the file are invalid the old file is deleted and a + * fresh key is created. + * + * @param filename name of file to use for storage + * @param cont function to call when done (or on errors) + * @param cont_cls closure for 'cont' + * @return handle to abort operation, NULL on fatal errors (cont will not be called if NULL is returned) + */ +struct GNUNET_CRYPTO_EccKeyGenerationContext * +GNUNET_CRYPTO_ecc_key_create_start (const char *filename, + GNUNET_CRYPTO_EccKeyCallback cont, + void *cont_cls) +{ + struct GNUNET_CRYPTO_EccKeyGenerationContext *gc; + struct GNUNET_CRYPTO_EccPrivateKey *pk; + const char *weak_random; + + if (NULL != (pk = try_read_key (filename))) + { + /* quick happy ending: key already exists! */ + gc = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccKeyGenerationContext)); + gc->pk = pk; + gc->cont = cont; + gc->cont_cls = cont_cls; + gc->read_task = GNUNET_SCHEDULER_add_now (&async_return_key, + gc); + return gc; + } + gc = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccKeyGenerationContext)); + gc->filename = GNUNET_strdup (filename); + gc->cont = cont; + gc->cont_cls = cont_cls; + gc->gnunet_ecc_out = GNUNET_DISK_pipe (GNUNET_NO, + GNUNET_NO, + GNUNET_NO, + GNUNET_YES); + if (NULL == gc->gnunet_ecc_out) + { + GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "pipe"); + GNUNET_free (gc->filename); + GNUNET_free (gc); + return NULL; + } + weak_random = NULL; + if (GNUNET_YES == + GNUNET_CRYPTO_random_is_weak ()) + weak_random = "-w"; + gc->gnunet_ecc = GNUNET_OS_start_process (GNUNET_NO, + GNUNET_OS_INHERIT_STD_ERR, + NULL, + gc->gnunet_ecc_out, + "gnunet-ecc", + "gnunet-ecc", + gc->filename, + weak_random, + NULL); + if (NULL == gc->gnunet_ecc) + { + GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "fork"); + GNUNET_DISK_pipe_close (gc->gnunet_ecc_out); + GNUNET_free (gc->filename); + GNUNET_free (gc); + return NULL; + } + GNUNET_assert (GNUNET_OK == + GNUNET_DISK_pipe_close_end (gc->gnunet_ecc_out, + GNUNET_DISK_PIPE_END_WRITE)); + gc->read_task = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, + GNUNET_DISK_pipe_handle (gc->gnunet_ecc_out, + GNUNET_DISK_PIPE_END_READ), + &check_key_generation_completion, + gc); + return gc; +} + + +/** + * Setup a key file for a peer given the name of the + * configuration file (!). This function is used so that + * at a later point code can be certain that reading a + * key is fast (for example in time-dependent testcases). + * + * @param cfg_name name of the configuration file to use + */ +void +GNUNET_CRYPTO_ecc_setup_key (const char *cfg_name) +{ + struct GNUNET_CONFIGURATION_Handle *cfg; + struct GNUNET_CRYPTO_EccPrivateKey *pk; + char *fn; + + cfg = GNUNET_CONFIGURATION_create (); + (void) GNUNET_CONFIGURATION_load (cfg, cfg_name); + if (GNUNET_OK == + GNUNET_CONFIGURATION_get_value_filename (cfg, "PEER", "PRIVATE_KEY", &fn)) + { + pk = GNUNET_CRYPTO_ecc_key_create_from_file (fn); + if (NULL != pk) + GNUNET_CRYPTO_ecc_key_free (pk); + GNUNET_free (fn); + } + GNUNET_CONFIGURATION_destroy (cfg); +} + + +/** + * Convert the data specified in the given purpose argument to an + * S-expression suitable for signature operations. + * + * @param purpose data to convert + * @return converted s-expression + */ +static gcry_sexp_t +data_to_pkcs1 (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose) +{ + struct GNUNET_CRYPTO_ShortHashCode hc; + size_t bufSize; + gcry_sexp_t data; + + GNUNET_CRYPTO_short_hash (purpose, ntohl (purpose->size), &hc); +#define FORMATSTRING "(4:data(5:flags3:raw)(5:value32:01234567890123456789012345678901))" +#define FORMATSTRING2 "(4:data(4:hash6:sha25632:01234567890123456789012345678901))" + bufSize = strlen (FORMATSTRING) + 1; + { + char buff[bufSize]; + + memcpy (buff, FORMATSTRING, bufSize); + memcpy (&buff + [bufSize - + strlen + ("01234567890123456789012345678901))") + - 1], &hc, sizeof (struct GNUNET_CRYPTO_ShortHashCode)); + GNUNET_assert (0 == gcry_sexp_new (&data, buff, bufSize, 0)); + } +#undef FORMATSTRING + return data; +} + + +/** + * Sign a given block. + * + * @param key private key to use for the signing + * @param purpose what to sign (size, purpose) + * @param sig where to write the signature + * @return GNUNET_SYSERR on error, GNUNET_OK on success + */ +int +GNUNET_CRYPTO_ecc_sign (const struct GNUNET_CRYPTO_EccPrivateKey *key, + const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, + struct GNUNET_CRYPTO_EccSignature *sig) +{ + gcry_sexp_t result; + gcry_sexp_t data; + size_t ssize; + int rc; + + data = data_to_pkcs1 (purpose); + if (0 != (rc = gcry_pk_sign (&result, data, key->sexp))) + { + LOG (GNUNET_ERROR_TYPE_WARNING, + _("ECC signing failed at %s:%d: %s\n"), __FILE__, + __LINE__, gcry_strerror (rc)); + } + gcry_sexp_release (data); + ssize = gcry_sexp_sprint (result, + GCRYSEXP_FMT_DEFAULT, + sig->sexpr, + GNUNET_CRYPTO_ECC_SIGNATURE_DATA_ENCODING_LENGTH); + if (0 == ssize) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + sig->size = htons ((uint16_t) (ssize + sizeof (uint16_t))); + /* padd with zeros */ + memset (&sig->sexpr[ssize], 0, GNUNET_CRYPTO_ECC_SIGNATURE_DATA_ENCODING_LENGTH - ssize); + gcry_sexp_release (result); + return GNUNET_OK; +} + + +/** + * Verify signature. + * + * @param purpose what is the purpose that the signature should have? + * @param validate block to validate (size, purpose, data) + * @param sig signature that is being validated + * @param publicKey public key of the signer + * @returns GNUNET_OK if ok, GNUNET_SYSERR if invalid + */ +int +GNUNET_CRYPTO_ecc_verify (uint32_t purpose, + const struct GNUNET_CRYPTO_EccSignaturePurpose + *validate, + const struct GNUNET_CRYPTO_EccSignature *sig, + const struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded + *publicKey) +{ + gcry_sexp_t data; + gcry_sexp_t sigdata; + size_t size; + gcry_sexp_t psexp; + size_t erroff; + int rc; + + if (purpose != ntohl (validate->purpose)) + return GNUNET_SYSERR; /* purpose mismatch */ + size = ntohs (sig->size); + if ( (size < sizeof (uint16_t)) || + (size > GNUNET_CRYPTO_ECC_SIGNATURE_DATA_ENCODING_LENGTH - sizeof (uint16_t)) ) + return GNUNET_SYSERR; /* size out of range */ + data = data_to_pkcs1 (validate); + GNUNET_assert (0 == + gcry_sexp_sscan (&sigdata, &erroff, + sig->sexpr, size - sizeof (uint16_t))); + if (! (psexp = decode_public_key (publicKey))) + { + gcry_sexp_release (data); + gcry_sexp_release (sigdata); + return GNUNET_SYSERR; + } + rc = gcry_pk_verify (sigdata, data, psexp); + gcry_sexp_release (psexp); + gcry_sexp_release (data); + gcry_sexp_release (sigdata); + if (0 != rc) + { + LOG (GNUNET_ERROR_TYPE_WARNING, + _("ECC signature verification failed at %s:%d: %s\n"), __FILE__, + __LINE__, gcry_strerror (rc)); + return GNUNET_SYSERR; + } + return GNUNET_OK; +} + + +/** + * Derive key material from a public and a private ECC key. + * + * @param key private key to use for the ECDH (x) + * @param pub public key to use for the ECDY (yG) + * @param key_material where to write the key material (xyG) + * @return GNUNET_SYSERR on error, GNUNET_OK on success + */ +int +GNUNET_CRYPTO_ecc_ecdh (const struct GNUNET_CRYPTO_EccPrivateKey *key, + const struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded *pub, + struct GNUNET_HashCode *key_material) +{ + gcry_sexp_t psexp; + + if (! (psexp = decode_public_key (pub))) + return GNUNET_SYSERR; + + + gcry_sexp_release (psexp); + GNUNET_break (0); // not implemented + /* FIXME: this totally breaks security ... */ + memset (key_material, 42, sizeof (struct GNUNET_HashCode)); + return GNUNET_OK; +} + + +/* end of crypto_ecc.c */ diff --git a/src/util/crypto_hash.c b/src/util/crypto_hash.c index 4d957c0..04225b3 100644 --- a/src/util/crypto_hash.c +++ b/src/util/crypto_hash.c @@ -49,7 +49,7 @@ * @param ret pointer to where to write the hashcode */ void -GNUNET_CRYPTO_hash (const void *block, size_t size, GNUNET_HashCode * ret) +GNUNET_CRYPTO_hash (const void *block, size_t size, struct GNUNET_HashCode * ret) { gcry_md_hash_buffer (GCRY_MD_SHA512, ret, block, size); } @@ -140,7 +140,7 @@ struct GNUNET_CRYPTO_FileHashContext */ static void file_hash_finish (struct GNUNET_CRYPTO_FileHashContext *fhc, - const GNUNET_HashCode * res) + const struct GNUNET_HashCode * res) { fhc->callback (fhc->callback_cls, res); GNUNET_free (fhc->filename); @@ -161,7 +161,7 @@ static void file_hash_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_CRYPTO_FileHashContext *fhc = cls; - GNUNET_HashCode *res; + struct GNUNET_HashCode *res; size_t delta; fhc->task = GNUNET_SCHEDULER_NO_TASK; @@ -179,7 +179,7 @@ file_hash_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) fhc->offset += delta; if (fhc->offset == fhc->fsize) { - res = (GNUNET_HashCode *) gcry_md_read (fhc->md, GCRY_MD_SHA512); + res = (struct GNUNET_HashCode *) gcry_md_read (fhc->md, GCRY_MD_SHA512); file_hash_finish (fhc, res); return; } @@ -272,7 +272,7 @@ GNUNET_CRYPTO_hash_file_cancel (struct GNUNET_CRYPTO_FileHashContext *fhc) * safely cast to char*, a '\\0' termination is set). */ void -GNUNET_CRYPTO_hash_to_enc (const GNUNET_HashCode * block, +GNUNET_CRYPTO_hash_to_enc (const struct GNUNET_HashCode * block, struct GNUNET_CRYPTO_HashAsciiEncoded *result) { char *np; @@ -296,7 +296,7 @@ GNUNET_CRYPTO_hash_to_enc (const GNUNET_HashCode * block, */ int GNUNET_CRYPTO_hash_from_string2 (const char *enc, size_t enclen, - GNUNET_HashCode * result) + struct GNUNET_HashCode * result) { char upper_enc[enclen]; char* up_ptr = upper_enc; @@ -321,8 +321,8 @@ GNUNET_CRYPTO_hash_from_string2 (const char *enc, size_t enclen, * hashcode proximity. */ unsigned int -GNUNET_CRYPTO_hash_distance_u32 (const GNUNET_HashCode * a, - const GNUNET_HashCode * b) +GNUNET_CRYPTO_hash_distance_u32 (const struct GNUNET_HashCode * a, + const struct GNUNET_HashCode * b) { unsigned int x1 = (a->bits[1] - b->bits[1]) >> 16; unsigned int x2 = (b->bits[1] - a->bits[1]) >> 16; @@ -339,11 +339,11 @@ GNUNET_CRYPTO_hash_distance_u32 (const GNUNET_HashCode * a, */ void GNUNET_CRYPTO_hash_create_random (enum GNUNET_CRYPTO_Quality mode, - GNUNET_HashCode * result) + struct GNUNET_HashCode * result) { int i; - for (i = (sizeof (GNUNET_HashCode) / sizeof (uint32_t)) - 1; i >= 0; i--) + for (i = (sizeof (struct GNUNET_HashCode) / sizeof (uint32_t)) - 1; i >= 0; i--) result->bits[i] = GNUNET_CRYPTO_random_u32 (mode, UINT32_MAX); } @@ -356,13 +356,13 @@ GNUNET_CRYPTO_hash_create_random (enum GNUNET_CRYPTO_Quality mode, * @param result set to b - a */ void -GNUNET_CRYPTO_hash_difference (const GNUNET_HashCode * a, - const GNUNET_HashCode * b, - GNUNET_HashCode * result) +GNUNET_CRYPTO_hash_difference (const struct GNUNET_HashCode * a, + const struct GNUNET_HashCode * b, + struct GNUNET_HashCode * result) { int i; - for (i = (sizeof (GNUNET_HashCode) / sizeof (unsigned int)) - 1; i >= 0; i--) + for (i = (sizeof (struct GNUNET_HashCode) / sizeof (unsigned int)) - 1; i >= 0; i--) result->bits[i] = b->bits[i] - a->bits[i]; } @@ -375,12 +375,12 @@ GNUNET_CRYPTO_hash_difference (const GNUNET_HashCode * a, * @param result set to a + delta */ void -GNUNET_CRYPTO_hash_sum (const GNUNET_HashCode * a, - const GNUNET_HashCode * delta, GNUNET_HashCode * result) +GNUNET_CRYPTO_hash_sum (const struct GNUNET_HashCode * a, + const struct GNUNET_HashCode * delta, struct GNUNET_HashCode * result) { int i; - for (i = (sizeof (GNUNET_HashCode) / sizeof (unsigned int)) - 1; i >= 0; i--) + for (i = (sizeof (struct GNUNET_HashCode) / sizeof (unsigned int)) - 1; i >= 0; i--) result->bits[i] = delta->bits[i] + a->bits[i]; } @@ -393,12 +393,12 @@ GNUNET_CRYPTO_hash_sum (const GNUNET_HashCode * a, * @param result set to a ^ b */ void -GNUNET_CRYPTO_hash_xor (const GNUNET_HashCode * a, const GNUNET_HashCode * b, - GNUNET_HashCode * result) +GNUNET_CRYPTO_hash_xor (const struct GNUNET_HashCode * a, const struct GNUNET_HashCode * b, + struct GNUNET_HashCode * result) { int i; - for (i = (sizeof (GNUNET_HashCode) / sizeof (unsigned int)) - 1; i >= 0; i--) + for (i = (sizeof (struct GNUNET_HashCode) / sizeof (unsigned int)) - 1; i >= 0; i--) result->bits[i] = a->bits[i] ^ b->bits[i]; } @@ -411,11 +411,11 @@ GNUNET_CRYPTO_hash_xor (const GNUNET_HashCode * a, const GNUNET_HashCode * b, * @param iv set to a valid initialization vector */ void -GNUNET_CRYPTO_hash_to_aes_key (const GNUNET_HashCode * hc, +GNUNET_CRYPTO_hash_to_aes_key (const struct GNUNET_HashCode * hc, struct GNUNET_CRYPTO_AesSessionKey *skey, struct GNUNET_CRYPTO_AesInitializationVector *iv) { - GNUNET_assert (sizeof (GNUNET_HashCode) >= + GNUNET_assert (sizeof (struct GNUNET_HashCode) >= GNUNET_CRYPTO_AES_KEY_LENGTH + sizeof (struct GNUNET_CRYPTO_AesInitializationVector)); memcpy (skey, hc, GNUNET_CRYPTO_AES_KEY_LENGTH); @@ -433,16 +433,16 @@ GNUNET_CRYPTO_hash_to_aes_key (const GNUNET_HashCode * hc, * @return Bit \a bit from hashcode \a code, -1 for invalid index */ int -GNUNET_CRYPTO_hash_get_bit (const GNUNET_HashCode * code, unsigned int bit) +GNUNET_CRYPTO_hash_get_bit (const struct GNUNET_HashCode * code, unsigned int bit) { - GNUNET_assert (bit < 8 * sizeof (GNUNET_HashCode)); + GNUNET_assert (bit < 8 * sizeof (struct GNUNET_HashCode)); return (((unsigned char *) code)[bit >> 3] & (1 << (bit & 7))) > 0; } /** * Determine how many low order bits match in two - * GNUNET_HashCodes. i.e. - 010011 and 011111 share + * struct GNUNET_HashCodes. i.e. - 010011 and 011111 share * the first two lowest order bits, and therefore the * return value is two (NOT XOR distance, nor how many * bits match absolutely!). @@ -453,16 +453,16 @@ GNUNET_CRYPTO_hash_get_bit (const GNUNET_HashCode * code, unsigned int bit) * @return the number of bits that match */ unsigned int -GNUNET_CRYPTO_hash_matching_bits (const GNUNET_HashCode * first, - const GNUNET_HashCode * second) +GNUNET_CRYPTO_hash_matching_bits (const struct GNUNET_HashCode * first, + const struct GNUNET_HashCode * second) { unsigned int i; - for (i = 0; i < sizeof (GNUNET_HashCode) * 8; i++) + for (i = 0; i < sizeof (struct GNUNET_HashCode) * 8; i++) if (GNUNET_CRYPTO_hash_get_bit (first, i) != GNUNET_CRYPTO_hash_get_bit (second, i)) return i; - return sizeof (GNUNET_HashCode) * 8; + return sizeof (struct GNUNET_HashCode) * 8; } @@ -475,7 +475,7 @@ GNUNET_CRYPTO_hash_matching_bits (const GNUNET_HashCode * first, * @return 1 if h1 > h2, -1 if h1 < h2 and 0 if h1 == h2. */ int -GNUNET_CRYPTO_hash_cmp (const GNUNET_HashCode * h1, const GNUNET_HashCode * h2) +GNUNET_CRYPTO_hash_cmp (const struct GNUNET_HashCode * h1, const struct GNUNET_HashCode * h2) { unsigned int *i1; unsigned int *i2; @@ -483,7 +483,7 @@ GNUNET_CRYPTO_hash_cmp (const GNUNET_HashCode * h1, const GNUNET_HashCode * h2) i1 = (unsigned int *) h1; i2 = (unsigned int *) h2; - for (i = (sizeof (GNUNET_HashCode) / sizeof (unsigned int)) - 1; i >= 0; i--) + for (i = (sizeof (struct GNUNET_HashCode) / sizeof (unsigned int)) - 1; i >= 0; i--) { if (i1[i] > i2[i]) return 1; @@ -504,15 +504,15 @@ GNUNET_CRYPTO_hash_cmp (const GNUNET_HashCode * h1, const GNUNET_HashCode * h2) * @return -1 if h1 is closer, 1 if h2 is closer and 0 if h1==h2. */ int -GNUNET_CRYPTO_hash_xorcmp (const GNUNET_HashCode * h1, - const GNUNET_HashCode * h2, - const GNUNET_HashCode * target) +GNUNET_CRYPTO_hash_xorcmp (const struct GNUNET_HashCode * h1, + const struct GNUNET_HashCode * h2, + const struct GNUNET_HashCode * target) { int i; unsigned int d1; unsigned int d2; - for (i = sizeof (GNUNET_HashCode) / sizeof (unsigned int) - 1; i >= 0; i--) + for (i = sizeof (struct GNUNET_HashCode) / sizeof (unsigned int) - 1; i >= 0; i--) { d1 = ((unsigned int *) h1)[i] ^ ((unsigned int *) target)[i]; d2 = ((unsigned int *) h2)[i] ^ ((unsigned int *) target)[i]; @@ -576,7 +576,7 @@ GNUNET_CRYPTO_hmac_derive_key_v (struct GNUNET_CRYPTO_AuthKey *key, void GNUNET_CRYPTO_hmac (const struct GNUNET_CRYPTO_AuthKey *key, const void *plaintext, size_t plaintext_len, - GNUNET_HashCode * hmac) + struct GNUNET_HashCode * hmac) { gcry_md_hd_t md; const unsigned char *mc; diff --git a/src/util/crypto_ksk.c b/src/util/crypto_ksk.c index 274457b..0c09109 100644 --- a/src/util/crypto_ksk.c +++ b/src/util/crypto_ksk.c @@ -70,11 +70,11 @@ struct GNUNET_CRYPTO_RsaPrivateKey static void -mpz_randomize (gcry_mpi_t n, unsigned int nbits, GNUNET_HashCode * rnd) +mpz_randomize (gcry_mpi_t n, unsigned int nbits, struct GNUNET_HashCode * rnd) { - GNUNET_HashCode hc; - GNUNET_HashCode tmp; - int bits_per_hc = sizeof (GNUNET_HashCode) * 8; + struct GNUNET_HashCode hc; + struct GNUNET_HashCode tmp; + int bits_per_hc = sizeof (struct GNUNET_HashCode) * 8; int cnt; int i; @@ -88,8 +88,8 @@ mpz_randomize (gcry_mpi_t n, unsigned int nbits, GNUNET_HashCode * rnd) int j; if (i > 0) - GNUNET_CRYPTO_hash (&hc, sizeof (GNUNET_HashCode), &tmp); - for (j = 0; j < sizeof (GNUNET_HashCode) / sizeof (uint32_t); j++) + GNUNET_CRYPTO_hash (&hc, sizeof (struct GNUNET_HashCode), &tmp); + for (j = 0; j < sizeof (struct GNUNET_HashCode) / sizeof (uint32_t); j++) { #if HAVE_GCRY_MPI_LSHIFT gcry_mpi_lshift (n, n, sizeof (uint32_t) * 8); @@ -101,7 +101,7 @@ mpz_randomize (gcry_mpi_t n, unsigned int nbits, GNUNET_HashCode * rnd) } hc = tmp; } - GNUNET_CRYPTO_hash (&hc, sizeof (GNUNET_HashCode), rnd); + GNUNET_CRYPTO_hash (&hc, sizeof (struct GNUNET_HashCode), rnd); i = gcry_mpi_get_nbits (n); while (i > nbits) gcry_mpi_clear_bit (n, --i); @@ -137,7 +137,7 @@ mpz_tdiv_q_2exp (gcry_mpi_t q, gcry_mpi_t n, unsigned int b) * Return true if n is probably a prime */ static int -is_prime (gcry_mpi_t n, int steps, GNUNET_HashCode * hc) +is_prime (gcry_mpi_t n, int steps, struct GNUNET_HashCode * hc) { gcry_mpi_t x; gcry_mpi_t y; @@ -218,7 +218,7 @@ adjust (unsigned char *buf, size_t size, size_t target) static void -gen_prime (gcry_mpi_t * ptest, unsigned int nbits, GNUNET_HashCode * hc) +gen_prime (gcry_mpi_t * ptest, unsigned int nbits, struct GNUNET_HashCode * hc) { /* Note: 2 is not included because it can be tested more easily by * looking at bit 0. The last entry in this list is marked by a zero */ @@ -400,7 +400,7 @@ gen_prime (gcry_mpi_t * ptest, unsigned int nbits, GNUNET_HashCode * hc) */ static void generate_kblock_key (KBlock_secret_key *sk, unsigned int nbits, - GNUNET_HashCode * hc) + struct GNUNET_HashCode * hc) { gcry_mpi_t t1, t2; gcry_mpi_t phi; /* helper: (p-1)(q-1) */ @@ -490,10 +490,10 @@ GNUNET_NETWORK_STRUCT_END * given HashCode as input to the PRNG. */ static struct KskRsaPrivateKeyBinaryEncoded * -makeKblockKeyInternal (const GNUNET_HashCode * hc) +makeKblockKeyInternal (const struct GNUNET_HashCode * hc) { KBlock_secret_key sk; - GNUNET_HashCode hx; + struct GNUNET_HashCode hx; unsigned char *pbu[6]; gcry_mpi_t *pkv[6]; size_t sizes[6]; @@ -564,7 +564,7 @@ struct KBlockKeyCacheLine /** * Hash from which the key was generated. */ - GNUNET_HashCode hc; + struct GNUNET_HashCode hc; /** * The encoded key. @@ -594,13 +594,13 @@ static unsigned int cacheSize; * @return corresponding private key; must not be freed! */ struct GNUNET_CRYPTO_RsaPrivateKey * -GNUNET_CRYPTO_rsa_key_create_from_hash (const GNUNET_HashCode * hc) +GNUNET_CRYPTO_rsa_key_create_from_hash (const struct GNUNET_HashCode * hc) { struct KBlockKeyCacheLine *line; unsigned int i; for (i = 0; i < cacheSize; i++) - if (0 == memcmp (hc, &cache[i]->hc, sizeof (GNUNET_HashCode))) + if (0 == memcmp (hc, &cache[i]->hc, sizeof (struct GNUNET_HashCode))) return GNUNET_CRYPTO_rsa_decode_key ((const char*) cache[i]->pke, ntohs (cache[i]->pke->len)); line = GNUNET_malloc (sizeof (struct KBlockKeyCacheLine)); diff --git a/src/util/crypto_random.c b/src/util/crypto_random.c index 35d3c41..b61d596 100644 --- a/src/util/crypto_random.c +++ b/src/util/crypto_random.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - (C) 2001, 2002, 2003, 2004, 2005, 2006 Christian Grothoff (and other contributing authors) + (C) 2001, 2002, 2003, 2004, 2005, 2006, 2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published @@ -34,6 +34,14 @@ #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall) + +/** + * GNUNET_YES if we are using a 'weak' (low-entropy) PRNG. + */ +static int weak_random; + + + /* TODO: ndurner, move this to plibc? */ /* The code is derived from glibc, obviously */ #if MINGW @@ -45,14 +53,22 @@ #endif #define RANDOM() glibc_weak_rand32() #define SRANDOM(s) glibc_weak_srand32(s) +#if defined(RAND_MAX) +#undef RAND_MAX +#endif +#define RAND_MAX 0x7fffffff /* Hopefully this is correct */ + + static int32_t glibc_weak_rand32_state = 1; + void glibc_weak_srand32 (int32_t s) { glibc_weak_rand32_state = s; } + int32_t glibc_weak_rand32 () { @@ -70,11 +86,12 @@ glibc_weak_rand32 () * @return number between 0 and 1. */ static double -weak_random () +get_weak_random () { return ((double) RANDOM () / RAND_MAX); } + /** * Seed a weak random generator. Only GNUNET_CRYPTO_QUALITY_WEAK-mode generator * can be seeded. @@ -87,6 +104,7 @@ GNUNET_CRYPTO_seed_weak_random (int32_t seed) SRANDOM (seed); } + /** * Produce a random value. * @@ -130,7 +148,7 @@ GNUNET_CRYPTO_random_u32 (enum GNUNET_CRYPTO_Quality mode, uint32_t i) while (ret >= ul); return ret % i; case GNUNET_CRYPTO_QUALITY_WEAK: - ret = i * weak_random (); + ret = i * get_weak_random (); if (ret >= i) ret = i - 1; return ret; @@ -207,7 +225,7 @@ GNUNET_CRYPTO_random_u64 (enum GNUNET_CRYPTO_Quality mode, uint64_t max) return ret % max; case GNUNET_CRYPTO_QUALITY_WEAK: - ret = max * weak_random (); + ret = max * get_weak_random (); if (ret >= max) ret = max - 1; return ret; @@ -217,6 +235,19 @@ GNUNET_CRYPTO_random_u64 (enum GNUNET_CRYPTO_Quality mode, uint64_t max) return 0; } + +/** + * Check if we are using weak random number generation. + * + * @return GNUNET_YES if weak number generation is on + */ +int +GNUNET_CRYPTO_random_is_weak () +{ + return weak_random; +} + + /** * This function should only be called in testcases * where strong entropy gathering is not desired @@ -225,6 +256,7 @@ GNUNET_CRYPTO_random_u64 (enum GNUNET_CRYPTO_Quality mode, uint64_t max) void GNUNET_CRYPTO_random_disable_entropy_gathering () { + weak_random = GNUNET_YES; gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0); } @@ -235,6 +267,7 @@ GNUNET_CRYPTO_random_disable_entropy_gathering () */ static struct GNUNET_OS_Process *genproc; + /** * Function called by libgcrypt whenever we are * blocked gathering entropy. @@ -253,7 +286,7 @@ entropy_generator (void *cls, const char *what, int printchar, int current, { if (genproc != NULL) { - if (0 != GNUNET_OS_process_kill (genproc, SIGTERM)) + if (0 != GNUNET_OS_process_kill (genproc, SIGKILL)) LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "kill"); GNUNET_break (GNUNET_OK == GNUNET_OS_process_wait (genproc)); GNUNET_OS_process_destroy (genproc); @@ -271,7 +304,7 @@ entropy_generator (void *cls, const char *what, int printchar, int current, GNUNET_break (0); return; } - if (0 != GNUNET_OS_process_kill (genproc, SIGTERM)) + if (0 != GNUNET_OS_process_kill (genproc, SIGKILL)) LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "kill"); GNUNET_break (GNUNET_OK == GNUNET_OS_process_wait (genproc)); GNUNET_OS_process_destroy (genproc); @@ -280,7 +313,7 @@ entropy_generator (void *cls, const char *what, int printchar, int current, LOG (GNUNET_ERROR_TYPE_INFO, _("Starting `%s' process to generate entropy\n"), "find"); genproc = - GNUNET_OS_start_process (GNUNET_NO, + GNUNET_OS_start_process (GNUNET_NO, 0, NULL, NULL, "sh", "sh", "-c", "exec find / -mount -type f -exec cp {} /dev/null \\; 2>/dev/null", NULL); @@ -302,12 +335,12 @@ killfind () void __attribute__ ((constructor)) GNUNET_CRYPTO_random_init () { gcry_control (GCRYCTL_DISABLE_SECMEM, 0); - if (!gcry_check_version (GCRYPT_VERSION)) + if (!gcry_check_version (NEED_LIBGCRYPT_VERSION)) { FPRINTF (stderr, _ ("libgcrypt has not the expected version (version %s is required).\n"), - GCRYPT_VERSION); + NEED_LIBGCRYPT_VERSION); GNUNET_abort (); } #ifdef GCRYCTL_INITIALIZATION_FINISHED diff --git a/src/util/crypto_rsa.c b/src/util/crypto_rsa.c index 0106f43..cd9a33f 100644 --- a/src/util/crypto_rsa.c +++ b/src/util/crypto_rsa.c @@ -22,21 +22,11 @@ * @file util/crypto_rsa.c * @brief public key cryptography (RSA) with libgcrypt * @author Christian Grothoff - * - * Note that the code locks often needlessly on the gcrypt-locking api. - * One would think that simple MPI operations should not require locking - * (since only global operations on the random pool must be locked, - * strictly speaking). But libgcrypt does sometimes require locking in - * unexpected places, so the safe solution is to always lock even if it - * is not required. The performance impact is minimal anyway. */ - #include "platform.h" #include <gcrypt.h> #include "gnunet_common.h" -#include "gnunet_crypto_lib.h" -#include "gnunet_disk_lib.h" -#include "gnunet_strings_lib.h" +#include "gnunet_util_lib.h" #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) @@ -44,21 +34,23 @@ #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename) +#define HOSTKEY_LEN 2048 + +#define EXTRA_CHECKS ALLOW_EXTRA_CHECKS + + /** * The private information of an RSA key pair. - * NOTE: this must match the definition in crypto_ksk.c + * NOTE: this must match the definition in crypto_ksk.c and gnunet-rsa.c! */ struct GNUNET_CRYPTO_RsaPrivateKey { + /** + * Libgcrypt S-expression for the ECC key. + */ gcry_sexp_t sexp; }; - -#define HOSTKEY_LEN 2048 - -#define EXTRA_CHECKS ALLOW_EXTRA_CHECKS - - /** * Log an error message at log-level 'level' that indicates * a failure of the command 'cmd' with the message given @@ -70,6 +62,10 @@ struct GNUNET_CRYPTO_RsaPrivateKey * If target != size, move target bytes to the * end of the size-sized buffer and zero out the * first target-size bytes. + * + * @param buf original buffer + * @param size number of bytes in the buffer + * @param target target size of the buffer */ static void adjust (unsigned char *buf, size_t size, size_t target) @@ -81,69 +77,50 @@ adjust (unsigned char *buf, size_t size, size_t target) } } + /** - * Create a new private key. Caller must free return value. + * Free memory occupied by RSA private key. * - * @return fresh private key + * @param key pointer to the memory to free */ -struct GNUNET_CRYPTO_RsaPrivateKey * -GNUNET_CRYPTO_rsa_key_create () +void +GNUNET_CRYPTO_rsa_key_free (struct GNUNET_CRYPTO_RsaPrivateKey *key) { - struct GNUNET_CRYPTO_RsaPrivateKey *ret; - gcry_sexp_t s_key; - gcry_sexp_t s_keyparam; - - GNUNET_assert (0 == - gcry_sexp_build (&s_keyparam, NULL, - "(genkey(rsa(nbits %d)(rsa-use-e 3:257)))", - HOSTKEY_LEN)); - GNUNET_assert (0 == gcry_pk_genkey (&s_key, s_keyparam)); - gcry_sexp_release (s_keyparam); -#if EXTRA_CHECKS - GNUNET_assert (0 == gcry_pk_testkey (s_key)); -#endif - ret = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_RsaPrivateKey)); - ret->sexp = s_key; - return ret; + gcry_sexp_release (key->sexp); + GNUNET_free (key); } + /** - * Free memory occupied by hostkey - * @param hostkey pointer to the memory to free + * Extract values from an S-expression. + * + * @param array where to store the result(s) + * @param sexp S-expression to parse + * @param topname top-level name in the S-expression that is of interest + * @param elems names of the elements to extract + * @return 0 on success */ -void -GNUNET_CRYPTO_rsa_key_free (struct GNUNET_CRYPTO_RsaPrivateKey *hostkey) -{ - gcry_sexp_release (hostkey->sexp); - GNUNET_free (hostkey); -} - static int key_from_sexp (gcry_mpi_t * array, gcry_sexp_t sexp, const char *topname, const char *elems) { - gcry_sexp_t list, l2; + gcry_sexp_t list; + gcry_sexp_t l2; const char *s; - int i, idx; + unsigned int i; + unsigned int idx; - list = gcry_sexp_find_token (sexp, topname, 0); - if (!list) - { - return 1; - } + if (! (list = gcry_sexp_find_token (sexp, topname, 0))) + return 1; l2 = gcry_sexp_cadr (list); gcry_sexp_release (list); list = l2; - if (!list) - { + if (! list) return 2; - } - idx = 0; for (s = elems; *s; s++, idx++) { - l2 = gcry_sexp_find_token (list, s, 1); - if (!l2) + if (! (l2 = gcry_sexp_find_token (list, s, 1))) { for (i = 0; i < idx; i++) { @@ -155,7 +132,7 @@ key_from_sexp (gcry_mpi_t * array, gcry_sexp_t sexp, const char *topname, } array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG); gcry_sexp_release (l2); - if (!array[idx]) + if (! array[idx]) { for (i = 0; i < idx; i++) { @@ -170,8 +147,10 @@ key_from_sexp (gcry_mpi_t * array, gcry_sexp_t sexp, const char *topname, return 0; } + /** * Extract the public key of the host. + * * @param priv the private key * @param pub where to write the public key */ @@ -186,9 +165,9 @@ GNUNET_CRYPTO_rsa_key_get_public (const struct GNUNET_CRYPTO_RsaPrivateKey int rc; rc = key_from_sexp (skey, priv->sexp, "public-key", "ne"); - if (rc) + if (0 != rc) rc = key_from_sexp (skey, priv->sexp, "private-key", "ne"); - if (rc) + if (0 != rc) rc = key_from_sexp (skey, priv->sexp, "rsa", "ne"); GNUNET_assert (0 == rc); pub->len = @@ -222,7 +201,7 @@ GNUNET_CRYPTO_rsa_key_get_public (const struct GNUNET_CRYPTO_RsaPrivateKey * @return string representing 'pub' */ char * -GNUNET_CRYPTO_rsa_public_key_to_string (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pub) +GNUNET_CRYPTO_rsa_public_key_to_string (const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pub) { char *pubkeybuf; size_t keylen = (sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded)) * 8; @@ -280,16 +259,15 @@ GNUNET_CRYPTO_rsa_public_key_from_string (const char *enc, /** - * Internal: publicKey => RSA-Key. + * Convert the given public key from the network format to the + * S-expression that can be used by libgcrypt. * - * Note that the return type is not actually a private - * key but rather an sexpression for the public key! + * @param publicKey public key to decode + * @return NULL on error */ -static struct GNUNET_CRYPTO_RsaPrivateKey * -public2PrivateKey (const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded - *publicKey) +static gcry_sexp_t +decode_public_key (const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *publicKey) { - struct GNUNET_CRYPTO_RsaPrivateKey *ret; gcry_sexp_t result; gcry_mpi_t n; gcry_mpi_t e; @@ -306,17 +284,15 @@ public2PrivateKey (const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded return NULL; } size = GNUNET_CRYPTO_RSA_DATA_ENCODING_LENGTH; - rc = gcry_mpi_scan (&n, GCRYMPI_FMT_USG, &publicKey->key[0], size, &size); - if (rc) + if (0 != (rc = gcry_mpi_scan (&n, GCRYMPI_FMT_USG, &publicKey->key[0], size, &size))) { LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); return NULL; } size = GNUNET_CRYPTO_RSA_KEY_LENGTH - GNUNET_CRYPTO_RSA_DATA_ENCODING_LENGTH; - rc = gcry_mpi_scan (&e, GCRYMPI_FMT_USG, - &publicKey->key[GNUNET_CRYPTO_RSA_DATA_ENCODING_LENGTH], - size, &size); - if (rc) + if (0 != (rc = gcry_mpi_scan (&e, GCRYMPI_FMT_USG, + &publicKey->key[GNUNET_CRYPTO_RSA_DATA_ENCODING_LENGTH], + size, &size))) { LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); gcry_mpi_release (n); @@ -326,21 +302,20 @@ public2PrivateKey (const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded e); gcry_mpi_release (n); gcry_mpi_release (e); - if (rc) + if (0 != rc) { LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc); /* erroff gives more info */ return NULL; } - ret = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_RsaPrivateKey)); - ret->sexp = result; - return ret; + return result; } /** * Encode the private key in a format suitable for * storing it into a file. - * @returns encoding of the private key. + * + * @return encoding of the private key. * The first 4 bytes give the size of the array, as usual. */ struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded * @@ -378,7 +353,7 @@ GNUNET_CRYPTO_rsa_encode_key (const struct GNUNET_CRYPTO_RsaPrivateKey *hostkey) size = sizeof (struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded); for (i = 0; i < 6; i++) { - if (pkv[i] != NULL) + if (NULL != pkv[i]) { GNUNET_assert (0 == gcry_mpi_aprint (GCRYMPI_FMT_USG, @@ -432,6 +407,7 @@ GNUNET_CRYPTO_rsa_encode_key (const struct GNUNET_CRYPTO_RsaPrivateKey *hostkey) * * @param buf the buffer where the private key data is stored * @param len the length of the data in 'buffer' + * @return NULL on error */ struct GNUNET_CRYPTO_RsaPrivateKey * GNUNET_CRYPTO_rsa_decode_key (const char *buf, uint16_t len) @@ -440,11 +416,17 @@ GNUNET_CRYPTO_rsa_decode_key (const char *buf, uint16_t len) const struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded *encoding = (const struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded *) buf; gcry_sexp_t res; - gcry_mpi_t n, e, d, p, q, u; + gcry_mpi_t n; + gcry_mpi_t e; + gcry_mpi_t d; + gcry_mpi_t p; + gcry_mpi_t q; + gcry_mpi_t u; int rc; size_t size; - int pos; + size_t pos; uint16_t enc_len; + size_t erroff; enc_len = ntohs (encoding->len); if (len != enc_len) @@ -456,7 +438,7 @@ GNUNET_CRYPTO_rsa_decode_key (const char *buf, uint16_t len) &((const unsigned char *) (&encoding[1]))[pos], size, &size); pos += ntohs (encoding->sizen); - if (rc) + if (0 != rc) { LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); return NULL; @@ -466,7 +448,7 @@ GNUNET_CRYPTO_rsa_decode_key (const char *buf, uint16_t len) &((const unsigned char *) (&encoding[1]))[pos], size, &size); pos += ntohs (encoding->sizee); - if (rc) + if (0 != rc) { LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); gcry_mpi_release (n); @@ -477,7 +459,7 @@ GNUNET_CRYPTO_rsa_decode_key (const char *buf, uint16_t len) &((const unsigned char *) (&encoding[1]))[pos], size, &size); pos += ntohs (encoding->sized); - if (rc) + if (0 != rc) { LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); gcry_mpi_release (n); @@ -492,7 +474,7 @@ GNUNET_CRYPTO_rsa_decode_key (const char *buf, uint16_t len) &((const unsigned char *) (&encoding[1]))[pos], size, &size); pos += ntohs (encoding->sizep); - if (rc) + if (0 != rc) { LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); gcry_mpi_release (n); @@ -510,13 +492,13 @@ GNUNET_CRYPTO_rsa_decode_key (const char *buf, uint16_t len) &((const unsigned char *) (&encoding[1]))[pos], size, &size); pos += ntohs (encoding->sizeq); - if (rc) + if (0 != rc) { LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); gcry_mpi_release (n); gcry_mpi_release (e); gcry_mpi_release (d); - if (q != NULL) + if (NULL != q) gcry_mpi_release (q); return NULL; } @@ -532,15 +514,15 @@ GNUNET_CRYPTO_rsa_decode_key (const char *buf, uint16_t len) rc = gcry_mpi_scan (&u, GCRYMPI_FMT_USG, &((const unsigned char *) (&encoding[1]))[pos], size, &size); - if (rc) + if (0 != rc) { LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); gcry_mpi_release (n); gcry_mpi_release (e); gcry_mpi_release (d); - if (p != NULL) + if (NULL != p) gcry_mpi_release (p); - if (q != NULL) + if (NULL != q) gcry_mpi_release (q); return NULL; } @@ -548,40 +530,40 @@ GNUNET_CRYPTO_rsa_decode_key (const char *buf, uint16_t len) else u = NULL; - if ((p != NULL) && (q != NULL) && (u != NULL)) + if ((NULL != p) && (NULL != q) && (NULL != u)) { - rc = gcry_sexp_build (&res, &size, /* erroff */ + rc = gcry_sexp_build (&res, &erroff, "(private-key(rsa(n %m)(e %m)(d %m)(p %m)(q %m)(u %m)))", n, e, d, p, q, u); } else { - if ((p != NULL) && (q != NULL)) + if ((NULL != p) && (NULL != q)) { - rc = gcry_sexp_build (&res, &size, /* erroff */ + rc = gcry_sexp_build (&res, &erroff, "(private-key(rsa(n %m)(e %m)(d %m)(p %m)(q %m)))", n, e, d, p, q); } else { - rc = gcry_sexp_build (&res, &size, /* erroff */ + rc = gcry_sexp_build (&res, &erroff, "(private-key(rsa(n %m)(e %m)(d %m)))", n, e, d); } } gcry_mpi_release (n); gcry_mpi_release (e); gcry_mpi_release (d); - if (p != NULL) + if (NULL != p) gcry_mpi_release (p); - if (q != NULL) + if (NULL != q) gcry_mpi_release (q); - if (u != NULL) + if (NULL != u) gcry_mpi_release (u); - if (rc) + if (0 != rc) LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc); #if EXTRA_CHECKS - if (gcry_pk_testkey (res)) + if (0 != (rc = gcry_pk_testkey (res))) { LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc); return NULL; @@ -594,6 +576,120 @@ GNUNET_CRYPTO_rsa_decode_key (const char *buf, uint16_t len) /** + * Create a new private key. Caller must free return value. + * + * @return fresh private key + */ +static struct GNUNET_CRYPTO_RsaPrivateKey * +rsa_key_create () +{ + struct GNUNET_CRYPTO_RsaPrivateKey *ret; + gcry_sexp_t s_key; + gcry_sexp_t s_keyparam; + + GNUNET_assert (0 == + gcry_sexp_build (&s_keyparam, NULL, + "(genkey(rsa(nbits %d)(rsa-use-e 3:257)))", + HOSTKEY_LEN)); + GNUNET_assert (0 == gcry_pk_genkey (&s_key, s_keyparam)); + gcry_sexp_release (s_keyparam); +#if EXTRA_CHECKS + GNUNET_assert (0 == gcry_pk_testkey (s_key)); +#endif + ret = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_RsaPrivateKey)); + ret->sexp = s_key; + return ret; +} + + +/** + * Try to read the private key from the given file. + * + * @param filename file to read the key from + * @return NULL on error + */ +static struct GNUNET_CRYPTO_RsaPrivateKey * +try_read_key (const char *filename) +{ + struct GNUNET_CRYPTO_RsaPrivateKey *ret; + struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded *enc; + struct GNUNET_DISK_FileHandle *fd; + OFF_T fs; + uint16_t len; + + if (GNUNET_YES != GNUNET_DISK_file_test (filename)) + return NULL; + + /* hostkey file exists already, read it! */ + if (NULL == (fd = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ, + GNUNET_DISK_PERM_NONE))) + { + LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "open", filename); + return NULL; + } + if (GNUNET_OK != (GNUNET_DISK_file_handle_size (fd, &fs))) + { + LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "stat", filename); + (void) GNUNET_DISK_file_close (fd); + return NULL; + } + if (0 == fs) + { + GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fd)); + return NULL; + } + if (fs > UINT16_MAX) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + _("File `%s' does not contain a valid private key (too long, %llu bytes). Renaming it.\n"), + filename, + (unsigned long long) fs); + GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fd)); + GNUNET_DISK_file_backup (filename); + return NULL; + } + + enc = GNUNET_malloc (fs); + GNUNET_break (fs == GNUNET_DISK_file_read (fd, enc, fs)); + len = ntohs (enc->len); + ret = NULL; + if ((len != fs) || + (NULL == (ret = GNUNET_CRYPTO_rsa_decode_key ((char *) enc, len)))) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + _("File `%s' does not contain a valid private key (failed decode, %llu bytes). Deleting it.\n"), + filename, + (unsigned long long) fs); + GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fd)); + GNUNET_DISK_file_backup (filename); + GNUNET_free (enc); + return NULL; + } + GNUNET_free (enc); + + GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fd)); + return ret; +} + + +/** + * Wait for a short time (we're trying to lock a file or want + * to give another process a shot at finishing a disk write, etc.). + * Sleeps for 100ms (as that should be long enough for virtually all + * modern systems to context switch and allow another process to do + * some 'real' work). + */ +static void +short_wait () +{ + struct GNUNET_TIME_Relative timeout; + + timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 100); + (void) GNUNET_NETWORK_socket_select (NULL, NULL, NULL, timeout); +} + + +/** * Create a new private key by reading it from a file. If the * files does not exist, create a new key and write it to the * file. Caller must free return value. Note that this function @@ -630,7 +726,7 @@ GNUNET_CRYPTO_rsa_key_create_from_file (const char *filename) GNUNET_DISK_PERM_USER_WRITE); if (NULL == fd) { - if (errno == EEXIST) + if (EEXIST == errno) { if (GNUNET_YES != GNUNET_DISK_file_test (filename)) { @@ -653,18 +749,18 @@ GNUNET_CRYPTO_rsa_key_create_from_file (const char *filename) sizeof (struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded), GNUNET_YES)) { - sleep (1); + short_wait (); if (0 == ++cnt % 10) { ec = errno; LOG (GNUNET_ERROR_TYPE_ERROR, - _("Could not aquire lock on file `%s': %s...\n"), filename, + _("Could not acquire lock on file `%s': %s...\n"), filename, STRERROR (ec)); } } LOG (GNUNET_ERROR_TYPE_INFO, _("Creating a new private key. This may take a while.\n")); - ret = GNUNET_CRYPTO_rsa_key_create (); + ret = rsa_key_create (); GNUNET_assert (ret != NULL); enc = GNUNET_CRYPTO_rsa_encode_key (ret); GNUNET_assert (enc != NULL); @@ -680,9 +776,6 @@ GNUNET_CRYPTO_rsa_key_create_from_file (const char *filename) GNUNET_assert (GNUNET_YES == GNUNET_DISK_file_close (fd)); GNUNET_CRYPTO_rsa_key_get_public (ret, &pub); GNUNET_CRYPTO_hash (&pub, sizeof (pub), &pid.hashPubKey); - LOG (GNUNET_ERROR_TYPE_INFO, - _("I am host `%s'. Stored new private key in `%s'.\n"), - GNUNET_i2s (&pid), filename); return ret; } /* hostkey file exists already, read it! */ @@ -705,13 +798,13 @@ GNUNET_CRYPTO_rsa_key_create_from_file (const char *filename) { ec = errno; LOG (GNUNET_ERROR_TYPE_ERROR, - _("Could not aquire lock on file `%s': %s...\n"), filename, + _("Could not acquire lock on file `%s': %s...\n"), filename, STRERROR (ec)); LOG (GNUNET_ERROR_TYPE_ERROR, _ - ("This may be ok if someone is currently generating a hostkey.\n")); + ("This may be ok if someone is currently generating a private key.\n")); } - sleep (1); + short_wait (); continue; } if (GNUNET_YES != GNUNET_DISK_file_test (filename)) @@ -730,7 +823,7 @@ GNUNET_CRYPTO_rsa_key_create_from_file (const char *filename) fs = 0; if (fs < sizeof (struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded)) { - /* maybe we got the read lock before the hostkey generating + /* maybe we got the read lock before the key generating * process had a chance to get the write lock; give it up! */ if (GNUNET_YES != GNUNET_DISK_file_unlock (fd, 0, @@ -740,14 +833,14 @@ GNUNET_CRYPTO_rsa_key_create_from_file (const char *filename) { LOG (GNUNET_ERROR_TYPE_ERROR, _ - ("When trying to read hostkey file `%s' I found %u bytes but I need at least %u.\n"), + ("When trying to read key file `%s' I found %u bytes but I need at least %u.\n"), filename, (unsigned int) fs, (unsigned int) sizeof (struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded)); LOG (GNUNET_ERROR_TYPE_ERROR, _ - ("This may be ok if someone is currently generating a hostkey.\n")); + ("This may be ok if someone is currently generating a private key.\n")); } - sleep (2); /* wait a bit longer! */ + short_wait (); /* wait a bit longer! */ continue; } break; @@ -762,10 +855,7 @@ GNUNET_CRYPTO_rsa_key_create_from_file (const char *filename) LOG (GNUNET_ERROR_TYPE_ERROR, _("File `%s' does not contain a valid private key. Deleting it.\n"), filename); - if (0 != UNLINK (filename)) - { - LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "unlink", filename); - } + GNUNET_DISK_file_backup (filename); } GNUNET_free (enc); if (GNUNET_YES != @@ -777,24 +867,242 @@ GNUNET_CRYPTO_rsa_key_create_from_file (const char *filename) { GNUNET_CRYPTO_rsa_key_get_public (ret, &pub); GNUNET_CRYPTO_hash (&pub, sizeof (pub), &pid.hashPubKey); - LOG (GNUNET_ERROR_TYPE_INFO, - _("I am host `%s'. Read private key from `%s'.\n"), GNUNET_i2s (&pid), - filename); } return ret; } /** - * Setup a hostkey file for a peer given the name of the + * Handle to cancel private key generation and state for the + * key generation operation. + */ +struct GNUNET_CRYPTO_RsaKeyGenerationContext +{ + + /** + * Continuation to call upon completion. + */ + GNUNET_CRYPTO_RsaKeyCallback cont; + + /** + * Closure for 'cont'. + */ + void *cont_cls; + + /** + * Name of the file. + */ + char *filename; + + /** + * Handle to the helper process which does the key generation. + */ + struct GNUNET_OS_Process *gnunet_rsa; + + /** + * Handle to 'stdout' of gnunet-rsa. We 'read' on stdout to detect + * process termination (instead of messing with SIGCHLD). + */ + struct GNUNET_DISK_PipeHandle *gnunet_rsa_out; + + /** + * Location where we store the private key if it already existed. + * (if this is used, 'filename', 'gnunet_rsa' and 'gnunet_rsa_out' will + * not be used). + */ + struct GNUNET_CRYPTO_RsaPrivateKey *pk; + + /** + * Task reading from 'gnunet_rsa_out' to wait for process termination. + */ + GNUNET_SCHEDULER_TaskIdentifier read_task; + +}; + + +/** + * Task called upon shutdown or process termination of 'gnunet-rsa' during + * RSA key generation. Check where we are and perform the appropriate + * action. + * + * @param cls the 'struct GNUNET_CRYPTO_RsaKeyGenerationContext' + * @param tc scheduler context + */ +static void +check_key_generation_completion (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + struct GNUNET_CRYPTO_RsaKeyGenerationContext *gc = cls; + struct GNUNET_CRYPTO_RsaPrivateKey *pk; + + gc->read_task = GNUNET_SCHEDULER_NO_TASK; + if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) + { + gc->cont (gc->cont_cls, NULL, _("interrupted by shutdown")); + GNUNET_CRYPTO_rsa_key_create_stop (gc); + return; + } + GNUNET_assert (GNUNET_OK == + GNUNET_OS_process_wait (gc->gnunet_rsa)); + GNUNET_OS_process_destroy (gc->gnunet_rsa); + gc->gnunet_rsa = NULL; + if (NULL == (pk = try_read_key (gc->filename))) + { + GNUNET_break (0); + gc->cont (gc->cont_cls, NULL, _("gnunet-rsa failed")); + GNUNET_CRYPTO_rsa_key_create_stop (gc); + return; + } + gc->cont (gc->cont_cls, pk, NULL); + GNUNET_DISK_pipe_close (gc->gnunet_rsa_out); + GNUNET_free (gc->filename); + GNUNET_free (gc); +} + + +/** + * Return the private RSA key which already existed on disk + * (asynchronously) to the caller. + * + * @param cls the 'struct GNUNET_CRYPTO_RsaKeyGenerationContext' + * @param tc scheduler context (unused) + */ +static void +async_return_key (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + struct GNUNET_CRYPTO_RsaKeyGenerationContext *gc = cls; + + gc->cont (gc->cont_cls, + gc->pk, + NULL); + GNUNET_free (gc); +} + + +/** + * Create a new private key by reading it from a file. If the files + * does not exist, create a new key and write it to the file. If the + * contents of the file are invalid the old file is deleted and a + * fresh key is created. + * + * @param filename name of file to use for storage + * @param cont function to call when done (or on errors) + * @param cont_cls closure for 'cont' + * @return handle to abort operation, NULL on fatal errors (cont will not be called if NULL is returned) + */ +struct GNUNET_CRYPTO_RsaKeyGenerationContext * +GNUNET_CRYPTO_rsa_key_create_start (const char *filename, + GNUNET_CRYPTO_RsaKeyCallback cont, + void *cont_cls) +{ + struct GNUNET_CRYPTO_RsaKeyGenerationContext *gc; + struct GNUNET_CRYPTO_RsaPrivateKey *pk; + const char *weak_random; + + if (NULL != (pk = try_read_key (filename))) + { + /* quick happy ending: key already exists! */ + gc = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_RsaKeyGenerationContext)); + gc->pk = pk; + gc->cont = cont; + gc->cont_cls = cont_cls; + gc->read_task = GNUNET_SCHEDULER_add_now (&async_return_key, + gc); + return gc; + } + gc = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_RsaKeyGenerationContext)); + gc->filename = GNUNET_strdup (filename); + gc->cont = cont; + gc->cont_cls = cont_cls; + gc->gnunet_rsa_out = GNUNET_DISK_pipe (GNUNET_NO, + GNUNET_NO, + GNUNET_NO, + GNUNET_YES); + if (NULL == gc->gnunet_rsa_out) + { + GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "pipe"); + GNUNET_free (gc->filename); + GNUNET_free (gc); + return NULL; + } + weak_random = NULL; + if (GNUNET_YES == + GNUNET_CRYPTO_random_is_weak ()) + weak_random = "-w"; + gc->gnunet_rsa = GNUNET_OS_start_process (GNUNET_NO, + GNUNET_OS_INHERIT_STD_ERR, + NULL, + gc->gnunet_rsa_out, + "gnunet-rsa", + "gnunet-rsa", + gc->filename, + weak_random, + NULL); + if (NULL == gc->gnunet_rsa) + { + GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "fork"); + GNUNET_DISK_pipe_close (gc->gnunet_rsa_out); + GNUNET_free (gc->filename); + GNUNET_free (gc); + return NULL; + } + GNUNET_assert (GNUNET_OK == + GNUNET_DISK_pipe_close_end (gc->gnunet_rsa_out, + GNUNET_DISK_PIPE_END_WRITE)); + gc->read_task = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, + GNUNET_DISK_pipe_handle (gc->gnunet_rsa_out, + GNUNET_DISK_PIPE_END_READ), + &check_key_generation_completion, + gc); + return gc; +} + + +/** + * Abort RSA key generation. + * + * @param gc key generation context to abort + */ +void +GNUNET_CRYPTO_rsa_key_create_stop (struct GNUNET_CRYPTO_RsaKeyGenerationContext *gc) +{ + if (GNUNET_SCHEDULER_NO_TASK != gc->read_task) + { + GNUNET_SCHEDULER_cancel (gc->read_task); + gc->read_task = GNUNET_SCHEDULER_NO_TASK; + } + if (NULL != gc->gnunet_rsa) + { + (void) GNUNET_OS_process_kill (gc->gnunet_rsa, SIGKILL); + GNUNET_break (GNUNET_OK == + GNUNET_OS_process_wait (gc->gnunet_rsa)); + GNUNET_OS_process_destroy (gc->gnunet_rsa); + GNUNET_DISK_pipe_close (gc->gnunet_rsa_out); + } + + if (NULL != gc->filename) + { + if (0 != UNLINK (gc->filename)) + GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", gc->filename); + GNUNET_free (gc->filename); + } + if (NULL != gc->pk) + GNUNET_CRYPTO_rsa_key_free (gc->pk); + GNUNET_free (gc); +} + + +/** + * Setup a key file for a peer given the name of the * configuration file (!). This function is used so that * at a later point code can be certain that reading a - * hostkey is fast (for example in time-dependent testcases). + * key is fast (for example in time-dependent testcases). * * @param cfg_name name of the configuration file to use */ void -GNUNET_CRYPTO_setup_hostkey (const char *cfg_name) +GNUNET_CRYPTO_rsa_setup_hostkey (const char *cfg_name) { struct GNUNET_CONFIGURATION_Handle *cfg; struct GNUNET_CRYPTO_RsaPrivateKey *pk; @@ -832,15 +1140,14 @@ GNUNET_CRYPTO_rsa_encrypt (const void *block, size_t size, { gcry_sexp_t result; gcry_sexp_t data; - struct GNUNET_CRYPTO_RsaPrivateKey *pubkey; + gcry_sexp_t psexp; gcry_mpi_t val; gcry_mpi_t rval; size_t isize; size_t erroff; - GNUNET_assert (size <= sizeof (GNUNET_HashCode)); - pubkey = public2PrivateKey (publicKey); - if (pubkey == NULL) + GNUNET_assert (size <= sizeof (struct GNUNET_HashCode)); + if (! (psexp = decode_public_key (publicKey))) return GNUNET_SYSERR; isize = size; GNUNET_assert (0 == @@ -849,10 +1156,9 @@ GNUNET_CRYPTO_rsa_encrypt (const void *block, size_t size, gcry_sexp_build (&data, &erroff, "(data (flags pkcs1)(value %m))", val)); gcry_mpi_release (val); - GNUNET_assert (0 == gcry_pk_encrypt (&result, data, pubkey->sexp)); + GNUNET_assert (0 == gcry_pk_encrypt (&result, data, psexp)); gcry_sexp_release (data); - GNUNET_CRYPTO_rsa_key_free (pubkey); - + gcry_sexp_release (psexp); GNUNET_assert (0 == key_from_sexp (&rval, result, "rsa", "a")); gcry_sexp_release (result); isize = sizeof (struct GNUNET_CRYPTO_RsaEncryptedData); @@ -867,7 +1173,7 @@ GNUNET_CRYPTO_rsa_encrypt (const void *block, size_t size, /** - * Decrypt a given block with the hostkey. + * Decrypt a given block with the key. * * @param key the key with which to decrypt this block * @param block the data to decrypt, encoded as returned by encrypt @@ -920,6 +1226,39 @@ GNUNET_CRYPTO_rsa_decrypt (const struct GNUNET_CRYPTO_RsaPrivateKey * key, /** + * Convert the data specified in the given purpose argument to an + * S-expression suitable for signature operations. + * + * @param purpose data to convert + * @return converted s-expression + */ +static gcry_sexp_t +data_to_pkcs1 (const struct GNUNET_CRYPTO_RsaSignaturePurpose *purpose) +{ + struct GNUNET_HashCode hc; + size_t bufSize; + gcry_sexp_t data; + + GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc); +#define FORMATSTRING "(4:data(5:flags5:pkcs1)(4:hash6:sha51264:0123456789012345678901234567890123456789012345678901234567890123))" + bufSize = strlen (FORMATSTRING) + 1; + { + char buff[bufSize]; + + memcpy (buff, FORMATSTRING, bufSize); + memcpy (&buff + [bufSize - + strlen + ("0123456789012345678901234567890123456789012345678901234567890123))") + - 1], &hc, sizeof (struct GNUNET_HashCode)); + GNUNET_assert (0 == gcry_sexp_new (&data, buff, bufSize, 0)); + } +#undef FORMATSTRING + return data; +} + + +/** * Sign a given block. * * @param key private key to use for the signing @@ -936,22 +1275,8 @@ GNUNET_CRYPTO_rsa_sign (const struct GNUNET_CRYPTO_RsaPrivateKey *key, gcry_sexp_t data; size_t ssize; gcry_mpi_t rval; - GNUNET_HashCode hc; - char *buff; - int bufSize; - GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc); -#define FORMATSTRING "(4:data(5:flags5:pkcs1)(4:hash6:sha51264:0123456789012345678901234567890123456789012345678901234567890123))" - bufSize = strlen (FORMATSTRING) + 1; - buff = GNUNET_malloc (bufSize); - memcpy (buff, FORMATSTRING, bufSize); - memcpy (&buff - [bufSize - - strlen - ("0123456789012345678901234567890123456789012345678901234567890123))") - - 1], &hc, sizeof (GNUNET_HashCode)); - GNUNET_assert (0 == gcry_sexp_new (&data, buff, bufSize, 0)); - GNUNET_free (buff); + data = data_to_pkcs1 (purpose); GNUNET_assert (0 == gcry_pk_sign (&result, data, key->sexp)); gcry_sexp_release (data); GNUNET_assert (0 == key_from_sexp (&rval, result, "rsa", "s")); @@ -987,16 +1312,12 @@ GNUNET_CRYPTO_rsa_verify (uint32_t purpose, gcry_sexp_t sigdata; size_t size; gcry_mpi_t val; - struct GNUNET_CRYPTO_RsaPrivateKey *hostkey; - GNUNET_HashCode hc; - char *buff; - int bufSize; + gcry_sexp_t psexp; size_t erroff; int rc; if (purpose != ntohl (validate->purpose)) return GNUNET_SYSERR; /* purpose mismatch */ - GNUNET_CRYPTO_hash (validate, ntohl (validate->size), &hc); size = sizeof (struct GNUNET_CRYPTO_RsaSignature); GNUNET_assert (0 == gcry_mpi_scan (&val, GCRYMPI_FMT_USG, @@ -1005,25 +1326,15 @@ GNUNET_CRYPTO_rsa_verify (uint32_t purpose, gcry_sexp_build (&sigdata, &erroff, "(sig-val(rsa(s %m)))", val)); gcry_mpi_release (val); - bufSize = strlen (FORMATSTRING) + 1; - buff = GNUNET_malloc (bufSize); - memcpy (buff, FORMATSTRING, bufSize); - memcpy (&buff - [strlen (FORMATSTRING) - - strlen - ("0123456789012345678901234567890123456789012345678901234567890123))")], - &hc, sizeof (GNUNET_HashCode)); - GNUNET_assert (0 == gcry_sexp_new (&data, buff, bufSize, 0)); - GNUNET_free (buff); - hostkey = public2PrivateKey (publicKey); - if (hostkey == NULL) + data = data_to_pkcs1 (validate); + if (! (psexp = decode_public_key (publicKey))) { gcry_sexp_release (data); gcry_sexp_release (sigdata); return GNUNET_SYSERR; } - rc = gcry_pk_verify (sigdata, data, hostkey->sexp); - GNUNET_CRYPTO_rsa_key_free (hostkey); + rc = gcry_pk_verify (sigdata, data, psexp); + gcry_sexp_release (psexp); gcry_sexp_release (data); gcry_sexp_release (sigdata); if (rc) diff --git a/src/util/disk.c b/src/util/disk.c index cba0d44..5cd85b6 100644 --- a/src/util/disk.c +++ b/src/util/disk.c @@ -47,7 +47,7 @@ -#if defined(LINUX) || defined(CYGWIN) +#if defined(LINUX) || defined(CYGWIN) || defined(GNU) #include <sys/vfs.h> #else #if defined(SOMEBSD) || defined(DARWIN) @@ -274,9 +274,7 @@ GNUNET_DISK_file_seek (const struct GNUNET_DISK_FileHandle * h, OFF_T offset, LARGE_INTEGER new_pos; BOOL b; - static DWORD t[] = {[GNUNET_DISK_SEEK_SET] = FILE_BEGIN, - [GNUNET_DISK_SEEK_CUR] = FILE_CURRENT,[GNUNET_DISK_SEEK_END] = FILE_END - }; + static DWORD t[] = { FILE_BEGIN, FILE_CURRENT, FILE_END }; li.QuadPart = offset; b = SetFilePointerEx (h->h, li, &new_pos, t[whence]); @@ -287,9 +285,7 @@ GNUNET_DISK_file_seek (const struct GNUNET_DISK_FileHandle * h, OFF_T offset, } return (OFF_T) new_pos.QuadPart; #else - static int t[] = {[GNUNET_DISK_SEEK_SET] = SEEK_SET, - [GNUNET_DISK_SEEK_CUR] = SEEK_CUR,[GNUNET_DISK_SEEK_END] = SEEK_END - }; + static int t[] = { SEEK_SET, SEEK_CUR, SEEK_END }; return lseek (h->fd, offset, t[whence]); #endif @@ -393,21 +389,15 @@ GNUNET_DISK_file_get_identifiers (const char *filename, uint64_t * dev, /** - * Create an (empty) temporary file on disk. If the given name is not - * an absolute path, the current 'TMPDIR' will be prepended. In any case, - * 6 random characters will be appended to the name to create a unique - * filename. + * Create the name for a temporary file or directory from a template. * - * @param t component to use for the name; - * does NOT contain "XXXXXX" or "/tmp/". - * @return NULL on error, otherwise name of fresh - * file on disk in directory for temporary files + * @param t template (without XXXXX or "/tmp/") + * @return name ready for passing to 'mktemp' or 'mkdtemp', NULL on error */ -char * -GNUNET_DISK_mktemp (const char *t) +static char * +mktemp_name (const char *t) { const char *tmpdir; - int fd; char *tmpl; char *fn; @@ -419,7 +409,12 @@ GNUNET_DISK_mktemp (const char *t) { /* FIXME: This uses system codepage on W32, not UTF-8 */ tmpdir = getenv ("TMPDIR"); - tmpdir = tmpdir ? tmpdir : "/tmp"; + if (NULL == tmpdir) + tmpdir = getenv ("TMP"); + if (NULL == tmpdir) + tmpdir = getenv ("TEMP"); + if (NULL == tmpdir) + tmpdir = "/tmp"; GNUNET_asprintf (&tmpl, "%s/%s%s", tmpdir, t, "XXXXXX"); } else @@ -438,12 +433,120 @@ GNUNET_DISK_mktemp (const char *t) #else fn = tmpl; #endif - /* FIXME: why is this not MKSTEMP()? This function is implemented in plibc. - * CG: really? If I put MKSTEMP here, I get a compilation error... - * It will assume that fn is UTF-8-encoded, if compiled with UTF-8 support. - */ - fd = mkstemp (fn); - if (fd == -1) + return fn; +} + + +#if WINDOWS +static char * +mkdtemp (char *fn) +{ + char *random_fn; + char *tfn; + + while (1) + { + tfn = GNUNET_strdup (fn); + random_fn = _mktemp (tfn); + if (NULL == random_fn) + { + GNUNET_free (tfn); + return NULL; + } + /* FIXME: assume fn to be UTF-8-encoded and do the right thing */ + if (0 == CreateDirectoryA (tfn, NULL)) + { + DWORD error = GetLastError (); + GNUNET_free (tfn); + if (ERROR_ALREADY_EXISTS == error) + continue; + return NULL; + } + break; + } + strcpy (fn, tfn); + return fn; +} +#endif + +/** + * Create an (empty) temporary directory on disk. If the given name is not + * an absolute path, the current 'TMPDIR' will be prepended. In any case, + * 6 random characters will be appended to the name to create a unique + * filename. + * + * @param t component to use for the name; + * does NOT contain "XXXXXX" or "/tmp/". + * @return NULL on error, otherwise name of fresh + * file on disk in directory for temporary files + */ +char * +GNUNET_DISK_mkdtemp (const char *t) +{ + char *fn; + + fn = mktemp_name (t); + if (fn != mkdtemp (fn)) + { + LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "mkstemp", fn); + GNUNET_free (fn); + return NULL; + } + return fn; +} + + +/** + * Move a file out of the way (create a backup) by + * renaming it to "orig.NUM~" where NUM is the smallest + * number that is not used yet. + * + * @param fil name of the file to back up + */ +void +GNUNET_DISK_file_backup (const char *fil) +{ + size_t slen; + char *target; + unsigned int num; + + slen = strlen (fil) + 20; + target = GNUNET_malloc (slen); + num = 0; + do + { + GNUNET_snprintf (target, slen, + "%s.%u~", + fil, + num++); + } while (0 == access (target, F_OK)); + if (0 != rename (fil, target)) + GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, + "rename", + fil); + GNUNET_free (target); +} + + +/** + * Create an (empty) temporary file on disk. If the given name is not + * an absolute path, the current 'TMPDIR' will be prepended. In any case, + * 6 random characters will be appended to the name to create a unique + * filename. + * + * @param t component to use for the name; + * does NOT contain "XXXXXX" or "/tmp/". + * @return NULL on error, otherwise name of fresh + * file on disk in directory for temporary files + */ +char * +GNUNET_DISK_mktemp (const char *t) +{ + int fd; + char *fn; + + fn = mktemp_name (t); + if (-1 == (fd = mkstemp (fn))) { LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "mkstemp", fn); GNUNET_free (fn); @@ -515,17 +618,19 @@ GNUNET_DISK_get_blocks_available (const char *part) /** - * Test if "fil" is a directory. - * Will not print an error message if the directory - * does not exist. Will log errors if GNUNET_SYSERR is - * returned (i.e., a file exists with the same name). + * Test if "fil" is a directory and listable. Optionally, also check if the + * directory is readable. Will not print an error message if the directory does + * not exist. Will log errors if GNUNET_SYSERR is returned (i.e., a file exists + * with the same name). * * @param fil filename to test - * @return GNUNET_YES if yes, GNUNET_NO if not, GNUNET_SYSERR if it - * does not exist + * @param is_readable GNUNET_YES to additionally check if "fil" is readable; + * GNUNET_NO to disable this check + * @return GNUNET_YES if yes, GNUNET_NO if not; GNUNET_SYSERR if it + * does not exist or stat'ed */ int -GNUNET_DISK_directory_test (const char *fil) +GNUNET_DISK_directory_test (const char *fil, int is_readable) { struct stat filestat; int ret; @@ -534,18 +639,23 @@ GNUNET_DISK_directory_test (const char *fil) if (ret != 0) { if (errno != ENOENT) - { LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "stat", fil); - return GNUNET_SYSERR; - } - return GNUNET_NO; + return GNUNET_SYSERR; } if (!S_ISDIR (filestat.st_mode)) + { + LOG (GNUNET_ERROR_TYPE_WARNING, + "A file already exits with the same name %s\n", fil); return GNUNET_NO; - if (ACCESS (fil, R_OK | X_OK) < 0) + } + if (GNUNET_YES == is_readable) + ret = ACCESS (fil, R_OK | X_OK); + else + ret = ACCESS (fil, X_OK); + if (ret < 0) { LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "access", fil); - return GNUNET_SYSERR; + return GNUNET_NO; } return GNUNET_YES; } @@ -587,7 +697,7 @@ GNUNET_DISK_file_test (const char *fil) GNUNET_free (rdir); return GNUNET_NO; } - if (ACCESS (rdir, R_OK) < 0) + if (ACCESS (rdir, F_OK) < 0) { LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "access", rdir); GNUNET_free (rdir); @@ -607,8 +717,9 @@ int GNUNET_DISK_directory_create (const char *dir) { char *rdir; - int len; - int pos; + unsigned int len; + unsigned int pos; + unsigned int pos2; int ret = GNUNET_OK; rdir = GNUNET_STRINGS_filename_expand (dir); @@ -638,18 +749,45 @@ GNUNET_DISK_directory_create (const char *dir) pos = 3; /* strlen("C:\\") */ } #endif + /* Check which low level directories already exist */ + pos2 = len; + rdir[len] = DIR_SEPARATOR; + while (pos <= pos2) + { + if (DIR_SEPARATOR == rdir[pos2]) + { + rdir[pos2] = '\0'; + ret = GNUNET_DISK_directory_test (rdir, GNUNET_NO); + if (GNUNET_NO == ret) + { + GNUNET_free (rdir); + return GNUNET_SYSERR; + } + rdir[pos2] = DIR_SEPARATOR; + if (GNUNET_YES == ret) + { + pos2++; + break; + } + } + pos2--; + } + rdir[len] = '\0'; + if (pos < pos2) + pos = pos2; + /* Start creating directories */ while (pos <= len) { if ((rdir[pos] == DIR_SEPARATOR) || (pos == len)) { rdir[pos] = '\0'; - ret = GNUNET_DISK_directory_test (rdir); - if (ret == GNUNET_SYSERR) + ret = GNUNET_DISK_directory_test (rdir, GNUNET_NO); + if (GNUNET_NO == ret) { GNUNET_free (rdir); return GNUNET_SYSERR; } - if (ret == GNUNET_NO) + if (GNUNET_SYSERR == ret) { #ifndef MINGW ret = mkdir (rdir, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); /* 755 */ @@ -728,7 +866,7 @@ GNUNET_DISK_file_read (const struct GNUNET_DISK_FileHandle * h, void *result, #ifdef MINGW DWORD bytesRead; - if (h->type != GNUNET_PIPE) + if (h->type != GNUNET_DISK_HANLDE_TYPE_PIPE) { if (!ReadFile (h->h, result, len, &bytesRead, NULL)) { @@ -770,7 +908,8 @@ GNUNET_DISK_file_read (const struct GNUNET_DISK_FileHandle * h, void *result, */ ssize_t GNUNET_DISK_file_read_non_blocking (const struct GNUNET_DISK_FileHandle * h, - void *result, size_t len) + void *result, + size_t len) { if (h == NULL) { @@ -781,7 +920,7 @@ GNUNET_DISK_file_read_non_blocking (const struct GNUNET_DISK_FileHandle * h, #ifdef MINGW DWORD bytesRead; - if (h->type != GNUNET_PIPE) + if (h->type != GNUNET_DISK_HANLDE_TYPE_PIPE) { if (!ReadFile (h->h, result, len, &bytesRead, NULL)) { @@ -818,10 +957,14 @@ GNUNET_DISK_file_read_non_blocking (const struct GNUNET_DISK_FileHandle * h, /* set to non-blocking, read, then set back */ flags = fcntl (h->fd, F_GETFL); if (0 == (flags & O_NONBLOCK)) - fcntl (h->fd, F_SETFL, flags | O_NONBLOCK); + (void) fcntl (h->fd, F_SETFL, flags | O_NONBLOCK); ret = read (h->fd, result, len); if (0 == (flags & O_NONBLOCK)) - fcntl (h->fd, F_SETFL, flags); + { + int eno = errno; + (void) fcntl (h->fd, F_SETFL, flags); + errno = eno; + } return ret; #endif } @@ -871,7 +1014,7 @@ GNUNET_DISK_file_write (const struct GNUNET_DISK_FileHandle * h, #ifdef MINGW DWORD bytesWritten; - if (h->type != GNUNET_PIPE) + if (h->type != GNUNET_DISK_HANLDE_TYPE_PIPE) { if (!WriteFile (h->h, buffer, n, &bytesWritten, NULL)) { @@ -984,10 +1127,10 @@ GNUNET_DISK_file_write_blocking (const struct GNUNET_DISK_FileHandle * h, /* set to blocking, write, then set back */ flags = fcntl (h->fd, F_GETFL); if (0 != (flags & O_NONBLOCK)) - fcntl (h->fd, F_SETFL, flags - O_NONBLOCK); + (void) fcntl (h->fd, F_SETFL, flags - O_NONBLOCK); ret = write (h->fd, buffer, n); if (0 == (flags & O_NONBLOCK)) - fcntl (h->fd, F_SETFL, flags); + (void) fcntl (h->fd, F_SETFL, flags); return ret; #endif } @@ -1274,34 +1417,34 @@ remove_helper (void *unused, const char *fn) * caution. * * - * @param fileName the file to remove + * @param filename the file to remove * @return GNUNET_OK on success, GNUNET_SYSERR on error */ int -GNUNET_DISK_directory_remove (const char *fileName) +GNUNET_DISK_directory_remove (const char *filename) { struct stat istat; - if (0 != LSTAT (fileName, &istat)) + if (0 != LSTAT (filename, &istat)) return GNUNET_NO; /* file may not exist... */ - CHMOD (fileName, S_IWUSR | S_IRUSR | S_IXUSR); - if (UNLINK (fileName) == 0) + (void) CHMOD (filename, S_IWUSR | S_IRUSR | S_IXUSR); + if (UNLINK (filename) == 0) return GNUNET_OK; if ((errno != EISDIR) && /* EISDIR is not sufficient in all cases, e.g. * sticky /tmp directory may result in EPERM on BSD. * So we also explicitly check "isDirectory" */ - (GNUNET_YES != GNUNET_DISK_directory_test (fileName))) + (GNUNET_YES != GNUNET_DISK_directory_test (filename, GNUNET_YES))) { - LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "rmdir", fileName); + LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "rmdir", filename); return GNUNET_SYSERR; } if (GNUNET_SYSERR == - GNUNET_DISK_directory_scan (fileName, &remove_helper, NULL)) + GNUNET_DISK_directory_scan (filename, &remove_helper, NULL)) return GNUNET_SYSERR; - if (0 != RMDIR (fileName)) + if (0 != RMDIR (filename)) { - LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "rmdir", fileName); + LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "rmdir", filename); return GNUNET_SYSERR; } return GNUNET_OK; @@ -1635,9 +1778,12 @@ GNUNET_DISK_file_open (const char *fn, enum GNUNET_DISK_OpenFlags flags, h = INVALID_HANDLE_VALUE; if (h == INVALID_HANDLE_VALUE) { + int err; SetErrnoFromWinError (GetLastError ()); - LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "open", expfn); + err = errno; + LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_INFO, "open", expfn); GNUNET_free (expfn); + errno = err; return NULL; } @@ -1655,7 +1801,7 @@ GNUNET_DISK_file_open (const char *fn, enum GNUNET_DISK_OpenFlags flags, ret = GNUNET_malloc (sizeof (struct GNUNET_DISK_FileHandle)); #ifdef MINGW ret->h = h; - ret->type = GNUNET_DISK_FILE; + ret->type = GNUNET_DISK_HANLDE_TYPE_FILE; #else ret->fd = fd; #endif @@ -1702,6 +1848,57 @@ GNUNET_DISK_file_close (struct GNUNET_DISK_FileHandle *h) /** + * Get a handle from a native FD. + * + * @param fd native file descriptor + * @return file handle corresponding to the descriptor + */ +struct GNUNET_DISK_FileHandle * +GNUNET_DISK_get_handle_from_native (FILE *fd) +{ + struct GNUNET_DISK_FileHandle *fh; + int fno; +#if MINGW + intptr_t osfh; +#endif + + fno = fileno (fd); + if (-1 == fno) + return NULL; + +#if MINGW + osfh = _get_osfhandle (fno); + if (INVALID_HANDLE_VALUE == (HANDLE) osfh) + return NULL; +#endif + + fh = GNUNET_malloc (sizeof (struct GNUNET_DISK_FileHandle)); + +#if MINGW + fh->h = (HANDLE) osfh; + /* Assume it to be a pipe. TODO: use some kind of detection + * function to figure out handle type. + * Note that we can't make it overlapped if it isn't already. + * (ReOpenFile() is only available in 2003/Vista). + * The process that opened this file in the first place (usually a parent + * process, if this is stdin/stdout/stderr) must make it overlapped, + * otherwise we're screwed, as selecting on non-overlapped handle + * will block. + */ + fh->type = GNUNET_DISK_HANLDE_TYPE_PIPE; + fh->oOverlapRead = GNUNET_malloc (sizeof (OVERLAPPED)); + fh->oOverlapWrite = GNUNET_malloc (sizeof (OVERLAPPED)); + fh->oOverlapRead->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); + fh->oOverlapWrite->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); +#else + fh->fd = fno; +#endif + + return fh; +} + + +/** * Construct full path to a file inside of the private * directory used by GNUnet. Also creates the corresponding * directory. If the resulting name is supposed to be @@ -1966,7 +2163,8 @@ create_selectable_pipe (PHANDLE read_pipe_ptr, PHANDLE write_pipe_ptr, /* Default to error. */ *read_pipe_ptr = *write_pipe_ptr = INVALID_HANDLE_VALUE; - HANDLE read_pipe = INVALID_HANDLE_VALUE, write_pipe = INVALID_HANDLE_VALUE; + HANDLE read_pipe; + HANDLE write_pipe; /* Ensure that there is enough pipe buffer space for atomic writes. */ if (psize < PIPE_BUF) @@ -2147,8 +2345,8 @@ GNUNET_DISK_pipe (int blocking_read, int blocking_write, int inherit_read, int i CloseHandle (p->fd[1]->h); p->fd[1]->h = tmp_handle; - p->fd[0]->type = GNUNET_PIPE; - p->fd[1]->type = GNUNET_PIPE; + p->fd[0]->type = GNUNET_DISK_HANLDE_TYPE_PIPE; + p->fd[1]->type = GNUNET_DISK_HANLDE_TYPE_PIPE; p->fd[0]->oOverlapRead = GNUNET_malloc (sizeof (OVERLAPPED)); p->fd[0]->oOverlapWrite = GNUNET_malloc (sizeof (OVERLAPPED)); @@ -2250,17 +2448,17 @@ GNUNET_DISK_pipe_from_fd (int blocking_read, int blocking_write, int fd[2]) } #else if (fd[0] >= 0) - p->fd[0]->h = _get_osfhandle (fd[0]); + p->fd[0]->h = (HANDLE) _get_osfhandle (fd[0]); else p->fd[0]->h = INVALID_HANDLE_VALUE; if (fd[1] >= 0) - p->fd[1]->h = _get_osfhandle (fd[1]); + p->fd[1]->h = (HANDLE) _get_osfhandle (fd[1]); else p->fd[1]->h = INVALID_HANDLE_VALUE; if (p->fd[0]->h != INVALID_HANDLE_VALUE) { - p->fd[0]->type = GNUNET_PIPE; + p->fd[0]->type = GNUNET_DISK_HANLDE_TYPE_PIPE; p->fd[0]->oOverlapRead = GNUNET_malloc (sizeof (OVERLAPPED)); p->fd[0]->oOverlapWrite = GNUNET_malloc (sizeof (OVERLAPPED)); p->fd[0]->oOverlapRead->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); @@ -2269,7 +2467,7 @@ GNUNET_DISK_pipe_from_fd (int blocking_read, int blocking_write, int fd[2]) if (p->fd[1]->h != INVALID_HANDLE_VALUE) { - p->fd[1]->type = GNUNET_PIPE; + p->fd[1]->type = GNUNET_DISK_HANLDE_TYPE_PIPE; p->fd[1]->oOverlapRead = GNUNET_malloc (sizeof (OVERLAPPED)); p->fd[1]->oOverlapWrite = GNUNET_malloc (sizeof (OVERLAPPED)); p->fd[1]->oOverlapRead->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); diff --git a/src/util/getopt.c b/src/util/getopt.c index 572e534..64e4341 100644 --- a/src/util/getopt.c +++ b/src/util/getopt.c @@ -238,45 +238,7 @@ strlen (const char *); static int first_nonopt; static int last_nonopt; -#ifdef _LIBC -/* Bash 2.0 gives us an environment variable containing flags - indicating ARGV elements that should not be considered arguments. */ - -/* Defined in getopt_init.c */ -extern char *__getopt_nonoption_flags; - -static int nonoption_flags_max_len; -static int nonoption_flags_len; - -static int original_argc; -static char *const *original_argv; - -extern pid_t __libc_pid; - -/* Make sure the environment variable bash 2.0 puts in the environment - is valid for the getopt call we must make sure that the ARGV passed - to getopt is that one passed to the process. */ -static void GNUNET_UNUSED -store_args_and_env (int argc, char *const *argv) -{ - /* XXX This is no good solution. We should rather copy the args so - * that we can compare them later. But we must not use malloc(3). */ - original_argc = argc; - original_argv = argv; -} - -text_set_element (__libc_subinit, store_args_and_env); - -#define SWAP_FLAGS(ch1, ch2) \ - if (nonoption_flags_len > 0) \ - { \ - char __tmp = __getopt_nonoption_flags[ch1]; \ - __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \ - __getopt_nonoption_flags[ch2] = __tmp; \ - } -#else /* !_LIBC */ #define SWAP_FLAGS(ch1, ch2) -#endif /* _LIBC */ /* Exchange two adjacent subsequences of ARGV. One subsequence is elements [first_nonopt,last_nonopt) @@ -305,29 +267,6 @@ exchange (char **argv) * It leaves the longer segment in the right place overall, * but it consists of two parts that need to be swapped next. */ -#ifdef _LIBC - /* First make sure the handling of the `__getopt_nonoption_flags' - * string can work normally. Our top argument must be in the range - * of the string. */ - if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len) - { - /* We must extend the array. The user plays games with us and - * presents new arguments. */ - char *new_str = malloc (top + 1); - - if (new_str == NULL) - nonoption_flags_len = nonoption_flags_max_len = 0; - else - { - memcpy (new_str, __getopt_nonoption_flags, nonoption_flags_max_len); - memset (&new_str[nonoption_flags_max_len], '\0', - top + 1 - nonoption_flags_max_len); - nonoption_flags_max_len = top + 1; - __getopt_nonoption_flags = new_str; - } - } -#endif - while (top > middle && middle > bottom) { if (top - middle > middle - bottom) @@ -410,41 +349,9 @@ _getopt_initialize (int argc, else ordering = PERMUTE; -#ifdef _LIBC - if (posixly_correct == NULL && argc == original_argc && argv == original_argv) - { - if (nonoption_flags_max_len == 0) - { - if (__getopt_nonoption_flags == NULL || - __getopt_nonoption_flags[0] == '\0') - nonoption_flags_max_len = -1; - else - { - const char *orig_str = __getopt_nonoption_flags; - int len = nonoption_flags_max_len = strlen (orig_str); - - if (nonoption_flags_max_len < argc) - nonoption_flags_max_len = argc; - __getopt_nonoption_flags = (char *) malloc (nonoption_flags_max_len); - if (__getopt_nonoption_flags == NULL) - nonoption_flags_max_len = -1; - else - { - memcpy (__getopt_nonoption_flags, orig_str, len); - memset (&__getopt_nonoption_flags[len], '\0', - nonoption_flags_max_len - len); - } - } - } - nonoption_flags_len = nonoption_flags_max_len; - } - else - nonoption_flags_len = 0; -#endif - return optstring; } - + /* Scan elements of ARGV (whose length is ARGC) for option characters given in OPTSTRING. @@ -523,13 +430,7 @@ GN_getopt_internal (int argc, char *const *argv, const char *optstring, * Either it does not have option syntax, or there is an environment flag * from the shell indicating it is not an option. The later information * is only used when the used in the GNU libc. */ -#ifdef _LIBC -#define NONOPTION_P (argv[GNoptind][0] != '-' || argv[GNoptind][1] == '\0' \ - || (GNoptind < nonoption_flags_len \ - && __getopt_nonoption_flags[GNoptind] == '1')) -#else #define NONOPTION_P (argv[GNoptind][0] != '-' || argv[GNoptind][1] == '\0') -#endif if (nextchar == NULL || *nextchar == '\0') { @@ -866,8 +767,7 @@ GN_getopt_internal (int argc, char *const *argv, const char *optstring, else { if (GNopterr) - FPRINTF (stderr, _("\ -%s: option `-W %s' does not allow an argument\n"), argv[0], pfound->name); + FPRINTF (stderr, _("%s: option `-W %s' does not allow an argument\n"), argv[0], pfound->name); nextchar += strlen (nextchar); return '?'; @@ -1039,8 +939,10 @@ GNUNET_GETOPT_run (const char *binaryOptions, GNUNET_free (shorts); GNUNET_free (long_options); - if (cont == GNUNET_SYSERR) - return GNUNET_SYSERR; + if (cont != GNUNET_OK) + { + return cont; + } return GNoptind; } diff --git a/src/util/getopt_helpers.c b/src/util/getopt_helpers.c index a31080f..5940c3f 100644 --- a/src/util/getopt_helpers.c +++ b/src/util/getopt_helpers.c @@ -26,7 +26,7 @@ #include "platform.h" #include "gnunet_common.h" -#include "gnunet_getopt_lib.h" +#include "gnunet_util_lib.h" #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) @@ -38,7 +38,7 @@ * @param scls additional closure (points to version string) * @param option name of the option * @param value not used (NULL) - * @return GNUNET_SYSERR (do not continue) + * @return GNUNET_NO (do not continue, not an error) */ int GNUNET_GETOPT_print_version_ (struct GNUNET_GETOPT_CommandLineProcessorContext @@ -48,7 +48,7 @@ GNUNET_GETOPT_print_version_ (struct GNUNET_GETOPT_CommandLineProcessorContext const char *version = scls; printf ("%s v%s\n", ctx->binaryName, version); - return GNUNET_SYSERR; + return GNUNET_NO; } @@ -62,7 +62,7 @@ GNUNET_GETOPT_print_version_ (struct GNUNET_GETOPT_CommandLineProcessorContext * @param scls additional closure (points to about text) * @param option name of the option * @param value not used (NULL) - * @return GNUNET_SYSERR (do not continue) + * @return GNUNET_NO (do not continue, not an error) */ int GNUNET_GETOPT_format_help_ (struct GNUNET_GETOPT_CommandLineProcessorContext @@ -152,7 +152,7 @@ OUTER: printf ("Report bugs to gnunet-developers@gnu.org.\n" "GNUnet home page: http://www.gnu.org/software/gnunet/\n" "General help using GNU software: http://www.gnu.org/gethelp/\n"); - return GNUNET_SYSERR; + return GNUNET_NO; } @@ -212,7 +212,7 @@ GNUNET_GETOPT_set_one (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, * A pointer to this function should be passed as part of the * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options * of this type. It should be followed by a pointer to a value of - * type 'char *'. + * type 'char *', which will be allocated with the requested string. * * @param ctx command line processing context * @param scls additional closure (will point to the 'char *', @@ -263,6 +263,36 @@ GNUNET_GETOPT_set_ulong (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, /** + * Set an option of type 'struct GNUNET_TIME_Relative' from the command line. + * A pointer to this function should be passed as part of the + * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options + * of this type. It should be followed by a pointer to a value of + * type 'struct GNUNET_TIME_Relative'. + * + * @param ctx command line processing context + * @param scls additional closure (will point to the 'struct GNUNET_TIME_Relative') + * @param option name of the option + * @param value actual value of the option as a string. + * @return GNUNET_OK if parsing the value worked + */ +int +GNUNET_GETOPT_set_relative_time (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx, + void *scls, const char *option, const char *value) +{ + struct GNUNET_TIME_Relative *val = scls; + + if (GNUNET_OK != + GNUNET_STRINGS_fancy_time_to_relative (value, + val)) + { + FPRINTF (stderr, _("You must pass relative time to the `%s' option.\n"), option); + return GNUNET_SYSERR; + } + return GNUNET_OK; +} + + +/** * Set an option of type 'unsigned int' from the command line. * A pointer to this function should be passed as part of the * 'struct GNUNET_GETOPT_CommandLineOption' array to initialize options diff --git a/src/util/gnunet-config.c b/src/util/gnunet-config.c new file mode 100644 index 0000000..e1aa94a --- /dev/null +++ b/src/util/gnunet-config.c @@ -0,0 +1,184 @@ +/* + This file is part of GNUnet. + (C) 2012 Christian Grothoff (and other contributing authors) + + GNUnet 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 3, or (at your + option) any later version. + + GNUnet 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 GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/** + * @file util/gnunet-config.c + * @brief tool to access and manipulate GNUnet configuration files + * @author Christian Grothoff + */ +#include "platform.h" +#include "gnunet_util_lib.h" + + +/** + * Name of the section + */ +static char *section; + +/** + * Name of the option + */ +static char *option; + +/** + * Value to set + */ +static char *value; + +/** + * Treat option as a filename. + */ +static int is_filename; + +/** + * Return value from 'main'. + */ +static int ret; + + +/** + * Print each option in a given section. + * + * @param cls closure + * @param section name of the section + * @param option name of the option + * @param value value of the option + */ +static void +print_option (void *cls, const char *section, + const char *option, + const char *value) +{ + fprintf (stdout, + "%s = %s\n", option, value); +} + + +/** + * Main function that will be run by the scheduler. + * + * @param cls closure + * @param args remaining command-line arguments + * @param cfgfile name of the configuration file used (for saving, can be NULL!) + * @param cfg configuration + */ +static void +run (void *cls, char *const *args, const char *cfgfile, + const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + struct GNUNET_CONFIGURATION_Handle *out; + + if (NULL == section) + { + fprintf (stderr, _("--section argument is required\n")); + ret = 1; + return; + } + + if (NULL == value) + { + if (NULL == option) + { + GNUNET_CONFIGURATION_iterate_section_values (cfg, section, + &print_option, NULL); + } + else + { + if (is_filename) + { + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_filename (cfg, section, option, &value)) + { + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, + section, option); + ret = 3; + return; + } + } + else + { + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_string (cfg, section, option, &value)) + { + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, + section, option); + ret = 3; + return; + } + } + fprintf (stdout, "%s\n", value); + } + } + else + { + if (NULL == option) + { + fprintf (stderr, _("--option argument required to set value\n")); + ret = 1; + return; + } + out = GNUNET_CONFIGURATION_dup (cfg); + GNUNET_CONFIGURATION_set_value_string (out, section, option, value); + if (GNUNET_OK != + GNUNET_CONFIGURATION_write (out, cfgfile)) + ret = 2; + GNUNET_CONFIGURATION_destroy (out); + return; + } +} + + +/** + * Program to manipulate configuration files. + * + * @param argc number of arguments from the command line + * @param argv command line arguments + * @return 0 ok, 1 on error + */ +int +main (int argc, char *const *argv) +{ + static const struct GNUNET_GETOPT_CommandLineOption options[] = { + { 'f', "filename", NULL, + gettext_noop ("obtain option of value as a filename (with $-expansion)"), + 0, &GNUNET_GETOPT_set_one, &is_filename }, + { 's', "section", "SECTION", + gettext_noop ("name of the section to access"), + 1, &GNUNET_GETOPT_set_string, §ion }, + { 'o', "option", "OPTION", + gettext_noop ("name of the option to access"), + 1, &GNUNET_GETOPT_set_string, &option }, + { 'V', "value", "VALUE", + gettext_noop ("value to set"), + 1, &GNUNET_GETOPT_set_string, &value }, + GNUNET_GETOPT_OPTION_END + }; + if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) + return 2; + + ret = (GNUNET_OK == + GNUNET_PROGRAM_run (argc, argv, "gnunet-config [OPTIONS]", + gettext_noop ("Manipulate GNUnet configuration files"), + options, &run, NULL)) ? 0 : ret; + GNUNET_free ((void*) argv); + return ret; +} + +/* end of gnunet-config.c */ diff --git a/src/util/gnunet-ecc.c b/src/util/gnunet-ecc.c new file mode 100644 index 0000000..b19fc19 --- /dev/null +++ b/src/util/gnunet-ecc.c @@ -0,0 +1,249 @@ +/* + This file is part of GNUnet. + (C) 2012 Christian Grothoff (and other contributing authors) + + GNUnet 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 3, or (at your + option) any later version. + + GNUnet 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 GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/** + * @file util/gnunet-ecc.c + * @brief tool to manipulate ECC key files + * @author Christian Grothoff + */ +#include "platform.h" +#include "gnunet_util_lib.h" +#include "gnunet_testing_lib.h" +#include <gcrypt.h> + + +/** + * Flag for printing public key. + */ +static int print_public_key; + +/** + * Flag for printing hash of public key. + */ +static int print_peer_identity; + +/** + * Flag for printing short hash of public key. + */ +static int print_short_identity; + +/** + * Use weak random number generator for key generation. + */ +static int weak_random; + +/** + * Option set to create a bunch of keys at once. + */ +static unsigned int make_keys; + +/** + * The private information of an ECC key pair. + * NOTE: this must match the definition in crypto_ksk.c and crypto_ecc.c! + */ +struct GNUNET_CRYPTO_EccPrivateKey +{ + gcry_sexp_t sexp; +}; + + +/** + * Create a new private key. Caller must free return value. + * + * @return fresh private key + */ +static struct GNUNET_CRYPTO_EccPrivateKey * +ecc_key_create () +{ + struct GNUNET_CRYPTO_EccPrivateKey *ret; + gcry_sexp_t s_key; + gcry_sexp_t s_keyparam; + + GNUNET_assert (0 == + gcry_sexp_build (&s_keyparam, NULL, + "(genkey(ecc(nbits %d)(ecc-use-e 3:257)))", + 2048)); + GNUNET_assert (0 == gcry_pk_genkey (&s_key, s_keyparam)); + gcry_sexp_release (s_keyparam); +#if EXTRA_CHECKS + GNUNET_assert (0 == gcry_pk_testkey (s_key)); +#endif + ret = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccPrivateKey)); + ret->sexp = s_key; + return ret; +} + + +/** + * Create a flat file with a large number of key pairs for testing. + */ +static void +create_keys (const char *fn) +{ + FILE *f; + struct GNUNET_CRYPTO_EccPrivateKey *pk; + struct GNUNET_CRYPTO_EccPrivateKeyBinaryEncoded *enc; + + if (NULL == (f = fopen (fn, "w+"))) + { + fprintf (stderr, + _("Failed to open `%s': %s\n"), + fn, + STRERROR (errno)); + return; + } + fprintf (stderr, + _("Generating %u keys, please wait"), + make_keys); + while (0 < make_keys--) + { + fprintf (stderr, + "."); + if (NULL == (pk = ecc_key_create ())) + { + GNUNET_break (0); + break; + } + enc = GNUNET_CRYPTO_ecc_encode_key (pk); + if (htons (enc->size) != fwrite (enc, 1, htons (enc->size), f)) + { + fprintf (stderr, + _("\nFailed to write to `%s': %s\n"), + fn, + STRERROR (errno)); + GNUNET_CRYPTO_ecc_key_free (pk); + GNUNET_free (enc); + break; + } + GNUNET_CRYPTO_ecc_key_free (pk); + GNUNET_free (enc); + } + if (0 == make_keys) + fprintf (stderr, + _("Finished!\n")); + fclose (f); +} + + +/** + * Main function that will be run by the scheduler. + * + * @param cls closure + * @param args remaining command-line arguments + * @param cfgfile name of the configuration file used (for saving, can be NULL!) + * @param cfg configuration + */ +static void +run (void *cls, char *const *args, const char *cfgfile, + const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + struct GNUNET_CRYPTO_EccPrivateKey *pk; + struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded pub; + struct GNUNET_PeerIdentity pid; + + if (NULL == args[0]) + { + fprintf (stderr, _("No hostkey file specified on command line\n")); + return; + } + if (0 != weak_random) + GNUNET_CRYPTO_random_disable_entropy_gathering (); + if (make_keys > 0) + { + create_keys (args[0]); + return; + } + pk = GNUNET_CRYPTO_ecc_key_create_from_file (args[0]); + if (NULL == pk) + return; + if (print_public_key) + { + char *s; + + GNUNET_CRYPTO_ecc_key_get_public (pk, &pub); + s = GNUNET_CRYPTO_ecc_public_key_to_string (&pub); + fprintf (stdout, "%s\n", s); + GNUNET_free (s); + } + if (print_peer_identity) + { + struct GNUNET_CRYPTO_HashAsciiEncoded enc; + + GNUNET_CRYPTO_ecc_key_get_public (pk, &pub); + GNUNET_CRYPTO_hash (&pub, sizeof (pub), &pid.hashPubKey); + GNUNET_CRYPTO_hash_to_enc (&pid.hashPubKey, &enc); + fprintf (stdout, "%s\n", enc.encoding); + } + if (print_short_identity) + { + struct GNUNET_CRYPTO_ShortHashAsciiEncoded enc; + struct GNUNET_CRYPTO_ShortHashCode sh; + + GNUNET_CRYPTO_ecc_key_get_public (pk, &pub); + GNUNET_CRYPTO_short_hash (&pub, sizeof (pub), &sh); + GNUNET_CRYPTO_short_hash_to_enc (&sh, &enc); + fprintf (stdout, "%s\n", enc.short_encoding); + } + GNUNET_CRYPTO_ecc_key_free (pk); +} + + +/** + * Program to manipulate ECC key files. + * + * @param argc number of arguments from the command line + * @param argv command line arguments + * @return 0 ok, 1 on error + */ +int +main (int argc, char *const *argv) +{ + static const struct GNUNET_GETOPT_CommandLineOption options[] = { + { 'g', "generate-keys", "COUNT", + gettext_noop ("create COUNT public-private key pairs (for testing)"), + 1, &GNUNET_GETOPT_set_uint, &make_keys }, + { 'p', "print-public-key", NULL, + gettext_noop ("print the public key in ASCII format"), + 0, &GNUNET_GETOPT_set_one, &print_public_key }, + { 'P', "print-peer-identity", NULL, + gettext_noop ("print the hash of the public key in ASCII format"), + 0, &GNUNET_GETOPT_set_one, &print_peer_identity }, + { 's', "print-short-identity", NULL, + gettext_noop ("print the short hash of the public key in ASCII format"), + 0, &GNUNET_GETOPT_set_one, &print_short_identity }, + { 'w', "weak-random", NULL, + gettext_noop ("use insecure, weak random number generator for key generation (for testing only)"), + 0, &GNUNET_GETOPT_set_one, &weak_random }, + GNUNET_GETOPT_OPTION_END + }; + int ret; + + if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) + return 2; + + ret = (GNUNET_OK == + GNUNET_PROGRAM_run (argc, argv, "gnunet-ecc [OPTIONS] keyfile", + gettext_noop ("Manipulate GNUnet private ECC key files"), + options, &run, NULL)) ? 0 : 1; + GNUNET_free ((void*) argv); + return ret; +} + +/* end of gnunet-ecc.c */ diff --git a/src/util/gnunet-resolver.c b/src/util/gnunet-resolver.c index 142dd0d..6cb6ac5 100644 --- a/src/util/gnunet-resolver.c +++ b/src/util/gnunet-resolver.c @@ -149,10 +149,17 @@ main (int argc, char *const *argv) 0, &GNUNET_GETOPT_set_one, &reverse }, GNUNET_GETOPT_OPTION_END }; - return (GNUNET_OK == - GNUNET_PROGRAM_run (argc, argv, "gnunet-resolver [hostname]", - gettext_noop ("Use build-in GNUnet stub resolver"), - options, &run, NULL)) ? 0 : 1; + int ret; + + if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) + return 2; + + ret = (GNUNET_OK == + GNUNET_PROGRAM_run (argc, argv, "gnunet-resolver [hostname]", + gettext_noop ("Use build-in GNUnet stub resolver"), + options, &run, NULL)) ? 0 : 1; + GNUNET_free ((void*) argv); + return ret; } /* end of gnunet-resolver.c */ diff --git a/src/util/gnunet-rsa.c b/src/util/gnunet-rsa.c index f3cd83a..917ee50 100644 --- a/src/util/gnunet-rsa.c +++ b/src/util/gnunet-rsa.c @@ -25,6 +25,8 @@ */ #include "platform.h" #include "gnunet_util_lib.h" +#include "gnunet_testing_lib.h" +#include <gcrypt.h> /** @@ -42,6 +44,112 @@ static int print_peer_identity; */ static int print_short_identity; +/** + * Use weak random number generator for key generation. + */ +static int weak_random; + +/** + * Option set to create a bunch of keys at once. + */ +static unsigned int make_keys; + +/** + * The private information of an RSA key pair. + * NOTE: this must match the definition in crypto_ksk.c and crypto_rsa.c! + */ +struct GNUNET_CRYPTO_RsaPrivateKey +{ + gcry_sexp_t sexp; +}; + + +/** + * Create a new private key. Caller must free return value. + * + * @return fresh private key + */ +static struct GNUNET_CRYPTO_RsaPrivateKey * +rsa_key_create () +{ + struct GNUNET_CRYPTO_RsaPrivateKey *ret; + gcry_sexp_t s_key; + gcry_sexp_t s_keyparam; + + GNUNET_assert (0 == + gcry_sexp_build (&s_keyparam, NULL, + "(genkey(rsa(nbits %d)(rsa-use-e 3:257)))", + 2048)); + GNUNET_assert (0 == gcry_pk_genkey (&s_key, s_keyparam)); + gcry_sexp_release (s_keyparam); +#if EXTRA_CHECKS + GNUNET_assert (0 == gcry_pk_testkey (s_key)); +#endif + ret = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_RsaPrivateKey)); + ret->sexp = s_key; + return ret; +} + + +/** + * Create a flat file with a large number of key pairs for testing. + */ +static void +create_keys (const char *fn) +{ + FILE *f; + struct GNUNET_CRYPTO_RsaPrivateKey *pk; + struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded *enc; + + if (NULL == (f = fopen (fn, "w+"))) + { + fprintf (stderr, + _("Failed to open `%s': %s\n"), + fn, + STRERROR (errno)); + return; + } + fprintf (stderr, + _("Generating %u keys, please wait"), + make_keys); + while (0 < make_keys--) + { + fprintf (stderr, + "."); + if (NULL == (pk = rsa_key_create ())) + { + GNUNET_break (0); + break; + } + enc = GNUNET_CRYPTO_rsa_encode_key (pk); + if (GNUNET_TESTING_HOSTKEYFILESIZE != htons (enc->len)) + { + /* sometimes we get a different key length because 'd' or 'u' start + with leading bits; skip those... */ + GNUNET_CRYPTO_rsa_key_free (pk); + GNUNET_free (enc); + make_keys++; + continue; + } + if (htons (enc->len) != fwrite (enc, 1, htons (enc->len), f)) + { + fprintf (stderr, + _("\nFailed to write to `%s': %s\n"), + fn, + STRERROR (errno)); + GNUNET_CRYPTO_rsa_key_free (pk); + GNUNET_free (enc); + break; + } + GNUNET_CRYPTO_rsa_key_free (pk); + GNUNET_free (enc); + } + if (0 == make_keys) + fprintf (stderr, + _("Finished!\n")); + fclose (f); +} + /** * Main function that will be run by the scheduler. @@ -64,7 +172,16 @@ run (void *cls, char *const *args, const char *cfgfile, fprintf (stderr, _("No hostkey file specified on command line\n")); return; } + if (0 != weak_random) + GNUNET_CRYPTO_random_disable_entropy_gathering (); + if (make_keys > 0) + { + create_keys (args[0]); + return; + } pk = GNUNET_CRYPTO_rsa_key_create_from_file (args[0]); + if (NULL == pk) + return; if (print_public_key) { char *s; @@ -98,16 +215,19 @@ run (void *cls, char *const *args, const char *cfgfile, /** - * The main function to obtain statistics in GNUnet. + * Program to manipulate RSA key files. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int -main (int argc, char *const *argv) +main (int argc, char *const*argv) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { + { 'g', "generate-keys", "COUNT", + gettext_noop ("create COUNT public-private key pairs (for testing)"), + 1, &GNUNET_GETOPT_set_uint, &make_keys }, { 'p', "print-public-key", NULL, gettext_noop ("print the public key in ASCII format"), 0, &GNUNET_GETOPT_set_one, &print_public_key }, @@ -117,12 +237,22 @@ main (int argc, char *const *argv) { 's', "print-short-identity", NULL, gettext_noop ("print the short hash of the public key in ASCII format"), 0, &GNUNET_GETOPT_set_one, &print_short_identity }, + { 'w', "weak-random", NULL, + gettext_noop ("use insecure, weak random number generator for key generation (for testing only)"), + 0, &GNUNET_GETOPT_set_one, &weak_random }, GNUNET_GETOPT_OPTION_END }; - return (GNUNET_OK == - GNUNET_PROGRAM_run (argc, argv, "gnunet-rsa [OPTIONS] keyfile", - gettext_noop ("Manipulate GNUnet private RSA key files"), - options, &run, NULL)) ? 0 : 1; + int ret; + + if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) + return 2; + + ret = (GNUNET_OK == + GNUNET_PROGRAM_run (argc, argv, "gnunet-rsa [OPTIONS] keyfile", + gettext_noop ("Manipulate GNUnet private RSA key files"), + options, &run, NULL)) ? 0 : 1; + GNUNET_free ((void*) argv); + return ret; } /* end of gnunet-rsa.c */ diff --git a/src/util/gnunet-service-resolver.c b/src/util/gnunet-service-resolver.c index 97eba6d..507ecf6 100644 --- a/src/util/gnunet-service-resolver.c +++ b/src/util/gnunet-service-resolver.c @@ -577,4 +577,19 @@ main (int argc, char *const *argv) return ret; } +#ifdef LINUX +#include <malloc.h> + +/** + * MINIMIZE heap size (way below 128k) since this process doesn't need much. + */ +void __attribute__ ((constructor)) GNUNET_ARM_memory_init () +{ + mallopt (M_TRIM_THRESHOLD, 4 * 1024); + mallopt (M_TOP_PAD, 1 * 1024); + malloc_trim (0); +} +#endif + + /* end of gnunet-service-resolver.c */ diff --git a/src/util/gnunet-uri.c b/src/util/gnunet-uri.c new file mode 100644 index 0000000..5ca1f4e --- /dev/null +++ b/src/util/gnunet-uri.c @@ -0,0 +1,184 @@ +/* + This file is part of GNUnet. + (C) 2012 Christian Grothoff (and other contributing authors) + + GNUnet 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 3, or (at your + option) any later version. + + GNUnet 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 GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/** + * @file util/gnunet-uri.c + * @brief tool to dispatch URIs to the appropriate GNUnet helper process + * @author Christian Grothoff + */ +#include "platform.h" +#include "gnunet_util_lib.h" + + +/** + * Global return value. + */ +static int ret = 1; + +/** + * Helper process we started. + */ +static struct GNUNET_OS_Process *p; + +/** + * Pipe used to communicate shutdown via signal. + */ +static struct GNUNET_DISK_PipeHandle *sigpipe; + + +/** + * Task triggered whenever we receive a SIGCHLD (child + * process died) or when user presses CTRL-C. + * + * @param cls closure, NULL + * @param tc scheduler context + */ +static void +maint_child_death (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + enum GNUNET_OS_ProcessStatusType type; + unsigned long code; + + if ( (GNUNET_OK == + GNUNET_OS_process_status (p, &type, &code)) && + (type == GNUNET_OS_PROCESS_EXITED) && + (0 == code) ) + ret = 0; + else + GNUNET_break (0 == GNUNET_OS_process_kill (p, SIGTERM)); + GNUNET_OS_process_destroy (p); +} + + +/** + * Main function that will be run by the scheduler. + * + * @param cls closure + * @param args remaining command-line arguments + * @param cfgfile name of the configuration file used (for saving, can be NULL!) + * @param cfg configuration + */ +static void +run (void *cls, char *const *args, const char *cfgfile, + const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + const char *uri; + const char *slash; + char *subsystem; + char *program; + GNUNET_SCHEDULER_TaskIdentifier rt; + + if (NULL == (uri = args[0])) + { + fprintf (stderr, _("No URI specified on command line\n")); + return; + } + if (0 != strncasecmp ("gnunet://", uri, strlen ("gnunet://"))) + { + fprintf (stderr, _("Invalid URI: does not start with `%s'\n"), + "gnunet://"); + return; + } + uri += strlen ("gnunet://"); + if (NULL == (slash = strchr (uri, '/'))) + { + fprintf (stderr, _("Invalid URI: fails to specify subsystem\n")); + return; + } + subsystem = GNUNET_strndup (uri, slash - uri); + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_string (cfg, + "uri", + subsystem, + &program)) + { + fprintf (stderr, _("No handler known for subsystem `%s'\n"), subsystem); + GNUNET_free (subsystem); + return; + } + GNUNET_free (subsystem); + rt = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, + GNUNET_DISK_pipe_handle (sigpipe, + GNUNET_DISK_PIPE_END_READ), + &maint_child_death, NULL); + p = GNUNET_OS_start_process (GNUNET_NO, 0, + NULL, NULL, + program, + program, + args[0], + NULL); + GNUNET_free (program); + if (NULL == p) + GNUNET_SCHEDULER_cancel (rt); +} + + +/** + * Signal handler called for SIGCHLD. Triggers the + * respective handler by writing to the trigger pipe. + */ +static void +sighandler_child_death () +{ + static char c; + int old_errno = errno; /* back-up errno */ + + GNUNET_break (1 == + GNUNET_DISK_file_write (GNUNET_DISK_pipe_handle + (sigpipe, GNUNET_DISK_PIPE_END_WRITE), + &c, sizeof (c))); + errno = old_errno; /* restore errno */ +} + + +/** + * The main function to handle gnunet://-URIs. + * + * @param argc number of arguments from the command line + * @param argv command line arguments + * @return 0 ok, 1 on error + */ +int +main (int argc, char *const *argv) +{ + static const struct GNUNET_GETOPT_CommandLineOption options[] = { + GNUNET_GETOPT_OPTION_END + }; + struct GNUNET_SIGNAL_Context *shc_chld; + int ret; + + if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) + return 2; + sigpipe = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO, GNUNET_NO, GNUNET_NO); + GNUNET_assert (sigpipe != NULL); + shc_chld = + GNUNET_SIGNAL_handler_install (GNUNET_SIGCHLD, &sighandler_child_death); + ret = GNUNET_PROGRAM_run (argc, argv, "gnunet-uri URI", + gettext_noop ("Perform default-actions for GNUnet URIs"), + options, &run, NULL); + GNUNET_SIGNAL_handler_uninstall (shc_chld); + shc_chld = NULL; + GNUNET_DISK_pipe_close (sigpipe); + sigpipe = NULL; + GNUNET_free ((void *) argv); + return (GNUNET_OK == ret) ? 0 : 1; +} + +/* end of gnunet-uri.c */ diff --git a/src/util/helper.c b/src/util/helper.c index 6a84ff3..0810fe1 100644 --- a/src/util/helper.c +++ b/src/util/helper.c @@ -109,6 +109,16 @@ struct GNUNET_HELPER_Handle struct GNUNET_SERVER_MessageStreamTokenizer *mst; /** + * The exception callback + */ + GNUNET_HELPER_ExceptionCallback exp_cb; + + /** + * The closure for callbacks + */ + void *cb_cls; + + /** * First message queued for transmission to helper. */ struct GNUNET_HELPER_SendHandle *sh_head; @@ -121,12 +131,12 @@ struct GNUNET_HELPER_Handle /** * Binary to run. */ - const char *binary_name; + char *binary_name; /** * NULL-terminated list of command-line arguments. */ - char *const *binary_argv; + char **binary_argv; /** * Task to read from the helper. @@ -142,6 +152,12 @@ struct GNUNET_HELPER_Handle * Restart task. */ GNUNET_SCHEDULER_TaskIdentifier restart_task; + + /** + * Does the helper support the use of a control pipe for signalling? + */ + int with_control_pipe; + }; @@ -244,20 +260,31 @@ helper_read (void *cls, _("Error reading from `%s': %s\n"), h->binary_name, STRERROR (errno)); + if (NULL != h->exp_cb) + { + h->exp_cb (h->cb_cls); + GNUNET_HELPER_stop (h); + return; + } stop_helper (h); /* Restart the helper */ h->restart_task = - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, - &restart_task, h); + GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &restart_task, h); return; } if (0 == t) { /* this happens if the helper is shut down via a signal, so it is not a "hard" error */ - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - _("Got 0 bytes from helper `%s' (EOF)\n"), + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Got 0 bytes from helper `%s' (EOF)\n", h->binary_name); + if (NULL != h->exp_cb) + { + h->exp_cb (h->cb_cls); + GNUNET_HELPER_stop (h); + return; + } stop_helper (h); /* Restart the helper */ h->restart_task = @@ -265,8 +292,8 @@ helper_read (void *cls, &restart_task, h); return; } - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - _("Got %u bytes from helper `%s'\n"), + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Got %u bytes from helper `%s'\n", (unsigned int) t, h->binary_name); h->read_task = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, @@ -277,6 +304,12 @@ helper_read (void *cls, GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to parse inbound message from helper `%s'\n"), h->binary_name); + if (NULL != h->exp_cb) + { + h->exp_cb (h->cb_cls); + GNUNET_HELPER_stop (h); + return; + } stop_helper (h); /* Restart the helper */ h->restart_task = @@ -306,18 +339,18 @@ start_helper (struct GNUNET_HELPER_Handle *h) &restart_task, h); return; } - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - _("Starting HELPER process `%s'\n"), + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Starting HELPER process `%s'\n", h->binary_name); h->fh_from_helper = GNUNET_DISK_pipe_handle (h->helper_out, GNUNET_DISK_PIPE_END_READ); h->fh_to_helper = GNUNET_DISK_pipe_handle (h->helper_in, GNUNET_DISK_PIPE_END_WRITE); h->helper_proc = - GNUNET_OS_start_process_vap (GNUNET_NO, - h->helper_in, h->helper_out, - h->binary_name, - h->binary_argv); + GNUNET_OS_start_process_vap (h->with_control_pipe, GNUNET_OS_INHERIT_STD_ERR, + h->helper_in, h->helper_out, + h->binary_name, + h->binary_argv); if (NULL == h->helper_proc) { /* failed to start process? try again later... */ @@ -354,27 +387,47 @@ restart_task (void *cls, /** - * @brief Starts a helper and begins reading from it + * Starts a helper and begins reading from it. The helper process is + * restarted when it dies except when it is stopped using GNUNET_HELPER_stop() + * or when the exp_cb callback is not NULL. * + * @param with_control_pipe does the helper support the use of a control pipe for signalling? * @param binary_name name of the binary to run * @param binary_argv NULL-terminated list of arguments to give when starting the binary (this * argument must not be modified by the client for - * the lifetime of the helper h) + * the lifetime of the helper handle) * @param cb function to call if we get messages from the helper - * @param cb_cls Closure for the callback - * @return the new H, NULL on error + * @param exp_cb the exception callback to call. Set this to NULL if the helper + * process has to be restarted automatically when it dies/crashes + * @param cb_cls closure for the above callback + * @return the new Handle, NULL on error */ -struct GNUNET_HELPER_Handle* -GNUNET_HELPER_start (const char *binary_name, +struct GNUNET_HELPER_Handle * +GNUNET_HELPER_start (int with_control_pipe, + const char *binary_name, char *const binary_argv[], - GNUNET_SERVER_MessageTokenizerCallback cb, void *cb_cls) + GNUNET_SERVER_MessageTokenizerCallback cb, + GNUNET_HELPER_ExceptionCallback exp_cb, + void *cb_cls) { - struct GNUNET_HELPER_Handle*h; - - h = GNUNET_malloc (sizeof (struct GNUNET_HELPER_Handle)); - h->binary_name = binary_name; - h->binary_argv = binary_argv; - h->mst = GNUNET_SERVER_mst_create (cb, cb_cls); + struct GNUNET_HELPER_Handle *h; + unsigned int c; + + h = GNUNET_malloc (sizeof (struct GNUNET_HELPER_Handle)); + h->with_control_pipe = with_control_pipe; + /* Lookup in libexec path only if we are starting gnunet helpers */ + if (NULL != strstr (binary_name, "gnunet")) + h->binary_name = GNUNET_OS_get_libexec_binary_path (binary_name); + else + h->binary_name = strdup (binary_name); + for (c = 0; NULL != binary_argv[c]; c++); + h->binary_argv = GNUNET_malloc (sizeof (char *) * (c + 1)); + for (c = 0; NULL != binary_argv[c]; c++) + h->binary_argv[c] = GNUNET_strdup (binary_argv[c]); + h->binary_argv[c] = NULL; + h->cb_cls = cb_cls; + h->mst = GNUNET_SERVER_mst_create (cb, h->cb_cls); + h->exp_cb = exp_cb; start_helper (h); return h; } @@ -389,7 +442,9 @@ void GNUNET_HELPER_stop (struct GNUNET_HELPER_Handle *h) { struct GNUNET_HELPER_SendHandle *sh; + unsigned int c; + h->exp_cb = NULL; /* signal pending writes that we were stopped */ while (NULL != (sh = h->sh_head)) { @@ -402,6 +457,10 @@ GNUNET_HELPER_stop (struct GNUNET_HELPER_Handle *h) } stop_helper (h); GNUNET_SERVER_mst_destroy (h->mst); + GNUNET_free (h->binary_name); + for (c = 0; h->binary_argv[c] != NULL; c++) + GNUNET_free (h->binary_argv[c]); + GNUNET_free (h->binary_argv); GNUNET_free (h); } @@ -440,6 +499,12 @@ helper_write (void *cls, _("Error writing to `%s': %s\n"), h->binary_name, STRERROR (errno)); + if (NULL != h->exp_cb) + { + h->exp_cb (h->cb_cls); + GNUNET_HELPER_stop (h); + return; + } stop_helper (h); /* Restart the helper */ h->restart_task = diff --git a/src/util/network.c b/src/util/network.c index 972f938..bea6bfb 100644 --- a/src/util/network.c +++ b/src/util/network.c @@ -22,12 +22,11 @@ * @file util/network.c * @brief basic, low-level networking interface * @author Nils Durner + * @author Christian Grothoff */ - #include "platform.h" -#include "gnunet_disk_lib.h" #include "disk.h" -#include "gnunet_container_lib.h" +#include "gnunet_util_lib.h" #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename) @@ -67,6 +66,77 @@ struct GNUNET_NETWORK_Handle }; +/** + * Test if the given protocol family is supported by this system. + * + * @param pf protocol family to test (PF_INET, PF_INET6, PF_UNIX) + * @return GNUNET_OK if the PF is supported + */ +int +GNUNET_NETWORK_test_pf (int pf) +{ + int s; + + s = socket (pf, SOCK_STREAM, 0); + if (-1 == s) + { + if (EAFNOSUPPORT == errno) + return GNUNET_NO; + fprintf (stderr, "Failed to create test socket: %s\n", STRERROR (errno)); + return GNUNET_SYSERR; + } +#if WINDOWS + closesocket (s); +#else + close (s); +#endif + return GNUNET_OK; +} + + +/** + * Given a unixpath that is too long (larger than UNIX_PATH_MAX), + * shorten it to an acceptable length while keeping it unique + * and making sure it remains a valid filename (if possible). + * + * @param unixpath long path, will be freed (or same pointer returned + * with moved 0-termination). + * @return shortened unixpath, NULL on error + */ +char * +GNUNET_NETWORK_shorten_unixpath (char *unixpath) +{ + struct sockaddr_un dummy; + size_t slen; + char *end; + struct GNUNET_CRYPTO_ShortHashCode sh; + struct GNUNET_CRYPTO_ShortHashAsciiEncoded ae; + size_t upm; + + upm = sizeof (dummy.sun_path); + slen = strlen (unixpath); + if (slen < upm) + return unixpath; /* no shortening required */ + GNUNET_CRYPTO_short_hash (unixpath, slen, &sh); + while (sizeof (struct GNUNET_CRYPTO_ShortHashAsciiEncoded) + + strlen (unixpath) >= upm) + { + if (NULL == (end = strrchr (unixpath, '/'))) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Unable to shorten unix path `%s' while keeping name unique\n"), + unixpath); + GNUNET_free (unixpath); + return NULL; + } + *end = '\0'; + } + GNUNET_CRYPTO_short_hash_to_enc (&sh, &ae); + strcat (unixpath, (char*) ae.short_encoding); + return unixpath; +} + + #ifndef FD_COPY #define FD_COPY(s, d) (memcpy ((d), (s), sizeof (fd_set))) #endif @@ -74,12 +144,13 @@ struct GNUNET_NETWORK_Handle /** * Set if a socket should use blocking or non-blocking IO. + * * @param fd socket * @param doBlock blocking mode * @return GNUNET_OK on success, GNUNET_SYSERR on error */ -static int -socket_set_blocking (struct GNUNET_NETWORK_Handle *fd, int doBlock) +int +GNUNET_NETWORK_socket_set_blocking (struct GNUNET_NETWORK_Handle *fd, int doBlock) { #if MINGW @@ -121,7 +192,6 @@ socket_set_blocking (struct GNUNET_NETWORK_Handle *fd, int doBlock) } -#ifndef MINGW /** * Make a socket non-inheritable to child processes * @@ -132,8 +202,8 @@ socket_set_blocking (struct GNUNET_NETWORK_Handle *fd, int doBlock) static int socket_set_inheritable (const struct GNUNET_NETWORK_Handle *h) { +#ifndef MINGW int i; - i = fcntl (h->fd, F_GETFD); if (i < 0) return GNUNET_SYSERR; @@ -142,9 +212,18 @@ socket_set_inheritable (const struct GNUNET_NETWORK_Handle *h) i |= FD_CLOEXEC; if (fcntl (h->fd, F_SETFD, i) < 0) return GNUNET_SYSERR; +#else + BOOL b; + SetLastError (0); + b = SetHandleInformation (h->fd, HANDLE_FLAG_INHERIT, 0); + if (!b) + { + SetErrnoFromWinsockError (WSAGetLastError ()); + return GNUNET_SYSERR; + } +#endif return GNUNET_OK; } -#endif #ifdef DARWIN @@ -224,11 +303,12 @@ initialize_network_handle (struct GNUNET_NETWORK_Handle *h, errno = EMFILE; return GNUNET_SYSERR; } +#endif if (GNUNET_OK != socket_set_inheritable (h)) LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "socket_set_inheritable"); -#endif - if (GNUNET_SYSERR == socket_set_blocking (h, GNUNET_NO)) + + if (GNUNET_SYSERR == GNUNET_NETWORK_socket_set_blocking (h, GNUNET_NO)) { GNUNET_break (0); GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (h)); @@ -817,6 +897,7 @@ void GNUNET_NETWORK_fdset_add (struct GNUNET_NETWORK_FDSet *dst, const struct GNUNET_NETWORK_FDSet *src) { +#ifndef MINGW int nfds; for (nfds = src->nsds; nfds > 0; nfds--) @@ -827,7 +908,18 @@ GNUNET_NETWORK_fdset_add (struct GNUNET_NETWORK_FDSet *dst, if (nfds + 1 > dst->nsds) dst->nsds = nfds + 1; } -#ifdef MINGW +#else + /* This is MinGW32-specific implementation that relies on the code that + * winsock2.h defines for FD_SET. Namely, it relies on FD_SET checking + * that fd being added is not already in the set. + * Also relies on us knowing what's inside fd_set (fd_count and fd_array). + */ + int i; + for (i = 0; i < src->sds.fd_count; i++) + FD_SET (src->sds.fd_array[i], &dst->sds); + if (src->nsds > dst->nsds) + dst->nsds = src->nsds; + GNUNET_CONTAINER_slist_append (dst->handles, src->handles); #endif } @@ -1087,13 +1179,47 @@ GNUNET_NETWORK_fdset_destroy (struct GNUNET_NETWORK_FDSet *fds) GNUNET_free (fds); } +#if MINGW +struct _select_params +{ + fd_set *r; + fd_set *w; + fd_set *e; + struct timeval *tv; + HANDLE wakeup; + HANDLE standby; + SOCKET wakeup_socket; + int status; +}; + +static DWORD WINAPI +_selector (LPVOID p) +{ + struct _select_params *sp = p; + int i; + while (1) + { + WaitForSingleObject (sp->standby, INFINITE); + ResetEvent (sp->standby); + sp->status = select (1, sp->r, sp->w, sp->e, sp->tv); + if (FD_ISSET (sp->wakeup_socket, sp->r)) + { + FD_CLR (sp->wakeup_socket, sp->r); + sp->status -= 1; + } + SetEvent (sp->wakeup); + } + return 0; +} +#endif + /** - * Check if sockets meet certain conditions - * @param rfds set of sockets to be checked for readability - * @param wfds set of sockets to be checked for writability - * @param efds set of sockets to be checked for exceptions + * Check if sockets or pipes meet certain conditions + * @param rfds set of sockets or pipes to be checked for readability + * @param wfds set of sockets or pipes to be checked for writability + * @param efds set of sockets or pipes to be checked for exceptions * @param timeout relative value when to return - * @return number of selected sockets, GNUNET_SYSERR on error + * @return number of selected sockets or pipes, GNUNET_SYSERR on error */ int GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds, @@ -1112,28 +1238,32 @@ GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds, int retcode = 0; DWORD ms_total = 0; - int nsock = 0; int nhandles = 0; - int nSockEvents = 0; - static HANDLE hEventRead = 0; - static HANDLE hEventWrite = 0; - static HANDLE hEventException = 0; static HANDLE hEventPipeWrite = 0; static HANDLE hEventReadReady = 0; + static struct _select_params sp; + static HANDLE select_thread = NULL; + static HANDLE select_finished_event = NULL; + static HANDLE select_standby_event = NULL; + static SOCKET select_wakeup_socket = -1; + static SOCKET select_send_socket = -1; + static struct timeval select_timeout; + int readPipes = 0; int writePipePos = 0; HANDLE handle_array[FD_SETSIZE + 2]; int returncode = -1; - DWORD newretcode = 0; int returnedpos = 0; struct GNUNET_CONTAINER_SList *handles_read; struct GNUNET_CONTAINER_SList *handles_write; struct GNUNET_CONTAINER_SList *handles_except; + int selectret = 0; + fd_set aread; fd_set awrite; fd_set aexcept; @@ -1195,11 +1325,11 @@ GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds, #endif ) { + GNUNET_break (0); LOG (GNUNET_ERROR_TYPE_ERROR, _ ("Fatal internal logic error, process hangs in `%s' (abort with CTRL-C)!\n"), "select"); - GNUNET_break (0); } #ifndef MINGW tv.tv_sec = timeout.rel_value / GNUNET_TIME_UNIT_SECONDS.rel_value; @@ -1218,7 +1348,14 @@ GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds, if (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value) ms_total = INFINITE; else + { ms_total = timeout.rel_value / GNUNET_TIME_UNIT_MILLISECONDS.rel_value; + if (timeout.rel_value / GNUNET_TIME_UNIT_MILLISECONDS.rel_value > 0xFFFFFFFFLL - 1) + { + GNUNET_break (0); + ms_total = 0xFFFFFFFF - 1; + } + } /* select() may be used as a portable way to sleep */ if (!(rfds || wfds || efds)) { @@ -1226,31 +1363,244 @@ GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds, return 0; } - /* Events for sockets */ - if (!hEventRead) - hEventRead = CreateEvent (NULL, TRUE, FALSE, NULL); + if (select_thread == NULL) + { + SOCKET select_listening_socket = -1; + struct sockaddr_in s_in; + int alen; + int res; + unsigned long p; + + select_standby_event = CreateEvent (NULL, TRUE, FALSE, NULL); + select_finished_event = CreateEvent (NULL, TRUE, FALSE, NULL); + + select_wakeup_socket = WSASocket (AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED); + + select_listening_socket = WSASocket (AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED); + + p = 1; + res = ioctlsocket (select_wakeup_socket, FIONBIO, &p); + + alen = sizeof (s_in); + s_in.sin_family = AF_INET; + s_in.sin_port = 0; + s_in.sin_addr.S_un.S_un_b.s_b1 = 127; + s_in.sin_addr.S_un.S_un_b.s_b2 = 0; + s_in.sin_addr.S_un.S_un_b.s_b3 = 0; + s_in.sin_addr.S_un.S_un_b.s_b4 = 1; + res = bind (select_listening_socket, (const struct sockaddr *) &s_in, sizeof (s_in)); + + res = getsockname (select_listening_socket, (struct sockaddr *) &s_in, &alen); + + res = listen (select_listening_socket, SOMAXCONN); + + res = connect (select_wakeup_socket, (const struct sockaddr *) &s_in, sizeof (s_in)); + + select_send_socket = accept (select_listening_socket, (struct sockaddr *) &s_in, &alen); + + closesocket (select_listening_socket); + + sp.wakeup = select_finished_event; + sp.standby = select_standby_event; + sp.wakeup_socket = select_wakeup_socket; + + select_thread = CreateThread (NULL, 0, _selector, &sp, 0, NULL); + } + + + handles_read = GNUNET_CONTAINER_slist_create (); + handles_write = GNUNET_CONTAINER_slist_create (); + handles_except = GNUNET_CONTAINER_slist_create (); + FD_ZERO (&aread); + FD_ZERO (&awrite); + FD_ZERO (&aexcept); +#if DEBUG_NETWORK + FD_ZERO (&bread); + FD_ZERO (&bwrite); + FD_ZERO (&bexcept); +#endif + if (rfds) + { + FD_COPY (&rfds->sds, &aread); +#if DEBUG_NETWORK + FD_COPY (&rfds->sds, &bread); +#endif + } + if (wfds) + { + FD_COPY (&wfds->sds, &awrite); +#if DEBUG_NETWORK + FD_COPY (&wfds->sds, &bwrite); +#endif + } + if (efds) + { + FD_COPY (&efds->sds, &aexcept); +#if DEBUG_NETWORK + FD_COPY (&efds->sds, &bexcept); +#endif + } + + /* Start by doing a fast check on sockets and pipes (without waiting). It is cheap, and is sufficient most of the time. + By profiling we detected that to be true in 90% of the cases. + */ + + /* Do the select now */ + select_timeout.tv_sec = 0; + select_timeout.tv_usec = 0; + + /* Copy all the writes to the except, so we can detect connect() errors */ + for (i = 0; i < awrite.fd_count; i++) + FD_SET (awrite.fd_array[i], &aexcept); + if (aread.fd_count > 0 || awrite.fd_count > 0 || aexcept.fd_count > 0) + selectret = select (1, (rfds != NULL) ? &aread : NULL, + (wfds != NULL) ? &awrite : NULL, &aexcept, &select_timeout); else - ResetEvent (hEventRead); + selectret = 0; + if (selectret == -1) + { + /* Throw an error early on, while we still have the context. */ + LOG (GNUNET_ERROR_TYPE_ERROR, "W32 select(%d, %d, %d) failed: %lu\n", + rfds ? aread.fd_count : 0, wfds ? awrite.fd_count : 0, aexcept.fd_count, GetLastError ()); + GNUNET_abort (); + } + + /* Check aexcept, add its contents to awrite + This is technically wrong (aexcept might have its own descriptors), we should + have checked that descriptors were in awrite originally before re-adding them from + aexcept. Luckily, GNUnet never uses aexcept for anything, so this does not become a problem (yet). */ + for (i = 0; i < aexcept.fd_count; i++) + FD_SET (aexcept.fd_array[i], &awrite); + + /* If our select returned something or is a 0-timed request, then also check the pipes and get out of here! */ + /* Sadly, it means code duplication :( */ + if ((selectret > 0) || (ms_total == 0)) + { + /* Read Pipes */ + if (rfds && read_handles) + { + struct GNUNET_CONTAINER_SList_Iterator i; + + for (i = GNUNET_CONTAINER_slist_begin (rfds->handles); + GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES; + GNUNET_CONTAINER_slist_next (&i)) + { + struct GNUNET_DISK_FileHandle *fh; + + fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,NULL); + if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE) + { + DWORD error; + BOOL bret; + + SetLastError (0); + DWORD waitstatus = 0; + bret = PeekNamedPipe (fh->h, NULL, 0, NULL, &waitstatus, NULL); + error = GetLastError (); + LOG (GNUNET_ERROR_TYPE_DEBUG, "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n", + i, fh->h, bret, waitstatus, error); + if (bret == 0) + { + /* TODO: either add more errors to this condition, or eliminate it + * entirely (failed to peek -> pipe is in serious trouble, should + * be selected as readable). + */ + if (error != ERROR_BROKEN_PIPE && error != ERROR_INVALID_HANDLE) + continue; + } + else if (waitstatus <= 0) + continue; + GNUNET_CONTAINER_slist_add (handles_read, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, + fh, sizeof (struct GNUNET_DISK_FileHandle)); + retcode++; + LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n", + fh, fh->h); + } + else + { + GNUNET_CONTAINER_slist_add (handles_read, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, + fh, sizeof (struct GNUNET_DISK_FileHandle)); + retcode++; + } + } + } + if (wfds && write_handles) + { + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Adding the write ready event to the array as %d\n", nhandles); + GNUNET_CONTAINER_slist_append (handles_write, wfds->handles); + retcode += write_handles; + } + if (efds && ex_handles) + { + struct GNUNET_CONTAINER_SList_Iterator i; + + for (i = GNUNET_CONTAINER_slist_begin (efds->handles); + GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES; + GNUNET_CONTAINER_slist_next (&i)) + { + struct GNUNET_DISK_FileHandle *fh; + DWORD dwBytes; + + fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i, NULL); + if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE) + { + if (PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL)) + continue; + GNUNET_CONTAINER_slist_add (handles_except, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, + fh, sizeof (struct GNUNET_DISK_FileHandle)); + retcode++; + } + } + } + + /* Add our select() result.*/ + if (selectret >= 0) + retcode += selectret; + + if (rfds) + { + GNUNET_NETWORK_fdset_zero (rfds); + if (selectret != -1) + GNUNET_NETWORK_fdset_copy_native (rfds, &aread, selectret); + GNUNET_CONTAINER_slist_append (rfds->handles, handles_read); + } + if (wfds) + { + GNUNET_NETWORK_fdset_zero (wfds); + if (selectret != -1) + GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, selectret); + GNUNET_CONTAINER_slist_append (wfds->handles, handles_write); + } + if (efds) + { + GNUNET_NETWORK_fdset_zero (efds); + if (selectret != -1) + GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, selectret); + GNUNET_CONTAINER_slist_append (efds->handles, handles_except); + } + GNUNET_CONTAINER_slist_destroy (handles_read); + GNUNET_CONTAINER_slist_destroy (handles_write); + GNUNET_CONTAINER_slist_destroy (handles_except); + + if (selectret == -1) + return -1; + return retcode; + } + + /* If we got this far, use slower implementation that is able to do a waiting select + on both sockets and pipes simultaneously */ + + /* Events for pipes */ if (!hEventReadReady) hEventReadReady = CreateEvent (NULL, TRUE, TRUE, NULL); - if (!hEventWrite) - hEventWrite = CreateEvent (NULL, TRUE, FALSE, NULL); - else - ResetEvent (hEventWrite); - if (!hEventException) - hEventException = CreateEvent (NULL, TRUE, FALSE, NULL); - else - ResetEvent (hEventException); - - /* Event for pipes */ if (!hEventPipeWrite) hEventPipeWrite = CreateEvent (NULL, TRUE, TRUE, NULL); readPipes = 0; writePipePos = -1; - handles_read = GNUNET_CONTAINER_slist_create (); - handles_write = GNUNET_CONTAINER_slist_create (); - handles_except = GNUNET_CONTAINER_slist_create (); + retcode = 0; + FD_ZERO (&aread); FD_ZERO (&awrite); FD_ZERO (&aexcept); @@ -1294,7 +1644,7 @@ GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds, fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i, NULL); - if (fh->type == GNUNET_PIPE) + if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE) { /* Read zero bytes to check the status of the pipe */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Reading 0 bytes from the pipe 0x%x\n", @@ -1355,7 +1705,7 @@ GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds, fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i, NULL); - if (fh->type == GNUNET_PIPE) + if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE) { if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL)) { @@ -1363,103 +1713,97 @@ GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, fh, sizeof (struct GNUNET_DISK_FileHandle)); - newretcode++; } } } } - if (nfds > 0) - { - if (rfds) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Adding the socket read event to the array as %d\n", nhandles); - handle_array[nhandles++] = hEventRead; - nSockEvents++; - for (i = 0; i < rfds->sds.fd_count; i++) - { - WSAEventSelect (rfds->sds.fd_array[i], hEventRead, - FD_ACCEPT | FD_READ | FD_CLOSE); - nsock++; - } - } - if (wfds) - { - int wakeup = 0; - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Adding the socket write event to the array as %d\n", nhandles); - handle_array[nhandles++] = hEventWrite; - nSockEvents++; - for (i = 0; i < wfds->sds.fd_count; i++) - { - DWORD error; - int status; + sp.status = 0; - status = send (wfds->sds.fd_array[i], NULL, 0, 0); - error = GetLastError (); - LOG (GNUNET_ERROR_TYPE_DEBUG, - "pre-send to the socket %d returned %d (%u)\n", i, status, error); - if (status == 0 || (error != WSAEWOULDBLOCK && error != WSAENOTCONN)) - wakeup = 1; - WSAEventSelect (wfds->sds.fd_array[i], hEventWrite, - FD_WRITE | FD_CONNECT | FD_CLOSE); - nsock++; - } - if (wakeup) - SetEvent (hEventWrite); - } - if (efds) + if (nfds > 0) + { + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Adding the socket event to the array as %d\n", nhandles); + handle_array[nhandles++] = select_finished_event; + if (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value) + sp.tv = NULL; + else { - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Adding the socket error event to the array as %d\n", nhandles); - handle_array[nhandles++] = hEventException; - nSockEvents++; - for (i = 0; i < efds->sds.fd_count; i++) - { - WSAEventSelect (efds->sds.fd_array[i], hEventException, - FD_OOB | FD_CLOSE); - nsock++; - } + select_timeout.tv_sec = timeout.rel_value / GNUNET_TIME_UNIT_SECONDS.rel_value; + select_timeout.tv_usec = 1000 * (timeout.rel_value - + (select_timeout.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value)); + sp.tv = &select_timeout; } + FD_SET (select_wakeup_socket, &aread); + sp.r = &aread; + sp.w = &awrite; + sp.e = &aexcept; + /* Failed connections cause sockets to be set in errorfds on W32, + * but on POSIX it should set them in writefds. + * First copy all awrite sockets to aexcept, later we'll + * check aexcept and set its contents in awrite as well + * Sockets are also set in errorfds when OOB data is available, + * but we don't use OOB data. + */ + for (i = 0; i < awrite.fd_count; i++) + FD_SET (awrite.fd_array[i], &aexcept); + ResetEvent (select_finished_event); + SetEvent (select_standby_event); } handle_array[nhandles] = NULL; - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Number nfds: %d, handles: %d, return code: %u will wait: %d ms\n", - nfds, nhandles, newretcode, ms_total); + LOG (GNUNET_ERROR_TYPE_DEBUG, "nfds: %d, handles: %d, will wait: %llu ms\n", + nfds, nhandles, (unsigned long long) ms_total); if (nhandles) + { returncode = WaitForMultipleObjects (nhandles, handle_array, FALSE, ms_total); - LOG (GNUNET_ERROR_TYPE_DEBUG, "WaitForMultipleObjects Returned : %d\n", - returncode); + LOG (GNUNET_ERROR_TYPE_DEBUG, "WaitForMultipleObjects Returned : %d\n", + returncode); + } + else if (nfds > 0) + { + i = (int) WaitForSingleObject (select_finished_event, INFINITE); + returncode = WAIT_TIMEOUT; + } + else + { + /* Shouldn't come this far. If it does - investigate. */ + GNUNET_assert (0); + } + + if (nfds > 0) + { + /* Don't wake up select-thread when delay is 0, it should return immediately + * and wake up by itself. + */ + if (ms_total != 0) + i = send (select_send_socket, (const char *) &returnedpos, 1, 0); + i = (int) WaitForSingleObject (select_finished_event, INFINITE); + LOG (GNUNET_ERROR_TYPE_DEBUG, "Finished waiting for the select thread: %d %d\n", i, sp.status); + if (ms_total != 0) + { + do + { + i = recv (select_wakeup_socket, (char *) &returnedpos, 1, 0); + } while (i == 1); + } + /* Check aexcept, add its contents to awrite */ + for (i = 0; i < aexcept.fd_count; i++) + FD_SET (aexcept.fd_array[i], &awrite); + } returnedpos = returncode - WAIT_OBJECT_0; LOG (GNUNET_ERROR_TYPE_DEBUG, "return pos is : %d\n", returnedpos); - /* FIXME: THIS LINE IS WRONG !! We should add to handles only handles that fired the events, not all ! */ - /* - * if(rfds) - * GNUNET_CONTAINER_slist_append (handles_read, rfds->handles); - */ if (nhandles && (returnedpos < nhandles)) { DWORD waitstatus; - /* Do the select */ - if (nfds) - { - struct timeval tvslice; - - tvslice.tv_sec = 0; - tvslice.tv_usec = 0; - retcode = select (nfds, &aread, &awrite, &aexcept, &tvslice); - if (retcode == -1) - retcode = 0; - LOG (GNUNET_ERROR_TYPE_DEBUG, "Select retcode : %d\n", retcode); - } - /* FIXME: <= writePipePos? Really? */ - if ((writePipePos != -1) && (returnedpos <= writePipePos)) + if (sp.status > 0) + retcode += sp.status; + + if ((writePipePos != -1) && (returnedpos < writePipePos)) { GNUNET_CONTAINER_slist_append (handles_write, wfds->handles); retcode += write_handles; @@ -1467,24 +1811,8 @@ GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds, } LOG (GNUNET_ERROR_TYPE_DEBUG, "ReadPipes is : %d\n", readPipes); /* We have some pipes ready for read. */ - /* FIXME: it is supposed to work !! Only choose the Pipes who fired the event, but it is not working */ - if (returnedpos < readPipes) { - /* - * for (i = 0; i < readPipes; i++) - * { - * waitstatus = WaitForSingleObject (handle_array[i], 0); - * LOG (GNUNET_ERROR_TYPE_DEBUG, "Read pipe %d wait status is : %d\n", i, waitstatus); - * if (waitstatus != WAIT_OBJECT_0) - * continue; - * GNUNET_CONTAINER_slist_add (handles_read, - * GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, - * readArray[i], sizeof (struct GNUNET_DISK_FileHandle)); - * retcode++; - * LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe\n"); - * } - */ for (i = 0; i < readPipes; i++) { DWORD error; @@ -1500,7 +1828,11 @@ GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds, i, readArray[i]->h, bret, waitstatus, error); if (bret == 0) { - if (error != ERROR_BROKEN_PIPE) + /* TODO: either add more errors to this condition, or eliminate it + * entirely (failed to peek -> pipe is in serious trouble, should + * be selected as readable). + */ + if (error != ERROR_BROKEN_PIPE && error != ERROR_INVALID_HANDLE) continue; } else if (waitstatus <= 0) @@ -1514,34 +1846,6 @@ GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds, readArray[i], readArray[i]->h); } } - waitstatus = WaitForSingleObject (hEventWrite, 0); - LOG (GNUNET_ERROR_TYPE_DEBUG, "Wait for the write event returned %d\n", - waitstatus); - if (waitstatus == WAIT_OBJECT_0) - { - for (i = 0; i < wfds->sds.fd_count; i++) - { - DWORD error; - int status; - int so_error = 0; - int sizeof_so_error = sizeof (so_error); - int gso_result = - getsockopt (wfds->sds.fd_array[i], SOL_SOCKET, SO_ERROR, - (char *) &so_error, &sizeof_so_error); - - status = send (wfds->sds.fd_array[i], NULL, 0, 0); - error = GetLastError (); - LOG (GNUNET_ERROR_TYPE_DEBUG, - "send to the socket %d returned %d (%u)\n", i, status, error); - if (status == 0 || (error != WSAEWOULDBLOCK && error != WSAENOTCONN) || - (status == -1 && gso_result == 0 && error == WSAENOTCONN && - so_error == WSAECONNREFUSED)) - { - FD_SET (wfds->sds.fd_array[i], &awrite); - retcode += 1; - } - } - } } if (!nhandles || (returnedpos >= nhandles)) LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning from _select() with nothing!\n"); @@ -1549,11 +1853,6 @@ GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds, { struct GNUNET_CONTAINER_SList_Iterator t; - for (i = 0; i < rfds->sds.fd_count; i++) - { - WSAEventSelect (rfds->sds.fd_array[i], hEventRead, 0); - nsock++; - } for (t = GNUNET_CONTAINER_slist_begin (rfds->handles); GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES; GNUNET_CONTAINER_slist_next (&t)) @@ -1562,12 +1861,12 @@ GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds, fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t, NULL); - if (fh->type == GNUNET_PIPE) + if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE) { CancelIo (fh->h); } } - LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing rfds\n"); + LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing rfds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : ""); GNUNET_NETWORK_fdset_zero (rfds); if (retcode != -1 && nhandles && (returnedpos < nhandles)) GNUNET_NETWORK_fdset_copy_native (rfds, &aread, retcode); @@ -1575,12 +1874,7 @@ GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds, } if (wfds) { - for (i = 0; i < wfds->sds.fd_count; i++) - { - WSAEventSelect (wfds->sds.fd_array[i], hEventWrite, 0); - nsock++; - } - LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing wfds\n"); + LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing wfds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : ""); GNUNET_NETWORK_fdset_zero (wfds); if (retcode != -1 && nhandles && (returnedpos < nhandles)) GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, retcode); @@ -1588,12 +1882,7 @@ GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds, } if (efds) { - for (i = 0; i < efds->sds.fd_count; i++) - { - WSAEventSelect (efds->sds.fd_array[i], hEventException, 0); - nsock++; - } - LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing efds\n"); + LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing efds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : ""); GNUNET_NETWORK_fdset_zero (efds); if (retcode != -1 && nhandles && (returnedpos < nhandles)) GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, retcode); @@ -1607,12 +1896,10 @@ GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds, { struct GNUNET_CONTAINER_SList_Iterator t; - for (i = 0; i < bread.fd_count; i++) + LOG (GNUNET_ERROR_TYPE_DEBUG, "rfds:\n"); + for (i = 0; i < rfds->sds.fd_count; i++) { - if (bread.fd_array[i] != 0) - LOG (GNUNET_ERROR_TYPE_DEBUG, "FD 0x%x is %s in rfds\n", - bread.fd_array[i], - (SAFE_FD_ISSET (bread.fd_array[i], rfds)) ? "SET" : "NOT SET"); + LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", rfds->sds.fd_array[i]); } for (t = GNUNET_CONTAINER_slist_begin (rfds->handles); GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES; @@ -1622,27 +1909,23 @@ GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds, fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t, NULL); - LOG (GNUNET_ERROR_TYPE_DEBUG, "FD 0x%x is SET in rfds\n", fh->h); + LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", fh->h); } } if (wfds) { - for (i = 0; i < bwrite.fd_count; i++) + LOG (GNUNET_ERROR_TYPE_DEBUG, "wfds:\n"); + for (i = 0; i < wfds->sds.fd_count; i++) { - if (bwrite.fd_array[i] != 0) - LOG (GNUNET_ERROR_TYPE_DEBUG, "FD 0x%x is %s in wfds\n", - bwrite.fd_array[i], - (SAFE_FD_ISSET (bwrite.fd_array[i], rfds)) ? "SET" : "NOT SET"); + LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", wfds->sds.fd_array[i]); } } if (efds) { - for (i = 0; i < bexcept.fd_count; i++) + LOG (GNUNET_ERROR_TYPE_DEBUG, "efds:\n"); + for (i = 0; i < efds->sds.fd_count; i++) { - if (bexcept.fd_array[i] != 0) - LOG (GNUNET_ERROR_TYPE_DEBUG, "FD 0x%x is %s in efds\n", - bexcept.fd_array[i], - (SAFE_FD_ISSET (bexcept.fd_array[i], rfds)) ? "SET" : "NOT SET"); + LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", efds->sds.fd_array[i]); } } LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning %d or 0\n", retcode); diff --git a/src/util/os_installation.c b/src/util/os_installation.c index e790ce1..e35f86c 100644 --- a/src/util/os_installation.c +++ b/src/util/os_installation.c @@ -27,12 +27,14 @@ #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <unistr.h> /* for u16_to_u8 */ #include "platform.h" #include "gnunet_common.h" #include "gnunet_configuration_lib.h" #include "gnunet_disk_lib.h" #include "gnunet_os_lib.h" +#include "gnunet_strings_lib.h" #if DARWIN #include <mach-o/ldsyms.h> #include <mach-o/dyld.h> @@ -45,6 +47,8 @@ #if LINUX /** * Try to determine path by reading /proc/PID/exe + * + * @return NULL on error */ static char * get_path_from_proc_maps () @@ -56,13 +60,12 @@ get_path_from_proc_maps () char *lgu; GNUNET_snprintf (fn, sizeof (fn), "/proc/%u/maps", getpid ()); - f = FOPEN (fn, "r"); - if (f == NULL) + if (NULL == (f = FOPEN (fn, "r"))) return NULL; while (NULL != fgets (line, sizeof (line), f)) { if ((1 == - SSCANF (line, "%*x-%*x %*c%*c%*c%*c %*x %*2u:%*2u %*u%*[ ]%s", dir)) && + SSCANF (line, "%*x-%*x %*c%*c%*c%*c %*x %*2u:%*2u %*u%*[ ]%1023s", dir)) && (NULL != (lgu = strstr (dir, "libgnunetutil")))) { lgu[0] = '\0'; @@ -74,8 +77,11 @@ get_path_from_proc_maps () return NULL; } + /** * Try to determine path by reading /proc/PID/exe + * + * @return NULL on error */ static char * get_path_from_proc_exe () @@ -95,6 +101,11 @@ get_path_from_proc_exe () lnk[size] = '\0'; while ((lnk[size] != '/') && (size > 0)) size--; + /* test for being in lib/gnunet/libexec/ */ + if ( (size > strlen ("/gnunet/libexec/")) && + (0 == strcmp ("/gnunet/libexec/", + &lnk[size - strlen ("/gnunet/libexec/")])) ) + size -= strlen ("gnunet/libexec/"); if ((size < 4) || (lnk[size - 4] != '/')) { /* not installed in "/bin/" -- binary path probably useless */ @@ -106,31 +117,132 @@ get_path_from_proc_exe () #endif #if WINDOWS + +static HINSTANCE dll_instance; + + +/* GNUNET_util_cl_init() in common_logging.c is preferred. + * This function is only for thread-local storage (not used in GNUnet) + * and hInstance saving. + */ +BOOL WINAPI +DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + switch (fdwReason) + { + case DLL_PROCESS_ATTACH: + dll_instance = hinstDLL; + break; + case DLL_THREAD_ATTACH: + break; + case DLL_THREAD_DETACH: + break; + case DLL_PROCESS_DETACH: + break; + } + return TRUE; +} + + /** * Try to determine path with win32-specific function + * + * @return NULL on error */ static char * get_path_from_module_filename () { - wchar_t path[4097]; - char upath[4097]; + size_t pathlen = 512; + DWORD real_pathlen; wchar_t *idx; - - GetModuleFileNameW (NULL, path, sizeof (path) - 1); - idx = path + wcslen (path); - while ((idx > path) && (*idx != L'\\') && (*idx != L'/')) + wchar_t *modulepath = NULL; + char *upath; + uint8_t *u8_string; + size_t u8_string_length; + + /* This braindead function won't tell us how much space it needs, so + * we start at 1024 and double the space up if it doesn't fit, until + * it fits, or we exceed the threshold. + */ + do + { + pathlen = pathlen * 2; + modulepath = GNUNET_realloc (modulepath, pathlen * sizeof (wchar_t)); + SetLastError (0); + real_pathlen = GetModuleFileNameW (dll_instance, modulepath, pathlen * sizeof (wchar_t)); + } while (real_pathlen >= pathlen && pathlen < 16*1024); + if (real_pathlen >= pathlen) + GNUNET_abort (); + /* To be safe */ + modulepath[real_pathlen] = '\0'; + + idx = modulepath + real_pathlen; + while ((idx > modulepath) && (*idx != L'\\') && (*idx != L'/')) idx--; *idx = L'\0'; - upath[0] = '\0'; - WideCharToMultiByte (CP_UTF8, 0, path, -1, upath, 4097, NULL, NULL); - return GNUNET_strdup (upath); + /* Now modulepath holds full path to the directory where libgnunetutil is. + * This directory should look like <GNUNET_PREFIX>/bin or <GNUNET_PREFIX>. + */ + if (wcschr (modulepath, L'/') || wcschr (modulepath, L'\\')) + { + /* At least one directory component (i.e. we're not in a root directory) */ + wchar_t *dirname = idx; + while ((dirname > modulepath) && (*dirname != L'\\') && (*dirname != L'/')) + dirname--; + *dirname = L'\0'; + if (dirname > modulepath) + { + dirname++; + /* Now modulepath holds full path to the parent directory of the directory + * where libgnunetutil is. + * dirname holds the name of the directory where libgnunetutil is. + */ + if (wcsicmp (dirname, L"bin") == 0) + { + /* pass */ + } + else + { + /* Roll back our changes to modulepath */ + dirname--; + *dirname = L'/'; + } + } + } + + /* modulepath is GNUNET_PREFIX */ + u8_string = u16_to_u8 (modulepath, wcslen (modulepath), NULL, &u8_string_length); + if (NULL == u8_string) + GNUNET_abort (); + + upath = GNUNET_malloc (u8_string_length + 1); + memcpy (upath, u8_string, u8_string_length); + upath[u8_string_length] = '\0'; + + free (u8_string); + GNUNET_free (modulepath); + + return upath; } #endif #if DARWIN +/** + * Signature of the '_NSGetExecutablePath" function. + * + * @param buf where to write the path + * @param number of bytes available in 'buf' + * @return 0 on success, otherwise desired number of bytes is stored in 'bufsize' + */ typedef int (*MyNSGetExecutablePathProto) (char *buf, size_t * bufsize); + +/** + * Try to obtain the path of our executable using '_NSGetExecutablePath'. + * + * @return NULL on error + */ static char * get_path_from_NSGetExecutablePath () { @@ -138,22 +250,19 @@ get_path_from_NSGetExecutablePath () char *path; size_t len; MyNSGetExecutablePathProto func; - int ret; path = NULL; - func = - (MyNSGetExecutablePathProto) dlsym (RTLD_DEFAULT, "_NSGetExecutablePath"); - if (!func) + if (NULL == (func = + (MyNSGetExecutablePathProto) dlsym (RTLD_DEFAULT, "_NSGetExecutablePath"))) return NULL; path = &zero; len = 0; /* get the path len, including the trailing \0 */ - func (path, &len); - if (len == 0) + (void) func (path, &len); + if (0 == len) return NULL; path = GNUNET_malloc (len); - ret = func (path, &len); - if (ret != 0) + if (0 != func (path, &len)) { GNUNET_free (path); return NULL; @@ -165,37 +274,42 @@ get_path_from_NSGetExecutablePath () return path; } + +/** + * Try to obtain the path of our executable using '_dyld_image' API. + * + * @return NULL on error + */ static char * get_path_from_dyld_image () { const char *path; - char *p, *s; - int i; + char *p; + char *s; + unsigned int i; int c; - p = NULL; c = _dyld_image_count (); for (i = 0; i < c; i++) { - if (_dyld_get_image_header (i) == &_mh_dylib_header) - { - path = _dyld_get_image_name (i); - if (path != NULL && strlen (path) > 0) - { - p = GNUNET_strdup (path); - s = p + strlen (p); - while ((s > p) && (*s != '/')) - s--; - s++; - *s = '\0'; - } - break; - } + if (_dyld_get_image_header (i) != &_mh_dylib_header) + continue; + path = _dyld_get_image_name (i); + if ( (NULL == path) || (0 == strlen (path)) ) + continue; + p = GNUNET_strdup (path); + s = p + strlen (p); + while ((s > p) && ('/' != *s)) + s--; + s++; + *s = '\0'; + return p; } - return p; + return NULL; } #endif + /** * Return the actual path to a file found in the current * PATH environment variable. @@ -212,11 +326,15 @@ get_path_from_PATH (const char *binary) char *buf; const char *p; - p = getenv ("PATH"); - if (p == NULL) + if (NULL == (p = getenv ("PATH"))) return NULL; +#if WINDOWS + /* On W32 look in CWD first. */ + GNUNET_asprintf (&path, ".%c%s", PATH_SEPARATOR, p); +#else path = GNUNET_strdup (p); /* because we write on it */ - buf = GNUNET_malloc (strlen (path) + 20); +#endif + buf = GNUNET_malloc (strlen (path) + strlen (binary) + 1 + 1); pos = path; while (NULL != (end = strchr (pos, PATH_SEPARATOR))) { @@ -232,7 +350,7 @@ get_path_from_PATH (const char *binary) pos = end + 1; } sprintf (buf, "%s/%s", pos, binary); - if (GNUNET_DISK_file_test (buf) == GNUNET_YES) + if (GNUNET_YES == GNUNET_DISK_file_test (buf)) { pos = GNUNET_strdup (pos); GNUNET_free (buf); @@ -244,17 +362,24 @@ get_path_from_PATH (const char *binary) return NULL; } + +/** + * Try to obtain the installation path using the "GNUNET_PREFIX" environment + * variable. + * + * @return NULL on error (environment variable not set) + */ static char * get_path_from_GNUNET_PREFIX () { const char *p; - p = getenv ("GNUNET_PREFIX"); - if (p != NULL) + if (NULL != (p = getenv ("GNUNET_PREFIX"))) return GNUNET_strdup (p); return NULL; } + /** * @brief get the path to GNUnet bin/ or lib/, prefering the lib/ path * @author Milan @@ -266,32 +391,28 @@ os_get_gnunet_path () { char *ret; - ret = get_path_from_GNUNET_PREFIX (); - if (ret != NULL) + if (NULL != (ret = get_path_from_GNUNET_PREFIX ())) return ret; #if LINUX - ret = get_path_from_proc_maps (); - if (ret != NULL) + if (NULL != (ret = get_path_from_proc_maps ())) + return ret; + /* try path *first*, before /proc/exe, as /proc/exe can be wrong */ + if (NULL != (ret = get_path_from_PATH ("gnunet-arm"))) return ret; - ret = get_path_from_proc_exe (); - if (ret != NULL) + if (NULL != (ret = get_path_from_proc_exe ())) return ret; #endif #if WINDOWS - ret = get_path_from_module_filename (); - if (ret != NULL) + if (NULL != (ret = get_path_from_module_filename ())) return ret; #endif #if DARWIN - ret = get_path_from_dyld_image (); - if (ret != NULL) + if (NULL != (ret = get_path_from_dyld_image ())) return ret; - ret = get_path_from_NSGetExecutablePath (); - if (ret != NULL) + if (NULL != (ret = get_path_from_NSGetExecutablePath ())) return ret; #endif - ret = get_path_from_PATH ("gnunet-arm"); - if (ret != NULL) + if (NULL != (ret = get_path_from_PATH ("gnunet-arm"))) return ret; /* other attempts here */ LOG (GNUNET_ERROR_TYPE_ERROR, @@ -301,7 +422,8 @@ os_get_gnunet_path () return NULL; } -/* + +/** * @brief get the path to current app's bin/ * @author Milan * @@ -310,22 +432,18 @@ os_get_gnunet_path () static char * os_get_exec_path () { - char *ret; + char *ret = NULL; - ret = NULL; #if LINUX - ret = get_path_from_proc_exe (); - if (ret != NULL) + if (NULL != (ret = get_path_from_proc_exe ())) return ret; #endif #if WINDOWS - ret = get_path_from_module_filename (); - if (ret != NULL) + if (NULL != (ret = get_path_from_module_filename ())) return ret; #endif #if DARWIN - ret = get_path_from_NSGetExecutablePath (); - if (ret != NULL) + if (NULL != (ret = get_path_from_NSGetExecutablePath ())) return ret; #endif /* other attempts here */ @@ -333,7 +451,6 @@ os_get_exec_path () } - /** * @brief get the path to a specific GNUnet installation directory or, * with GNUNET_IPK_SELF_PREFIX, the current running apps installation directory @@ -355,21 +472,21 @@ GNUNET_OS_installation_get_path (enum GNUNET_OS_InstallationPathKind dirkind) /* try to get GNUnet's bin/ or lib/, or if previous was unsuccessful some * guess for the current app */ - if (execpath == NULL) + if (NULL == execpath) execpath = os_get_gnunet_path (); - if (execpath == NULL) + if (NULL == execpath) return NULL; n = strlen (execpath); - if (n == 0) + if (0 == n) { /* should never happen, but better safe than sorry */ GNUNET_free (execpath); return NULL; } /* remove filename itself */ - while ((n > 1) && (execpath[n - 1] == DIR_SEPARATOR)) + while ((n > 1) && (DIR_SEPARATOR == execpath[n - 1])) execpath[--n] = '\0'; isbasedir = 1; @@ -377,7 +494,8 @@ GNUNET_OS_installation_get_path (enum GNUNET_OS_InstallationPathKind dirkind) ((0 == strcasecmp (&execpath[n - 5], "lib32")) || (0 == strcasecmp (&execpath[n - 5], "lib64")))) { - if (dirkind != GNUNET_OS_IPK_LIBDIR) + if ( (GNUNET_OS_IPK_LIBDIR != dirkind) && + (GNUNET_OS_IPK_LIBEXECDIR != dirkind) ) { /* strip '/lib32' or '/lib64' */ execpath[n - 5] = '\0'; @@ -408,8 +526,30 @@ GNUNET_OS_installation_get_path (enum GNUNET_OS_InstallationPathKind dirkind) break; case GNUNET_OS_IPK_LIBDIR: if (isbasedir) + { dirname = DIR_SEPARATOR_STR "lib" DIR_SEPARATOR_STR "gnunet" DIR_SEPARATOR_STR; + tmp = GNUNET_malloc (strlen (execpath) + strlen (dirname) + 1); + sprintf (tmp, "%s%s", execpath, dirname); + if ( (GNUNET_YES != + GNUNET_DISK_directory_test (tmp, GNUNET_YES)) && + (4 == sizeof (void *)) ) + { + GNUNET_free (tmp); + dirname = + DIR_SEPARATOR_STR "lib32" DIR_SEPARATOR_STR "gnunet" DIR_SEPARATOR_STR; + tmp = GNUNET_malloc (strlen (execpath) + strlen (dirname) + 1); + sprintf (tmp, "%s%s", execpath, dirname); + } + if ( (GNUNET_YES != + GNUNET_DISK_directory_test (tmp, GNUNET_YES)) && + (8 == sizeof (void *)) ) + { + dirname = + DIR_SEPARATOR_STR "lib64" DIR_SEPARATOR_STR "gnunet" DIR_SEPARATOR_STR; + } + GNUNET_free (tmp); + } else dirname = DIR_SEPARATOR_STR "gnunet" DIR_SEPARATOR_STR; break; @@ -430,6 +570,40 @@ GNUNET_OS_installation_get_path (enum GNUNET_OS_InstallationPathKind dirkind) DIR_SEPARATOR_STR "share" DIR_SEPARATOR_STR "doc" DIR_SEPARATOR_STR \ "gnunet" DIR_SEPARATOR_STR; break; + case GNUNET_OS_IPK_LIBEXECDIR: + if (isbasedir) + { + dirname = + DIR_SEPARATOR_STR "lib" DIR_SEPARATOR_STR "gnunet" DIR_SEPARATOR_STR \ + "libexec" DIR_SEPARATOR_STR; + tmp = GNUNET_malloc (strlen (execpath) + strlen (dirname) + 1); + sprintf (tmp, "%s%s", execpath, dirname); + if ( (GNUNET_YES != + GNUNET_DISK_directory_test (tmp, GNUNET_YES)) && + (4 == sizeof (void *)) ) + { + GNUNET_free (tmp); + dirname = + DIR_SEPARATOR_STR "lib32" DIR_SEPARATOR_STR "gnunet" DIR_SEPARATOR_STR \ + "libexec" DIR_SEPARATOR_STR; + tmp = GNUNET_malloc (strlen (execpath) + strlen (dirname) + 1); + sprintf (tmp, "%s%s", execpath, dirname); + } + if ( (GNUNET_YES != + GNUNET_DISK_directory_test (tmp, GNUNET_YES)) && + (8 == sizeof (void *)) ) + { + dirname = + DIR_SEPARATOR_STR "lib64" DIR_SEPARATOR_STR "gnunet" DIR_SEPARATOR_STR \ + "libexec" DIR_SEPARATOR_STR; + } + GNUNET_free (tmp); + } + else + dirname = + DIR_SEPARATOR_STR "gnunet" DIR_SEPARATOR_STR \ + "libexec" DIR_SEPARATOR_STR; + break; default: GNUNET_free (execpath); return NULL; @@ -442,12 +616,41 @@ GNUNET_OS_installation_get_path (enum GNUNET_OS_InstallationPathKind dirkind) /** + * Given the name of a gnunet-helper, gnunet-service or gnunet-daemon + * binary, try to prefix it with the libexec/-directory to get the + * full path. + * + * @param progname name of the binary + * @return full path to the binary, if possible, otherwise copy of 'progname' + */ +char * +GNUNET_OS_get_libexec_binary_path (const char *progname) +{ + char *libexecdir; + char *binary; + + if (DIR_SEPARATOR == progname[0]) + return GNUNET_strdup (progname); + libexecdir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_LIBEXECDIR); + if (NULL == libexecdir) + return GNUNET_strdup (progname); + GNUNET_asprintf (&binary, + "%s%s", + libexecdir, + progname); + GNUNET_free (libexecdir); + return binary; +} + + +/** * Check whether an executable exists and possibly * if the suid bit is set on the file. * Attempts to find the file using the current * PATH environment variable as a search path. * - * @param binary the name of the file to check + * @param binary the name of the file to check. + * W32: must not have an .exe suffix. * @return GNUNET_YES if the file is SUID, * GNUNET_NO if not SUID (but binary exists) * GNUNET_SYSERR on error (no such binary or not executable) @@ -458,30 +661,43 @@ GNUNET_OS_check_helper_binary (const char *binary) struct stat statbuf; char *p; char *pf; - #ifdef MINGW SOCKET rawsock; char *binaryexe; GNUNET_asprintf (&binaryexe, "%s.exe", binary); - p = get_path_from_PATH (binaryexe); - if (p != NULL) + if ( (GNUNET_YES == GNUNET_STRINGS_path_is_absolute (binaryexe, GNUNET_NO, + NULL, NULL)) || + (0 == strncmp (binary, "./", 2)) ) + p = GNUNET_strdup (binaryexe); + else { - GNUNET_asprintf (&pf, "%s/%s", p, binaryexe); - GNUNET_free (p); - p = pf; + p = get_path_from_PATH (binaryexe); + if (NULL != p) + { + GNUNET_asprintf (&pf, "%s/%s", p, binaryexe); + GNUNET_free (p); + p = pf; + } } GNUNET_free (binaryexe); #else - p = get_path_from_PATH (binary); - if (p != NULL) + if ( (GNUNET_YES == GNUNET_STRINGS_path_is_absolute (binary, GNUNET_NO, + NULL, NULL)) || + (0 == strncmp (binary, "./", 2)) ) + p = GNUNET_strdup (binary); + else { - GNUNET_asprintf (&pf, "%s/%s", p, binary); - GNUNET_free (p); - p = pf; + p = get_path_from_PATH (binary); + if (NULL != p) + { + GNUNET_asprintf (&pf, "%s/%s", p, binary); + GNUNET_free (p); + p = pf; + } } #endif - if (p == NULL) + if (NULL == p) { LOG (GNUNET_ERROR_TYPE_INFO, _("Could not find binary `%s' in PATH!\n"), binary); @@ -489,8 +705,7 @@ GNUNET_OS_check_helper_binary (const char *binary) } if (0 != ACCESS (p, X_OK)) { - LOG (GNUNET_ERROR_TYPE_WARNING, _("access (%s, X_OK) failed: %s\n"), p, - STRERROR (errno)); + LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "access", p); GNUNET_free (p); return GNUNET_SYSERR; } @@ -504,13 +719,12 @@ GNUNET_OS_check_helper_binary (const char *binary) #endif if (0 != STAT (p, &statbuf)) { - LOG (GNUNET_ERROR_TYPE_WARNING, _("stat (%s) failed: %s\n"), p, - STRERROR (errno)); + LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "stat", p); GNUNET_free (p); return GNUNET_SYSERR; } #ifndef MINGW - if ((0 != (statbuf.st_mode & S_ISUID)) && (statbuf.st_uid == 0)) + if ((0 != (statbuf.st_mode & S_ISUID)) && (0 == statbuf.st_uid)) { GNUNET_free (p); return GNUNET_YES; @@ -520,17 +734,28 @@ GNUNET_OS_check_helper_binary (const char *binary) return GNUNET_NO; #else GNUNET_free (p); - rawsock = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP); - if (INVALID_SOCKET == rawsock) { - DWORD err = GetLastError (); + static int once; /* remember result from previous runs... */ - LOG (GNUNET_ERROR_TYPE_INFO, - "socket (AF_INET, SOCK_RAW, IPPROTO_ICMP) failed! GLE = %d\n", err); - return GNUNET_NO; /* not running as administrator */ + if (0 == once) + { + rawsock = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP); + if (INVALID_SOCKET == rawsock) + { + DWORD err = GetLastError (); + + LOG (GNUNET_ERROR_TYPE_DEBUG, + "socket (AF_INET, SOCK_RAW, IPPROTO_ICMP) failed! GLE = %d\n", err); + once = -1; + return GNUNET_NO; /* not running as administrator */ + } + once = 1; + closesocket (rawsock); + } + if (-1 == once) + return GNUNET_NO; + return GNUNET_YES; } - closesocket (rawsock); - return GNUNET_YES; #endif } diff --git a/src/util/os_priority.c b/src/util/os_priority.c index b8b1ba1..ba2034c 100644 --- a/src/util/os_priority.c +++ b/src/util/os_priority.c @@ -41,6 +41,7 @@ #define GNUNET_OS_CONTROL_PIPE "GNUNET_OS_CONTROL_PIPE" + struct GNUNET_OS_Process { /** @@ -78,7 +79,8 @@ static struct GNUNET_OS_Process current_process; /** * Creates a named pipe/FIFO and opens it * - * @param fn pointer to the name of the named pipe or to NULL + * @param fn pointer to the name of the named pipe or to NULL, + * possibly updated to the new name (or free'd) * @param flags open flags * @param perm access permissions * @return pipe handle on success, NULL on error @@ -102,12 +104,12 @@ npipe_create (char **fn, enum GNUNET_DISK_OpenFlags flags, if (flags & GNUNET_DISK_OPEN_FAILIFEXISTS) openMode |= FILE_FLAG_FIRST_PIPE_INSTANCE; - while (h == NULL) + while (NULL == h) { DWORD error_code; name = NULL; - if (*fn != NULL) + if (NULL != *fn) { GNUNET_asprintf (&name, "\\\\.\\pipe\\%.246s", fn); LOG (GNUNET_ERROR_TYPE_DEBUG, @@ -133,25 +135,22 @@ npipe_create (char **fn, enum GNUNET_DISK_OpenFlags flags, NULL); } error_code = GetLastError (); - if (name) - GNUNET_free (name); + GNUNET_free_non_null (name); /* don't re-set name to NULL yet */ - if (h == INVALID_HANDLE_VALUE) + if (INVALID_HANDLE_VALUE == h) { SetErrnoFromWinError (error_code); LOG (GNUNET_ERROR_TYPE_DEBUG, "Pipe creation have failed because of %d, errno is %d\n", error_code, errno); - if (name == NULL) + if (NULL != *fn) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Pipe was to be unique, considering re-creation\n"); GNUNET_free (*fn); *fn = NULL; - if (error_code != ERROR_ACCESS_DENIED && error_code != ERROR_PIPE_BUSY) - { - return NULL; - } + if ( (ERROR_ACCESS_DENIED != error_code) && (ERROR_PIPE_BUSY != error_code) ) + return NULL; LOG (GNUNET_ERROR_TYPE_DEBUG, "Pipe name was not unique, trying again\n"); h = NULL; @@ -160,11 +159,9 @@ npipe_create (char **fn, enum GNUNET_DISK_OpenFlags flags, return NULL; } } - errno = 0; - - ret = GNUNET_malloc (sizeof (*ret)); + ret = GNUNET_malloc (sizeof (struct GNUNET_DISK_FileHandle)); ret->h = h; - ret->type = GNUNET_PIPE; + ret->type = GNUNET_DISK_HANLDE_TYPE_PIPE; ret->oOverlapRead = GNUNET_malloc (sizeof (OVERLAPPED)); ret->oOverlapWrite = GNUNET_malloc (sizeof (OVERLAPPED)); ret->oOverlapRead->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); @@ -197,15 +194,15 @@ npipe_open (const char *fn, enum GNUNET_DISK_OpenFlags flags) h = CreateFile (fn, openMode, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED | FILE_READ_ATTRIBUTES, NULL); - if (h == INVALID_HANDLE_VALUE) + if (INVALID_HANDLE_VALUE == h) { SetErrnoFromWinError (GetLastError ()); return NULL; } - ret = GNUNET_malloc (sizeof (*ret)); + ret = GNUNET_malloc (sizeof (struct GNUNET_DISK_FileHandle)); ret->h = h; - ret->type = GNUNET_PIPE; + ret->type = GNUNET_DISK_HANLDE_TYPE_PIPE; ret->oOverlapRead = GNUNET_malloc (sizeof (OVERLAPPED)); ret->oOverlapWrite = GNUNET_malloc (sizeof (OVERLAPPED)); ret->oOverlapRead->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); @@ -326,6 +323,7 @@ parent_control_handler (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_DISK_FileHandle *control_pipe = cls; + char *pipe_name; char sig; ssize_t ret; @@ -343,11 +341,15 @@ parent_control_handler (void *cls, { if (-1 == ret) LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "GNUNET_DISK_file_read"); + LOG (GNUNET_ERROR_TYPE_WARNING, "Closing control pipe\n"); GNUNET_DISK_file_close (control_pipe); control_pipe = NULL; return; } - LOG (GNUNET_ERROR_TYPE_DEBUG, "Got control code %d from parent\n", sig); + pipe_name = getenv (GNUNET_OS_CONTROL_PIPE); + GNUNET_assert ( (NULL == pipe_name) || (strlen (pipe_name) <= 0) ); + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Got control code %d from parent via pipe %s\n", sig, pipe_name); GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, control_pipe, &parent_control_handler, control_pipe); @@ -373,7 +375,7 @@ GNUNET_OS_install_parent_control_handler (void *cls, struct GNUNET_DISK_FileHandle *control_pipe; env_buf = getenv (GNUNET_OS_CONTROL_PIPE); - if ( (env_buf == NULL) || (strlen (env_buf) <= 0) ) + if ( (NULL == env_buf) || (strlen (env_buf) <= 0) ) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Not installing a handler because $%s is empty\n", @@ -440,8 +442,9 @@ GNUNET_OS_process_kill (struct GNUNET_OS_Process *proc, int sig) #endif if (NULL != proc->control_pipe) { + LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending signal %d to pid: %u via pipe\n", sig, proc->pid); ret = GNUNET_DISK_file_write (proc->control_pipe, &csig, sizeof (csig)); - if (ret == sizeof (csig)) + if (sizeof (csig) == ret) return 0; } /* pipe failed or non-existent, try other methods */ @@ -454,13 +457,42 @@ GNUNET_OS_process_kill (struct GNUNET_OS_Process *proc, int sig) case SIGKILL: case SIGTERM: #if WINDOWS && !defined(__CYGWIN__) - if (0 == TerminateProcess (proc->handle, 0)) { - /* FIXME: set 'errno' */ - return -1; + DWORD exitcode; + int must_kill = GNUNET_YES; + if (0 != GetExitCodeProcess (proc->handle, &exitcode)) + must_kill = (exitcode == STILL_ACTIVE) ? GNUNET_YES : GNUNET_NO; + if (GNUNET_YES == must_kill) + if (0 == SafeTerminateProcess (proc->handle, 0, 0)) + { + DWORD error_code = GetLastError (); + if ((error_code != WAIT_TIMEOUT) && (error_code != ERROR_PROCESS_ABORTED)) + { + LOG ((error_code == ERROR_ACCESS_DENIED) ? + GNUNET_ERROR_TYPE_INFO : GNUNET_ERROR_TYPE_WARNING, + "SafeTermiateProcess failed with code %lu\n", error_code); + /* The problem here is that a process that is already dying + * might cause SafeTerminateProcess to fail with + * ERROR_ACCESS_DENIED, but the process WILL die eventually. + * If we really had a permissions problem, hanging up (which + * is what will happen in process_wait() in that case) is + * a valid option. + */ + if (ERROR_ACCESS_DENIED == error_code) + { + errno = 0; + } + else + { + SetErrnoFromWinError (error_code); + return -1; + } + } + } } return 0; #else + LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending signal %d to pid: %u via system call\n", sig, proc->pid); return PLIBC_KILL (proc->pid, sig); #endif default: @@ -468,6 +500,7 @@ GNUNET_OS_process_kill (struct GNUNET_OS_Process *proc, int sig) errno = EINVAL; return -1; #else + LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending signal %d to pid: %u via system call\n", sig, proc->pid); return PLIBC_KILL (proc->pid, sig); #endif } @@ -541,6 +574,7 @@ child_wait_thread (void *arg) } #endif + /** * Set process priority * @@ -555,7 +589,7 @@ GNUNET_OS_set_process_priority (struct GNUNET_OS_Process *proc, int rprio; GNUNET_assert (prio < GNUNET_SCHEDULER_PRIORITY_COUNT); - if (prio == GNUNET_SCHEDULER_PRIORITY_KEEP) + if (GNUNET_SCHEDULER_PRIORITY_KEEP == prio) return GNUNET_OK; /* convert to MINGW/Unix values */ @@ -646,6 +680,7 @@ GNUNET_OS_set_process_priority (struct GNUNET_OS_Process *proc, return GNUNET_OK; } + #if MINGW static char * CreateCustomEnvTable (char **vars) @@ -666,7 +701,7 @@ CreateCustomEnvTable (char **vars) char *val; win32_env_table = GetEnvironmentStringsA (); - if (win32_env_table == NULL) + if (NULL == win32_env_table) return NULL; for (c = 0, var_ptr = vars; *var_ptr; var_ptr += 2, c++) ; n_var = c; @@ -751,6 +786,38 @@ CreateCustomEnvTable (char **vars) *result_ptr = 0; return result; } + +#else + +/** + * Open '/dev/null' and make the result the given + * file descriptor. + * + * @param target_fd desired FD to point to /dev/null + * @param flags open flags (O_RDONLY, O_WRONLY) + */ +static void +open_dev_null (int target_fd, + int flags) +{ + int fd; + + fd = open ("/dev/null", flags); + if (-1 == fd) + { + GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", "/dev/null"); + return; + } + if (fd == target_fd) + return; + if (-1 == dup2 (fd, target_fd)) + { + GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "dup2"); + (void) close (fd); + return; + } + GNUNET_break (0 == close (fd)); +} #endif @@ -758,33 +825,54 @@ CreateCustomEnvTable (char **vars) * Start a process. * * @param pipe_control should a pipe be used to send signals to the child? + * @param std_inheritance a set of GNUNET_OS_INHERIT_STD_* flags controlling which + * std handles of the parent are inherited by the child. + * pipe_stdin and pipe_stdout take priority over std_inheritance + * (when they are non-NULL). * @param pipe_stdin pipe to use to send input to child process (or NULL) * @param pipe_stdout pipe to use to get output from child process (or NULL) + * @param lsocks array of listen sockets to dup systemd-style (or NULL); + * must be NULL on platforms where dup is not supported * @param filename name of the binary - * @param argv NULL-terminated array of arguments to the process - * @return pointer to process structure of the new process, NULL on error + * @param argv NULL-terminated list of arguments to the process + * @return process ID of the new process, -1 on error */ -struct GNUNET_OS_Process * -GNUNET_OS_start_process_vap (int pipe_control, - struct GNUNET_DISK_PipeHandle *pipe_stdin, - struct GNUNET_DISK_PipeHandle *pipe_stdout, - const char *filename, - char *const argv[]) +static struct GNUNET_OS_Process * +start_process (int pipe_control, + enum GNUNET_OS_InheritStdioFlags std_inheritance, + struct GNUNET_DISK_PipeHandle *pipe_stdin, + struct GNUNET_DISK_PipeHandle *pipe_stdout, + const SOCKTYPE *lsocks, + const char *filename, + char *const argv[]) { #ifndef MINGW - char *childpipename = NULL; - struct GNUNET_OS_Process *gnunet_proc = NULL; pid_t ret; + char lpid[16]; + char fds[16]; + struct GNUNET_OS_Process *gnunet_proc; + char *childpipename = NULL; + int i; + int j; + int k; + int tgt; + int flags; + int *lscp; + unsigned int ls; int fd_stdout_write; int fd_stdout_read; int fd_stdin_read; int fd_stdin_write; + if (GNUNET_SYSERR == GNUNET_OS_check_helper_binary (filename)) + return NULL; /* not executable */ if ( (GNUNET_YES == pipe_control) && - (GNUNET_OK != - npipe_setup (&childpipename)) ) - return NULL; - if (pipe_stdout != NULL) + (GNUNET_OK != npipe_setup (&childpipename)) ) + { + GNUNET_free (childpipename); + return NULL; + } + if (NULL != pipe_stdout) { GNUNET_assert (GNUNET_OK == GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle @@ -796,7 +884,7 @@ GNUNET_OS_start_process_vap (int pipe_control, (pipe_stdout, GNUNET_DISK_PIPE_END_READ), &fd_stdout_read, sizeof (int))); } - if (pipe_stdin != NULL) + if (NULL != pipe_stdin) { GNUNET_assert (GNUNET_OK == GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle @@ -807,14 +895,28 @@ GNUNET_OS_start_process_vap (int pipe_control, (pipe_stdin, GNUNET_DISK_PIPE_END_WRITE), &fd_stdin_write, sizeof (int))); } - + lscp = NULL; + ls = 0; + if (NULL != lsocks) + { + i = 0; + while (-1 != (k = lsocks[i++])) + GNUNET_array_append (lscp, ls, k); + GNUNET_array_append (lscp, ls, -1); + } +#if DARWIN + /* see https://gnunet.org/vfork */ + ret = vfork (); +#else ret = fork (); +#endif if (-1 == ret) { int eno = errno; LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "fork"); GNUNET_free_non_null (childpipename); + GNUNET_array_grow (lscp, ls, 0); errno = eno; return NULL; } @@ -822,393 +924,48 @@ GNUNET_OS_start_process_vap (int pipe_control, { gnunet_proc = GNUNET_malloc (sizeof (struct GNUNET_OS_Process)); gnunet_proc->pid = ret; - gnunet_proc->childpipename = childpipename; + gnunet_proc->childpipename = childpipename; + GNUNET_array_grow (lscp, ls, 0); return gnunet_proc; } if (NULL != childpipename) { setenv (GNUNET_OS_CONTROL_PIPE, childpipename, 1); +#ifndef DARWIN + /* due to vfork, we must NOT free memory on DARWIN! */ GNUNET_free (childpipename); +#endif } - if (pipe_stdout != NULL) - { - GNUNET_break (0 == close (fd_stdout_read)); - if (-1 == dup2 (fd_stdout_write, 1)) - LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "dup2"); - GNUNET_break (0 == close (fd_stdout_write)); - } - - if (pipe_stdin != NULL) + if (NULL != pipe_stdin) { - GNUNET_break (0 == close (fd_stdin_write)); if (-1 == dup2 (fd_stdin_read, 0)) LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "dup2"); GNUNET_break (0 == close (fd_stdin_read)); } - execvp (filename, argv); - LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "execvp", filename); - _exit (1); -#else - char *childpipename = NULL; - struct GNUNET_OS_Process *gnunet_proc = NULL; - char *arg; - unsigned int cmdlen; - char *cmd, *idx; - STARTUPINFOW start; - PROCESS_INFORMATION proc; - int argc, arg_count; - HANDLE stdin_handle; - HANDLE stdout_handle; - struct GNUNET_DISK_FileHandle *control_pipe; - - char path[MAX_PATH + 1]; - - char *our_env[3] = { NULL, NULL, NULL }; - char *env_block = NULL; - char *pathbuf; - DWORD pathbuf_len, alloc_len; - char *self_prefix; - char *bindir; - char *libdir; - char *ptr; - char *non_const_filename; - char win_path[MAX_PATH + 1]; - wchar_t *wpath, *wcmd; - size_t wpath_len, wcmd_len; - long lRet; - - /* Search in prefix dir (hopefully - the directory from which - * the current module was loaded), bindir and libdir, then in PATH - */ - self_prefix = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_SELF_PREFIX); - bindir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_BINDIR); - libdir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_LIBDIR); - - pathbuf_len = GetEnvironmentVariableA ("PATH", (char *) &pathbuf, 0); - - alloc_len = - pathbuf_len + 1 + strlen (self_prefix) + 1 + strlen (bindir) + 1 + - strlen (libdir); - - pathbuf = GNUNET_malloc (alloc_len * sizeof (char)); - - ptr = pathbuf; - ptr += sprintf (pathbuf, "%s;%s;%s;", self_prefix, bindir, libdir); - GNUNET_free (self_prefix); - GNUNET_free (bindir); - GNUNET_free (libdir); - - alloc_len = GetEnvironmentVariableA ("PATH", ptr, pathbuf_len); - GNUNET_assert (alloc_len == (pathbuf_len - 1)); - - cmdlen = strlen (filename); - if (cmdlen < 5 || strcmp (&filename[cmdlen - 4], ".exe") != 0) - GNUNET_asprintf (&non_const_filename, "%s.exe", filename); - else - GNUNET_asprintf (&non_const_filename, "%s", filename); - - /* It could be in POSIX form, convert it to a DOS path early on */ - if (ERROR_SUCCESS != (lRet = plibc_conv_to_win_path (non_const_filename, win_path))) - { - SetErrnoFromWinError (lRet); - LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "plibc_conv_to_win_path", - non_const_filename); - GNUNET_free (non_const_filename); - GNUNET_free (pathbuf); - return NULL; - } - GNUNET_free (non_const_filename); - non_const_filename = GNUNET_strdup (win_path); - /* Check that this is the full path. If it isn't, search. */ - /* FIXME: convert it to wchar_t and use SearchPathW? - * Remember: arguments to _start_process() are technically in UTF-8... - */ - if (non_const_filename[1] == ':') - snprintf (path, sizeof (path) / sizeof (char), "%s", non_const_filename); - else if (!SearchPathA - (pathbuf, non_const_filename, NULL, sizeof (path) / sizeof (char), - path, NULL)) - { - SetErrnoFromWinError (GetLastError ()); - LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "SearchPath", - non_const_filename); - GNUNET_free (non_const_filename); - GNUNET_free (pathbuf); - return NULL; - } - GNUNET_free (pathbuf); - GNUNET_free (non_const_filename); - - cmdlen = 0; - argc = 0; - while (NULL != (arg = argv[argc++])) - { - if (cmdlen == 0) - cmdlen = cmdlen + strlen (path) + 4; - else - cmdlen = cmdlen + strlen (arg) + 4; - } - arg_count = argc; - - cmd = idx = GNUNET_malloc (sizeof (char) * (cmdlen + 1)); - argc = 0; - while (NULL != (arg = argv[argc++])) - { - /* This is to escape trailing slash */ - char arg_lastchar = arg[strlen (arg) - 1]; - if (idx == cmd) - idx += sprintf (idx, "\"%s%s\"%s", path, - arg_lastchar == '\\' ? "\\" : "", argc + 1 == arg_count ? "" : " "); - else - idx += sprintf (idx, "\"%s%s\"%s", arg, - arg_lastchar == '\\' ? "\\" : "", argc + 1 == arg_count ? "" : " "); - } - - memset (&start, 0, sizeof (start)); - start.cb = sizeof (start); - - if ((pipe_stdin != NULL) || (pipe_stdout != NULL)) - start.dwFlags |= STARTF_USESTDHANDLES; - - if (pipe_stdin != NULL) - { - GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle - (pipe_stdin, GNUNET_DISK_PIPE_END_READ), - &stdin_handle, sizeof (HANDLE)); - start.hStdInput = stdin_handle; - } - - if (pipe_stdout != NULL) - { - GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle - (pipe_stdout, - GNUNET_DISK_PIPE_END_WRITE), - &stdout_handle, sizeof (HANDLE)); - start.hStdOutput = stdout_handle; - } - if (GNUNET_YES == pipe_control) - { - control_pipe = - npipe_create (&childpipename, GNUNET_DISK_OPEN_WRITE, - GNUNET_DISK_PERM_USER_READ | - GNUNET_DISK_PERM_USER_WRITE); - if (control_pipe == NULL) - { - GNUNET_free (cmd); - GNUNET_free (path); - return NULL; - } - } - else - control_pipe = NULL; - if (NULL != childpipename) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, "Opened the parent end of the pipe `%s'\n", - childpipename); - GNUNET_asprintf (&our_env[0], "%s=", GNUNET_OS_CONTROL_PIPE); - GNUNET_asprintf (&our_env[1], "%s", childpipename); - our_env[2] = NULL; - } - else - { - our_env[0] = NULL; - } - env_block = CreateCustomEnvTable (our_env); - GNUNET_free_non_null (our_env[0]); - GNUNET_free_non_null (our_env[1]); - - wpath_len = 0; - if (NULL == (wpath = u8_to_u16 ((uint8_t *) path, 1 + strlen (path), NULL, &wpath_len))) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Failed to convert `%s' from UTF-8 to UTF-16: %d\n", path, errno); - GNUNET_free (env_block); - GNUNET_free (cmd); - return NULL; - } - - wcmd_len = 0; - if (NULL == (wcmd = u8_to_u16 ((uint8_t *) cmd, 1 + strlen (cmd), NULL, &wcmd_len))) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Failed to convert `%s' from UTF-8 to UTF-16: %d\n", cmd, errno); - GNUNET_free (env_block); - GNUNET_free (cmd); - free (wpath); - return NULL; - } - - if (!CreateProcessW (wpath, wcmd, NULL, NULL, TRUE, - DETACHED_PROCESS | CREATE_SUSPENDED, env_block, NULL, &start, &proc)) - { - SetErrnoFromWinError (GetLastError ()); - LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "CreateProcess", path); - GNUNET_free (env_block); - GNUNET_free (cmd); - free (wpath); - free (wcmd); - return NULL; - } - - GNUNET_free (env_block); - - gnunet_proc = GNUNET_malloc (sizeof (struct GNUNET_OS_Process)); - gnunet_proc->pid = proc.dwProcessId; - gnunet_proc->handle = proc.hProcess; - gnunet_proc->control_pipe = control_pipe; - - CreateThread (NULL, 64000, &child_wait_thread, (void *) gnunet_proc, 0, NULL); - - ResumeThread (proc.hThread); - CloseHandle (proc.hThread); - - GNUNET_free (cmd); - free (wpath); - free (wcmd); - return gnunet_proc; -#endif -} - - -/** - * Start a process. - * - * @param pipe_control should a pipe be used to send signals to the child? - * @param pipe_stdin pipe to use to send input to child process (or NULL) - * @param pipe_stdout pipe to use to get output from child process (or NULL) - * @param filename name of the binary - * @param va NULL-terminated list of arguments to the process - * @return pointer to process structure of the new process, NULL on error - */ -struct GNUNET_OS_Process * -GNUNET_OS_start_process_va (int pipe_control, - struct GNUNET_DISK_PipeHandle *pipe_stdin, - struct GNUNET_DISK_PipeHandle *pipe_stdout, - const char *filename, va_list va) -{ - struct GNUNET_OS_Process *ret; - va_list ap; - char **argv; - int argc; - - argc = 0; - va_copy (ap, va); - while (NULL != va_arg (ap, char *)) - argc++; - va_end (ap); - argv = GNUNET_malloc (sizeof (char *) * (argc + 1)); - argc = 0; - va_copy (ap, va); - while (NULL != (argv[argc] = va_arg (ap, char *))) - argc++; - va_end (ap); - ret = GNUNET_OS_start_process_vap (pipe_control, - pipe_stdin, - pipe_stdout, - filename, - argv); - GNUNET_free (argv); - return ret; -} - - - -/** - * Start a process. - * - * @param pipe_control should a pipe be used to send signals to the child? - * @param pipe_stdin pipe to use to send input to child process (or NULL) - * @param pipe_stdout pipe to use to get output from child process (or NULL) - * @param filename name of the binary - * @param ... NULL-terminated list of arguments to the process - * - * @return pointer to process structure of the new process, NULL on error - * - */ -struct GNUNET_OS_Process * -GNUNET_OS_start_process (int pipe_control, - struct GNUNET_DISK_PipeHandle *pipe_stdin, - struct GNUNET_DISK_PipeHandle *pipe_stdout, - const char *filename, ...) -{ - struct GNUNET_OS_Process *ret; - va_list ap; - - va_start (ap, filename); - ret = GNUNET_OS_start_process_va (pipe_control, pipe_stdin, pipe_stdout, filename, ap); - va_end (ap); - return ret; -} - - -/** - * Start a process. - * - * @param pipe_control should a pipe be used to send signals to the child? - * @param lsocks array of listen sockets to dup systemd-style (or NULL); - * must be NULL on platforms where dup is not supported - * @param filename name of the binary - * @param argv NULL-terminated list of arguments to the process - * @return process ID of the new process, -1 on error - */ -struct GNUNET_OS_Process * -GNUNET_OS_start_process_v (int pipe_control, - const SOCKTYPE *lsocks, - const char *filename, - char *const argv[]) -{ -#ifndef MINGW - pid_t ret; - char lpid[16]; - char fds[16]; - struct GNUNET_OS_Process *gnunet_proc = NULL; - char *childpipename = NULL; - int i; - int j; - int k; - int tgt; - int flags; - int *lscp; - unsigned int ls; - - if ( (GNUNET_YES == pipe_control) && - (GNUNET_OK != npipe_setup (&childpipename)) ) - return NULL; - lscp = NULL; - ls = 0; - if (lsocks != NULL) + else if (0 == (std_inheritance & GNUNET_OS_INHERIT_STD_IN)) { - i = 0; - while (-1 != (k = lsocks[i++])) - GNUNET_array_append (lscp, ls, k); - GNUNET_array_append (lscp, ls, -1); + GNUNET_break (0 == close (0)); + open_dev_null (0, O_RDONLY); } - ret = fork (); - if (-1 == ret) + if (NULL != pipe_stdout) { - int eno = errno; - - LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "fork"); - GNUNET_free_non_null (childpipename); - GNUNET_array_grow (lscp, ls, 0); - errno = eno; - return NULL; + GNUNET_break (0 == close (fd_stdout_read)); + if (-1 == dup2 (fd_stdout_write, 1)) + LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "dup2"); + GNUNET_break (0 == close (fd_stdout_write)); } - if (0 != ret) + else if (0 == (std_inheritance & GNUNET_OS_INHERIT_STD_OUT)) { - gnunet_proc = GNUNET_malloc (sizeof (struct GNUNET_OS_Process)); - gnunet_proc->pid = ret; - gnunet_proc->childpipename = childpipename; - GNUNET_array_grow (lscp, ls, 0); - return gnunet_proc; + GNUNET_break (0 == close (1)); + open_dev_null (1, O_WRONLY); } - if (NULL != childpipename) + if (0 == (std_inheritance & GNUNET_OS_INHERIT_STD_ERR)) { - setenv (GNUNET_OS_CONTROL_PIPE, childpipename, 1); - GNUNET_free (childpipename); + GNUNET_break (0 == close (2)); + open_dev_null (2, O_WRONLY); } - if (lscp != NULL) + if (NULL != lscp) { /* read systemd documentation... */ GNUNET_snprintf (lpid, sizeof (lpid), "%u", getpid ()); @@ -1250,25 +1007,31 @@ GNUNET_OS_start_process_v (int pipe_control, GNUNET_snprintf (fds, sizeof (fds), "%u", i); setenv ("LISTEN_FDS", fds, 1); } +#ifndef DARWIN + /* due to vfork, we must NOT free memory on DARWIN! */ GNUNET_array_grow (lscp, ls, 0); +#endif execvp (filename, argv); LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "execvp", filename); _exit (1); #else - struct GNUNET_DISK_FileHandle *control_pipe = NULL; + struct GNUNET_DISK_FileHandle *control_pipe; char *childpipename = NULL; - char **arg, **non_const_argv; + char **arg; + char **non_const_argv; unsigned int cmdlen; - char *cmd, *idx; + char *cmd; + char *idx; STARTUPINFOW start; PROCESS_INFORMATION proc; int argcount = 0; - struct GNUNET_OS_Process *gnunet_proc = NULL; + struct GNUNET_OS_Process *gnunet_proc; char path[MAX_PATH + 1]; char *our_env[5] = { NULL, NULL, NULL, NULL, NULL }; char *env_block = NULL; char *pathbuf; - DWORD pathbuf_len, alloc_len; + DWORD pathbuf_len; + DWORD alloc_len; char *self_prefix; char *bindir; char *libdir; @@ -1279,12 +1042,23 @@ GNUNET_OS_start_process_v (int pipe_control, const struct GNUNET_DISK_FileHandle *lsocks_write_fd; HANDLE lsocks_read; HANDLE lsocks_write; - wchar_t *wpath, *wcmd; - size_t wpath_len, wcmd_len; + wchar_t *wpath; + wchar_t *wcmd; + size_t wpath_len; + size_t wcmd_len; int env_off; int fail; long lRet; - + HANDLE stdin_handle; + HANDLE stdout_handle; + HANDLE stdih, stdoh, stdeh; + DWORD stdif, stdof, stdef; + BOOL bresult; + DWORD error_code; + + if (GNUNET_SYSERR == GNUNET_OS_check_helper_binary (filename)) + return NULL; /* not executable */ + /* Search in prefix dir (hopefully - the directory from which * the current module was loaded), bindir and libdir, then in PATH */ @@ -1315,7 +1089,7 @@ GNUNET_OS_start_process_v (int pipe_control, } cmdlen = strlen (filename); - if (cmdlen < 5 || strcmp (&filename[cmdlen - 4], ".exe") != 0) + if ( (cmdlen < 5) || (0 != strcmp (&filename[cmdlen - 4], ".exe")) ) GNUNET_asprintf (&non_const_filename, "%s.exe", filename); else GNUNET_asprintf (&non_const_filename, "%s", filename); @@ -1403,6 +1177,65 @@ GNUNET_OS_start_process_v (int pipe_control, memset (&start, 0, sizeof (start)); start.cb = sizeof (start); + if ((pipe_stdin != NULL) || (pipe_stdout != NULL) || (std_inheritance != 0)) + start.dwFlags |= STARTF_USESTDHANDLES; + + stdih = GetStdHandle (STD_INPUT_HANDLE); + GetHandleInformation (stdih, &stdif); + if (pipe_stdin != NULL) + { + GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle + (pipe_stdin, GNUNET_DISK_PIPE_END_READ), + &stdin_handle, sizeof (HANDLE)); + start.hStdInput = stdin_handle; + } + if (stdih) + { + if (std_inheritance & GNUNET_OS_INHERIT_STD_IN) + { + SetHandleInformation (stdih, HANDLE_FLAG_INHERIT, 1); + if (pipe_stdin == NULL) + start.hStdInput = stdih; + } + else + SetHandleInformation (stdih, HANDLE_FLAG_INHERIT, 0); + } + + + stdoh = GetStdHandle (STD_OUTPUT_HANDLE); + GetHandleInformation (stdoh, &stdof); + if (NULL != pipe_stdout) + { + GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle + (pipe_stdout, + GNUNET_DISK_PIPE_END_WRITE), + &stdout_handle, sizeof (HANDLE)); + start.hStdOutput = stdout_handle; + } + if (stdoh) + { + if (std_inheritance & GNUNET_OS_INHERIT_STD_OUT) + { + SetHandleInformation (stdoh, HANDLE_FLAG_INHERIT, 1); + if (pipe_stdout == NULL) + start.hStdOutput = stdoh; + } + else + SetHandleInformation (stdoh, HANDLE_FLAG_INHERIT, 0); + } + + stdeh = GetStdHandle (STD_ERROR_HANDLE); + GetHandleInformation (stdeh, &stdef); + if (stdeh) + { + if (std_inheritance & GNUNET_OS_INHERIT_STD_ERR) + { + SetHandleInformation (stdeh, HANDLE_FLAG_INHERIT, 1); + start.hStdError = stdeh; + } + else + SetHandleInformation (stdeh, HANDLE_FLAG_INHERIT, 0); + } if (GNUNET_YES == pipe_control) { @@ -1480,24 +1313,36 @@ GNUNET_OS_start_process_v (int pipe_control, return NULL; } - if (!CreateProcessW (wpath, wcmd, NULL, NULL, TRUE, - DETACHED_PROCESS | CREATE_SUSPENDED, env_block, NULL, &start, &proc)) + bresult = CreateProcessW (wpath, wcmd, NULL, NULL, TRUE, + DETACHED_PROCESS | CREATE_SUSPENDED, env_block, NULL, &start, &proc); + error_code = GetLastError (); + + if ((NULL == pipe_stdin) && (stdih)) + SetHandleInformation (stdih, HANDLE_FLAG_INHERIT, stdif); + + + if ((NULL == pipe_stdout) && (stdoh)) + SetHandleInformation (stdoh, HANDLE_FLAG_INHERIT, stdof); + + if (stdeh) + SetHandleInformation (stdeh, HANDLE_FLAG_INHERIT, stdef); + + GNUNET_free (env_block); + GNUNET_free (cmd); + free (wpath); + free (wcmd); + + if (!bresult) { - SetErrnoFromWinError (GetLastError ()); + SetErrnoFromWinError (error_code); LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "CreateProcess"); if (NULL != control_pipe) GNUNET_DISK_file_close (control_pipe); if (NULL != lsocks) GNUNET_DISK_pipe_close (lsocks_pipe); - GNUNET_free (env_block); - GNUNET_free (cmd); - free (wpath); - free (wcmd); return NULL; } - GNUNET_free (env_block); - gnunet_proc = GNUNET_malloc (sizeof (struct GNUNET_OS_Process)); gnunet_proc->pid = proc.dwProcessId; gnunet_proc->handle = proc.hProcess; @@ -1507,11 +1352,8 @@ GNUNET_OS_start_process_v (int pipe_control, ResumeThread (proc.hThread); CloseHandle (proc.hThread); - GNUNET_free (cmd); - free (wpath); - free (wcmd); - if (lsocks == NULL || lsocks[0] == INVALID_SOCKET) + if ( (NULL == lsocks) || (INVALID_SOCKET == lsocks[0]) ) return gnunet_proc; GNUNET_DISK_pipe_close_end (lsocks_pipe, GNUNET_DISK_PIPE_END_READ); @@ -1520,16 +1362,20 @@ GNUNET_OS_start_process_v (int pipe_control, fail = 1; do { - int wrote; - uint64_t size, count, i; + ssize_t wrote; + uint64_t size; + uint64_t count; + unsigned int i; /* Tell the number of sockets */ for (count = 0; lsocks && lsocks[count] != INVALID_SOCKET; count++); wrote = GNUNET_DISK_file_write (lsocks_write_fd, &count, sizeof (count)); - if (wrote != sizeof (count)) + if (sizeof (count) != wrote) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to write %u count bytes to the child: %u\n", sizeof (count), GetLastError ()); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to write %u count bytes to the child: %u\n", + sizeof (count), GetLastError ()); break; } for (i = 0; lsocks && lsocks[i] != INVALID_SOCKET; i++) @@ -1538,8 +1384,9 @@ GNUNET_OS_start_process_v (int pipe_control, /* Get a socket duplication info */ if (SOCKET_ERROR == WSADuplicateSocketA (lsocks[i], gnunet_proc->pid, &pi)) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to duplicate an socket[%llu]: %u\n", i, GetLastError ()); - LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "CreateProcess"); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to duplicate an socket[%llu]: %u\n", i, + GetLastError ()); break; } /* Synchronous I/O is not nice, but we can't schedule this: @@ -1552,16 +1399,20 @@ GNUNET_OS_start_process_v (int pipe_control, */ size = sizeof (pi); wrote = GNUNET_DISK_file_write (lsocks_write_fd, &size, sizeof (size)); - if (wrote != sizeof (size)) + if (sizeof (size) != wrote) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to write %u size[%llu] bytes to the child: %u\n", sizeof (size), i, GetLastError ()); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to write %u size[%llu] bytes to the child: %u\n", + sizeof (size), i, GetLastError ()); break; } /* Finally! Send the data */ wrote = GNUNET_DISK_file_write (lsocks_write_fd, &pi, sizeof (pi)); - if (wrote != sizeof (pi)) + if (sizeof (pi) != wrote) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to write %u socket[%llu] bytes to the child: %u\n", sizeof (pi), i, GetLastError ()); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to write %u socket[%llu] bytes to the child: %u\n", + sizeof (pi), i, GetLastError ()); break; } } @@ -1583,7 +1434,7 @@ GNUNET_OS_start_process_v (int pipe_control, /* If we can't pass on the socket(s), the child will block forever, * better put it out of its misery. */ - TerminateProcess (gnunet_proc->handle, 0); + SafeTerminateProcess (gnunet_proc->handle, 0, 0); CloseHandle (gnunet_proc->handle); if (NULL != gnunet_proc->control_pipe) GNUNET_DISK_file_close (gnunet_proc->control_pipe); @@ -1595,6 +1446,142 @@ GNUNET_OS_start_process_v (int pipe_control, } + + +/** + * Start a process. + * + * @param pipe_control should a pipe be used to send signals to the child? + * @param std_inheritance a set of GNUNET_OS_INHERIT_STD_* flags + * @param pipe_stdin pipe to use to send input to child process (or NULL) + * @param pipe_stdout pipe to use to get output from child process (or NULL) + * @param filename name of the binary + * @param argv NULL-terminated array of arguments to the process + * @return pointer to process structure of the new process, NULL on error + */ +struct GNUNET_OS_Process * +GNUNET_OS_start_process_vap (int pipe_control, + enum GNUNET_OS_InheritStdioFlags std_inheritance, + struct GNUNET_DISK_PipeHandle *pipe_stdin, + struct GNUNET_DISK_PipeHandle *pipe_stdout, + const char *filename, + char *const argv[]) +{ + return start_process (pipe_control, + std_inheritance, + pipe_stdin, + pipe_stdout, + NULL, + filename, + argv); +} + + +/** + * Start a process. + * + * @param pipe_control should a pipe be used to send signals to the child? + * @param std_inheritance a set of GNUNET_OS_INHERIT_STD_* flags + * @param pipe_stdin pipe to use to send input to child process (or NULL) + * @param pipe_stdout pipe to use to get output from child process (or NULL) + * @param filename name of the binary + * @param va NULL-terminated list of arguments to the process + * @return pointer to process structure of the new process, NULL on error + */ +struct GNUNET_OS_Process * +GNUNET_OS_start_process_va (int pipe_control, + enum GNUNET_OS_InheritStdioFlags std_inheritance, + struct GNUNET_DISK_PipeHandle *pipe_stdin, + struct GNUNET_DISK_PipeHandle *pipe_stdout, + const char *filename, va_list va) +{ + struct GNUNET_OS_Process *ret; + va_list ap; + char **argv; + int argc; + + argc = 0; + va_copy (ap, va); + while (NULL != va_arg (ap, char *)) + argc++; + va_end (ap); + argv = GNUNET_malloc (sizeof (char *) * (argc + 1)); + argc = 0; + va_copy (ap, va); + while (NULL != (argv[argc] = va_arg (ap, char *))) + argc++; + va_end (ap); + ret = GNUNET_OS_start_process_vap (pipe_control, + std_inheritance, + pipe_stdin, + pipe_stdout, + filename, + argv); + GNUNET_free (argv); + return ret; +} + + +/** + * Start a process. + * + * @param pipe_control should a pipe be used to send signals to the child? + * @param std_inheritance a set of GNUNET_OS_INHERIT_STD_* flags + * @param pipe_stdin pipe to use to send input to child process (or NULL) + * @param pipe_stdout pipe to use to get output from child process (or NULL) + * @param filename name of the binary + * @param ... NULL-terminated list of arguments to the process + * @return pointer to process structure of the new process, NULL on error + */ +struct GNUNET_OS_Process * +GNUNET_OS_start_process (int pipe_control, + enum GNUNET_OS_InheritStdioFlags std_inheritance, + struct GNUNET_DISK_PipeHandle *pipe_stdin, + struct GNUNET_DISK_PipeHandle *pipe_stdout, + const char *filename, ...) +{ + struct GNUNET_OS_Process *ret; + va_list ap; + + va_start (ap, filename); + ret = GNUNET_OS_start_process_va (pipe_control, std_inheritance, pipe_stdin, + pipe_stdout, filename, ap); + va_end (ap); + return ret; +} + + +/** + * Start a process. + * + * @param pipe_control should a pipe be used to send signals to the child? + * @param std_inheritance a set of GNUNET_OS_INHERIT_STD_* flags controlling which + * std handles of the parent are inherited by the child. + * pipe_stdin and pipe_stdout take priority over std_inheritance + * (when they are non-NULL). + * @param lsocks array of listen sockets to dup systemd-style (or NULL); + * must be NULL on platforms where dup is not supported + * @param filename name of the binary + * @param argv NULL-terminated list of arguments to the process + * @return process ID of the new process, -1 on error + */ +struct GNUNET_OS_Process * +GNUNET_OS_start_process_v (int pipe_control, + enum GNUNET_OS_InheritStdioFlags std_inheritance, + const SOCKTYPE *lsocks, + const char *filename, + char *const argv[]) +{ + return start_process (pipe_control, + std_inheritance, + NULL, + NULL, + lsocks, + filename, + argv); +} + + /** * Retrieve the status of a process, waiting on him if dead. * Nonblocking version. @@ -1698,13 +1685,13 @@ GNUNET_OS_process_status (struct GNUNET_OS_Process *proc, /** * Wait for a process + * * @param proc pointer to process structure * @return GNUNET_OK on success, GNUNET_SYSERR otherwise */ int GNUNET_OS_process_wait (struct GNUNET_OS_Process *proc) { - #ifndef MINGW pid_t pid = proc->pid; pid_t ret; @@ -1719,7 +1706,6 @@ GNUNET_OS_process_wait (struct GNUNET_OS_Process *proc) return GNUNET_OK; #else HANDLE h; - int ret; h = proc->handle; if (NULL == h) @@ -1728,18 +1714,15 @@ GNUNET_OS_process_wait (struct GNUNET_OS_Process *proc) proc->pid, h); return GNUNET_SYSERR; } - if (h == NULL) + if (NULL == h) h = GetCurrentProcess (); if (WAIT_OBJECT_0 != WaitForSingleObject (h, INFINITE)) { SetErrnoFromWinError (GetLastError ()); - ret = GNUNET_SYSERR; + return GNUNET_SYSERR; } - else - ret = GNUNET_OK; - - return ret; + return GNUNET_OK; #endif } @@ -1807,8 +1790,7 @@ struct GNUNET_OS_CommandHandle void GNUNET_OS_command_stop (struct GNUNET_OS_CommandHandle *cmd) { - - if (cmd->proc != NULL) + if (NULL != cmd->proc) { GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != cmd->rtask); GNUNET_SCHEDULER_cancel (cmd->rtask); @@ -1861,7 +1843,7 @@ cmd_read (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) } end = memchr (&cmd->buf[cmd->off], '\n', ret); cmd->off += ret; - while (end != NULL) + while (NULL != end) { *end = '\0'; cmd->proc (cmd->proc_cls, cmd->buf); @@ -1900,7 +1882,8 @@ GNUNET_OS_command_run (GNUNET_OS_LineProcessor proc, void *proc_cls, if (NULL == opipe) return NULL; va_start (ap, binary); - eip = GNUNET_OS_start_process_va (GNUNET_NO, NULL, opipe, binary, ap); + /* redirect stdout, don't inherit stderr/stdin */ + eip = GNUNET_OS_start_process_va (GNUNET_NO, 0, NULL, opipe, binary, ap); va_end (ap); if (NULL == eip) { @@ -1920,6 +1903,4 @@ GNUNET_OS_command_run (GNUNET_OS_LineProcessor proc, void *proc_cls, } - - /* end of os_priority.c */ diff --git a/src/util/peer.c b/src/util/peer.c index 2444cb9..1ad3ee2 100644 --- a/src/util/peer.c +++ b/src/util/peer.c @@ -53,7 +53,7 @@ struct PeerEntry /** * Table with our interned peer IDs. */ -static struct PeerEntry *table; +static struct PeerEntry **table; /** * Hashmap of PeerIdentities to "struct PeerEntry" @@ -84,15 +84,13 @@ GNUNET_PEER_Id GNUNET_PEER_search (const struct GNUNET_PeerIdentity *pid) { struct PeerEntry *e; - long off; - if (pid == NULL) + if (NULL == pid) return 0; if (NULL == map) return 0; - off = (long) GNUNET_CONTAINER_multihashmap_get (map, &pid->hashPubKey); - e = (off == 0) ? NULL : &table[off]; - if (e == NULL) + e = GNUNET_CONTAINER_multihashmap_get (map, &pid->hashPubKey); + if (NULL == e) return 0; GNUNET_assert (e->rc > 0); return e->pid; @@ -112,15 +110,13 @@ GNUNET_PEER_intern (const struct GNUNET_PeerIdentity *pid) GNUNET_PEER_Id ret; struct PeerEntry *e; unsigned int i; - long off; - if (pid == NULL) + if (NULL == pid) return 0; if (NULL == map) - map = GNUNET_CONTAINER_multihashmap_create (32); - off = (long) GNUNET_CONTAINER_multihashmap_get (map, &pid->hashPubKey); - e = (off == 0) ? NULL : &table[off]; - if (e != NULL) + map = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_YES); + e = GNUNET_CONTAINER_multihashmap_get (map, &pid->hashPubKey); + if (NULL != e) { GNUNET_assert (e->rc > 0); e->rc++; @@ -131,23 +127,27 @@ GNUNET_PEER_intern (const struct GNUNET_PeerIdentity *pid) { GNUNET_array_grow (table, size, size + 16); for (i = ret; i < size; i++) - table[i].pid = i + 1; + { + table[i] = GNUNET_malloc (sizeof (struct PeerEntry)); + table[i]->pid = i + 1; + } } - if (ret == 0) + if (0 == ret) { - table[0].pid = 0; - table[0].rc = 1; + table[0]->pid = 0; + table[0]->rc = 1; ret = 1; } GNUNET_assert (ret < size); - GNUNET_assert (table[ret].rc == 0); - free_list_start = table[ret].pid; - table[ret].id = *pid; - table[ret].rc = 1; - table[ret].pid = ret; + GNUNET_assert (0 == table[ret]->rc); + free_list_start = table[ret]->pid; + table[ret]->id = *pid; + table[ret]->rc = 1; + table[ret]->pid = ret; GNUNET_break (GNUNET_OK == - GNUNET_CONTAINER_multihashmap_put (map, &pid->hashPubKey, - (void *) (long) ret, + GNUNET_CONTAINER_multihashmap_put (map, + &table[ret]->id.hashPubKey, + table[ret], GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); return ret; } @@ -165,24 +165,23 @@ GNUNET_PEER_decrement_rcs (const GNUNET_PEER_Id *ids, unsigned int count) int i; GNUNET_PEER_Id id; - if (count == 0) + if (0 == count) return; for (i = count - 1; i >= 0; i--) { id = ids[i]; - if (id == 0) + if (0 == id) continue; GNUNET_assert (id < size); - GNUNET_assert (table[id].rc > 0); - table[id].rc--; - if (table[id].rc == 0) + GNUNET_assert (table[id]->rc > 0); + table[id]->rc--; + if (0 == table[id]->rc) { GNUNET_break (GNUNET_OK == GNUNET_CONTAINER_multihashmap_remove (map, - &table[id]. - id.hashPubKey, - (void *) (long) id)); - table[id].pid = free_list_start; + &table[id]->id.hashPubKey, + table[id])); + table[id]->pid = free_list_start; free_list_start = id; } } @@ -198,20 +197,19 @@ GNUNET_PEER_decrement_rcs (const GNUNET_PEER_Id *ids, unsigned int count) void GNUNET_PEER_change_rc (GNUNET_PEER_Id id, int delta) { - if (id == 0) + if (0 == id) return; GNUNET_assert (id < size); - GNUNET_assert (table[id].rc > 0); - GNUNET_assert ((delta >= 0) || (table[id].rc >= -delta)); - table[id].rc += delta; - if (table[id].rc == 0) + GNUNET_assert (table[id]->rc > 0); + GNUNET_assert ((delta >= 0) || (table[id]->rc >= -delta)); + table[id]->rc += delta; + if (0 == table[id]->rc) { GNUNET_break (GNUNET_OK == GNUNET_CONTAINER_multihashmap_remove (map, - &table[id]. - id.hashPubKey, - (void *) (long) id)); - table[id].pid = free_list_start; + &table[id]->id.hashPubKey, + table[id])); + table[id]->pid = free_list_start; free_list_start = id; } } @@ -226,16 +224,30 @@ GNUNET_PEER_change_rc (GNUNET_PEER_Id id, int delta) void GNUNET_PEER_resolve (GNUNET_PEER_Id id, struct GNUNET_PeerIdentity *pid) { - if (id == 0) + if (0 == id) { memset (pid, 0, sizeof (struct GNUNET_PeerIdentity)); GNUNET_break (0); return; } GNUNET_assert (id < size); - GNUNET_assert (table[id].rc > 0); - *pid = table[id].id; + GNUNET_assert (table[id]->rc > 0); + *pid = table[id]->id; +} + + +/** + * Convert an interned PID to a normal peer identity. + * + * @param id interned PID to convert + * @return pointer to peer identity, valid as long 'id' is valid + */ +const struct GNUNET_PeerIdentity * +GNUNET_PEER_resolve2 (GNUNET_PEER_Id id) +{ + return &table[id]->id; } + /* end of peer.c */ diff --git a/src/util/perf_crypto_hash.c b/src/util/perf_crypto_hash.c index d883776..d1f4c9d 100644 --- a/src/util/perf_crypto_hash.c +++ b/src/util/perf_crypto_hash.c @@ -32,9 +32,9 @@ static void perfHash () { - GNUNET_HashCode hc1; - GNUNET_HashCode hc2; - GNUNET_HashCode hc3; + struct GNUNET_HashCode hc1; + struct GNUNET_HashCode hc2; + struct GNUNET_HashCode hc3; int i; char *buf; @@ -43,8 +43,8 @@ perfHash () GNUNET_CRYPTO_hash ("foo", 3, &hc1); for (i = 0; i < 1024; i++) { - GNUNET_CRYPTO_hash (&hc1, sizeof (GNUNET_HashCode), &hc2); - GNUNET_CRYPTO_hash (&hc2, sizeof (GNUNET_HashCode), &hc1); + GNUNET_CRYPTO_hash (&hc1, sizeof (struct GNUNET_HashCode), &hc2); + GNUNET_CRYPTO_hash (&hc2, sizeof (struct GNUNET_HashCode), &hc1); GNUNET_CRYPTO_hash (buf, 1024 * 64, &hc3); } GNUNET_free (buf); diff --git a/src/util/perf_malloc.c b/src/util/perf_malloc.c new file mode 100644 index 0000000..31f08df --- /dev/null +++ b/src/util/perf_malloc.c @@ -0,0 +1,66 @@ +/* + This file is part of GNUnet. + (C) 2012 Christian Grothoff (and other contributing authors) + + GNUnet 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. + + GNUnet 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 GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/** + * @author Christian Grothoff + * @file util/perf_malloc.c + * @brief measure performance of allocation functions + */ +#include "platform.h" +#include "gnunet_common.h" +#include "gnunet_crypto_lib.h" +#include "gnunet_time_lib.h" +#include <gauger.h> + +static uint64_t +perfMalloc () +{ + size_t i; + uint64_t ret; + + ret = 0; + for (i=1;i<1024 * 1024;i+=1024) + { + ret += i; + GNUNET_free (GNUNET_malloc (i)); + } + return ret; +} + + +int +main (int argc, char *argv[]) +{ + struct GNUNET_TIME_Absolute start; + uint64_t kb; + + start = GNUNET_TIME_absolute_get (); + kb = perfMalloc (); + printf ("Malloc perf took %llu ms\n", + (unsigned long long) + GNUNET_TIME_absolute_get_duration (start).rel_value); + GAUGER ("UTIL", "Allocation", + kb / 1024 / (1 + + GNUNET_TIME_absolute_get_duration + (start).rel_value), "kb/s"); + return 0; +} + +/* end of perf_malloc.c */ diff --git a/src/util/program.c b/src/util/program.c index 9e1a83d..5cd129b 100644 --- a/src/util/program.c +++ b/src/util/program.c @@ -9,7 +9,7 @@ GNUnet 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 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPROSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License @@ -78,6 +78,7 @@ GNUNET_SPEEDUP_start_ (const struct GNUNET_CONFIGURATION_Handle *cfg); int GNUNET_SPEEDUP_stop_ (void); + /** * Initial task called by the scheduler for each * program. Runs the program-specific main task. @@ -86,8 +87,10 @@ static void program_main (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct CommandContext *cc = cls; - GNUNET_SPEEDUP_start_(cc->cfg); + if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) + return; + GNUNET_SPEEDUP_start_(cc->cfg); GNUNET_RESOLVER_connect (cc->cfg); cc->task (cc->task_cls, cc->args, cc->cfgfile, cc->cfg); } @@ -158,7 +161,7 @@ GNUNET_PROGRAM_run2 (int argc, char *const *argv, const char *binaryName, GNUNET_GETOPT_OPTION_HELP (binaryHelp), GNUNET_GETOPT_OPTION_LOGLEVEL (&loglev), GNUNET_GETOPT_OPTION_LOGFILE (&logfile), - GNUNET_GETOPT_OPTION_VERSION (PACKAGE_VERSION) + GNUNET_GETOPT_OPTION_VERSION (PACKAGE_VERSION " " VCS_VERSION) }; struct GNUNET_GETOPT_CommandLineOption *allopts; const char *gargs; @@ -228,9 +231,8 @@ GNUNET_PROGRAM_run2 (int argc, char *const *argv, const char *binaryName, lpfx = GNUNET_strdup (binaryName); if (NULL != (spc = strstr (lpfx, " "))) *spc = '\0'; - if ((-1 == - (ret = - GNUNET_GETOPT_run (binaryName, allopts, (unsigned int) argc, argv))) || + ret = GNUNET_GETOPT_run (binaryName, allopts, (unsigned int) argc, argv); + if ((GNUNET_OK > ret) || (GNUNET_OK != GNUNET_log_setup (lpfx, loglev, logfile))) { GNUNET_CONFIGURATION_destroy (cfg); @@ -239,9 +241,19 @@ GNUNET_PROGRAM_run2 (int argc, char *const *argv, const char *binaryName, GNUNET_free_non_null (logfile); GNUNET_free (allopts); GNUNET_free (lpfx); - return GNUNET_SYSERR; + return (ret == GNUNET_SYSERR) ? GNUNET_SYSERR : GNUNET_OK; + } + if (GNUNET_YES == + GNUNET_DISK_file_test (cc.cfgfile)) + (void) GNUNET_CONFIGURATION_load (cfg, cc.cfgfile); + else + { + (void) GNUNET_CONFIGURATION_load (cfg, NULL); + if (0 != strcmp (cc.cfgfile, GNUNET_DEFAULT_USER_CONFIG_FILE)) + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Could not access configuration file `%s'\n"), + cc.cfgfile); } - (void) GNUNET_CONFIGURATION_load (cfg, cc.cfgfile); GNUNET_free (allopts); GNUNET_free (lpfx); if (GNUNET_OK == diff --git a/src/util/pseudonym.c b/src/util/pseudonym.c index 0165738..fa48e19 100644 --- a/src/util/pseudonym.c +++ b/src/util/pseudonym.c @@ -88,7 +88,7 @@ static struct DiscoveryCallback *head; * @param rating rating of pseudonym */ static void -internal_notify (const GNUNET_HashCode * id, +internal_notify (const struct GNUNET_HashCode * id, const struct GNUNET_CONTAINER_MetaData *md, int rating) { struct DiscoveryCallback *pos; @@ -169,7 +169,7 @@ GNUNET_PSEUDONYM_discovery_callback_unregister (GNUNET_PSEUDONYM_Iterator */ static char * get_data_filename (const struct GNUNET_CONFIGURATION_Handle *cfg, - const char *prefix, const GNUNET_HashCode * psid) + const char *prefix, const struct GNUNET_HashCode * psid) { struct GNUNET_CRYPTO_HashAsciiEncoded enc; @@ -192,7 +192,7 @@ get_data_filename (const struct GNUNET_CONFIGURATION_Handle *cfg, */ static void write_pseudonym_info (const struct GNUNET_CONFIGURATION_Handle *cfg, - const GNUNET_HashCode * nsid, + const struct GNUNET_HashCode * nsid, const struct GNUNET_CONTAINER_MetaData *meta, int32_t ranking, const char *ns_name) { @@ -238,7 +238,7 @@ write_pseudonym_info (const struct GNUNET_CONFIGURATION_Handle *cfg, */ static int read_info (const struct GNUNET_CONFIGURATION_Handle *cfg, - const GNUNET_HashCode * nsid, + const struct GNUNET_HashCode * nsid, struct GNUNET_CONTAINER_MetaData **meta, int32_t * ranking, char **ns_name) { @@ -248,6 +248,12 @@ read_info (const struct GNUNET_CONFIGURATION_Handle *cfg, fn = get_data_filename (cfg, PS_METADATA_DIR, nsid); GNUNET_assert (fn != NULL); + if (GNUNET_YES != + GNUNET_DISK_file_test (fn)) + { + GNUNET_free (fn); + return GNUNET_SYSERR; + } fileR = GNUNET_BIO_read_open (fn); if (fileR == NULL) { @@ -303,9 +309,9 @@ read_info (const struct GNUNET_CONFIGURATION_Handle *cfg, */ char * GNUNET_PSEUDONYM_name_uniquify (const struct GNUNET_CONFIGURATION_Handle *cfg, - const GNUNET_HashCode * nsid, const char *name, unsigned int *suffix) + const struct GNUNET_HashCode * nsid, const char *name, unsigned int *suffix) { - GNUNET_HashCode nh; + struct GNUNET_HashCode nh; uint64_t len; char *fn; struct GNUNET_DISK_FileHandle *fh; @@ -328,23 +334,23 @@ GNUNET_PSEUDONYM_name_uniquify (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_DISK_PERM_USER_WRITE); i = 0; idx = -1; - while ((len >= sizeof (GNUNET_HashCode)) && - (sizeof (GNUNET_HashCode) == - GNUNET_DISK_file_read (fh, &nh, sizeof (GNUNET_HashCode)))) + while ((len >= sizeof (struct GNUNET_HashCode)) && + (sizeof (struct GNUNET_HashCode) == + GNUNET_DISK_file_read (fh, &nh, sizeof (struct GNUNET_HashCode)))) { - if (0 == memcmp (&nh, nsid, sizeof (GNUNET_HashCode))) + if (0 == memcmp (&nh, nsid, sizeof (struct GNUNET_HashCode))) { idx = i; break; } i++; - len -= sizeof (GNUNET_HashCode); + len -= sizeof (struct GNUNET_HashCode); } if (idx == -1) { idx = i; - if (sizeof (GNUNET_HashCode) != - GNUNET_DISK_file_write (fh, nsid, sizeof (GNUNET_HashCode))) + if (sizeof (struct GNUNET_HashCode) != + GNUNET_DISK_file_write (fh, nsid, sizeof (struct GNUNET_HashCode))) LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "write", fn); } GNUNET_DISK_file_close (fh); @@ -376,7 +382,7 @@ GNUNET_PSEUDONYM_name_uniquify (const struct GNUNET_CONFIGURATION_Handle *cfg, */ int GNUNET_PSEUDONYM_get_info (const struct GNUNET_CONFIGURATION_Handle *cfg, - const GNUNET_HashCode * nsid, struct GNUNET_CONTAINER_MetaData **ret_meta, + const struct GNUNET_HashCode * nsid, struct GNUNET_CONTAINER_MetaData **ret_meta, int32_t *ret_rank, char **ret_name, int *name_is_a_dup) { struct GNUNET_CONTAINER_MetaData *meta; @@ -450,13 +456,13 @@ GNUNET_PSEUDONYM_get_info (const struct GNUNET_CONFIGURATION_Handle *cfg, */ int GNUNET_PSEUDONYM_name_to_id (const struct GNUNET_CONFIGURATION_Handle *cfg, - const char *ns_uname, GNUNET_HashCode * nsid) + const char *ns_uname, struct GNUNET_HashCode * nsid) { size_t slen; uint64_t len; unsigned int idx; char *name; - GNUNET_HashCode nh; + struct GNUNET_HashCode nh; char *fn; struct GNUNET_DISK_FileHandle *fh; @@ -476,7 +482,7 @@ GNUNET_PSEUDONYM_name_to_id (const struct GNUNET_CONFIGURATION_Handle *cfg, if ((GNUNET_OK != GNUNET_DISK_file_test (fn) || (GNUNET_OK != GNUNET_DISK_file_size (fn, &len, GNUNET_YES, GNUNET_YES))) || - ((idx + 1) * sizeof (GNUNET_HashCode) > len)) + ((idx + 1) * sizeof (struct GNUNET_HashCode) > len)) { GNUNET_free (fn); return GNUNET_SYSERR; @@ -487,10 +493,15 @@ GNUNET_PSEUDONYM_name_to_id (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE); GNUNET_free (fn); - GNUNET_DISK_file_seek (fh, idx * sizeof (GNUNET_HashCode), - GNUNET_DISK_SEEK_SET); - if (sizeof (GNUNET_HashCode) != - GNUNET_DISK_file_read (fh, nsid, sizeof (GNUNET_HashCode))) + if (GNUNET_SYSERR == + GNUNET_DISK_file_seek (fh, idx * sizeof (struct GNUNET_HashCode), + GNUNET_DISK_SEEK_SET)) + { + GNUNET_DISK_file_close (fh); + return GNUNET_SYSERR; + } + if (sizeof (struct GNUNET_HashCode) != + GNUNET_DISK_file_read (fh, nsid, sizeof (struct GNUNET_HashCode))) { GNUNET_DISK_file_close (fh); return GNUNET_SYSERR; @@ -535,7 +546,7 @@ list_pseudonym_helper (void *cls, const char *fullname) { struct ListPseudonymClosure *c = cls; int ret; - GNUNET_HashCode id; + struct GNUNET_HashCode id; int32_t rating; struct GNUNET_CONTAINER_MetaData *meta; const char *fn; @@ -612,7 +623,7 @@ GNUNET_PSEUDONYM_list_all (const struct GNUNET_CONFIGURATION_Handle *cfg, */ int GNUNET_PSEUDONYM_rank (const struct GNUNET_CONFIGURATION_Handle *cfg, - const GNUNET_HashCode * nsid, int delta) + const struct GNUNET_HashCode * nsid, int delta) { struct GNUNET_CONTAINER_MetaData *meta; int ret; @@ -648,7 +659,7 @@ GNUNET_PSEUDONYM_rank (const struct GNUNET_CONFIGURATION_Handle *cfg, */ int GNUNET_PSEUDONYM_set_info (const struct GNUNET_CONFIGURATION_Handle *cfg, - const GNUNET_HashCode * nsid, const char *name, + const struct GNUNET_HashCode * nsid, const char *name, const struct GNUNET_CONTAINER_MetaData *md, int rank) { GNUNET_assert (cfg != NULL); @@ -670,7 +681,7 @@ GNUNET_PSEUDONYM_set_info (const struct GNUNET_CONFIGURATION_Handle *cfg, */ void GNUNET_PSEUDONYM_add (const struct GNUNET_CONFIGURATION_Handle *cfg, - const GNUNET_HashCode * id, + const struct GNUNET_HashCode * id, const struct GNUNET_CONTAINER_MetaData *meta) { char *name; diff --git a/src/util/resolver.conf.in b/src/util/resolver.conf.in index 7abe1c9..cccb60c 100644 --- a/src/util/resolver.conf.in +++ b/src/util/resolver.conf.in @@ -3,7 +3,6 @@ AUTOSTART = YES @JAVAPORT@PORT = 2089 HOSTNAME = localhost HOME = $SERVICEHOME -CONFIG = $DEFAULTCONFIG BINARY = gnunet-service-resolver ACCEPT_FROM = 127.0.0.1; ACCEPT_FROM6 = ::1; diff --git a/src/util/resolver_api.c b/src/util/resolver_api.c index 87b76f1..2247b49 100644 --- a/src/util/resolver_api.c +++ b/src/util/resolver_api.c @@ -707,7 +707,7 @@ reconnect () (unsigned long long) backoff.rel_value); GNUNET_assert (NULL != resolver_cfg); r_task = GNUNET_SCHEDULER_add_delayed (backoff, &reconnect_task, NULL); - backoff = GNUNET_TIME_relative_multiply (backoff, 2); + backoff = GNUNET_TIME_STD_BACKOFF (backoff); } diff --git a/src/util/scheduler.c b/src/util/scheduler.c index 45cc020..0adf9f0 100644 --- a/src/util/scheduler.c +++ b/src/util/scheduler.c @@ -36,7 +36,7 @@ #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util-scheduler", syscall) -#ifdef LINUX +#if HAVE_EXECINFO_H #include "execinfo.h" /** @@ -565,22 +565,17 @@ run_ready (struct GNUNET_NETWORK_FDSet *rs, struct GNUNET_NETWORK_FDSet *ws) GNUNET_assert (pos != NULL); /* ready_count wrong? */ ready[p] = pos->next; ready_count--; - if (current_priority != pos->priority) - { - current_priority = pos->priority; - (void) GNUNET_OS_set_process_priority (GNUNET_OS_process_current (), - pos->priority); - } + current_priority = pos->priority; current_lifeness = pos->lifeness; active_task = pos; #if PROFILE_DELAYS if (GNUNET_TIME_absolute_get_duration (pos->start_time).rel_value > DELAY_THRESHOLD.rel_value) { - LOG (GNUNET_ERROR_TYPE_ERROR, "Task %llu took %llums to be scheduled\n", - pos->id, - (unsigned long long) - GNUNET_TIME_absolute_get_duration (pos->start_time).rel_value); + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Task %llu took %s to be scheduled\n", + (unsigned long long) pos->id, + GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (pos->start_time), GNUNET_YES)); } #endif tc.reason = pos->reason; @@ -727,6 +722,7 @@ GNUNET_SCHEDULER_run (GNUNET_SCHEDULER_Task task, void *task_cls) GNUNET_DISK_PIPE_END_READ); GNUNET_assert (pr != NULL); my_pid = getpid (); + LOG (GNUNET_ERROR_TYPE_DEBUG, "Registering signal handlers\n"); shc_int = GNUNET_SIGNAL_handler_install (SIGINT, &sighandler_shutdown); shc_term = GNUNET_SIGNAL_handler_install (SIGTERM, &sighandler_shutdown); #ifndef MINGW diff --git a/src/util/server.c b/src/util/server.c index 409e89f..fc5f263 100644 --- a/src/util/server.c +++ b/src/util/server.c @@ -297,11 +297,6 @@ struct GNUNET_SERVER_Client int receive_pending; /** - * Finish pending write when disconnecting? - */ - int finish_pending_write; - - /** * Persist the file handle for this client no matter what happens, * force the OS to close once the process actually dies. Should only * be used in special cases! @@ -334,43 +329,6 @@ process_listen_socket (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) /** - * Add a listen task with the scheduler for this server. - * - * @param server handle to our server for which we are adding the listen - * socket - */ -static void -schedule_listen_task (struct GNUNET_SERVER_Handle *server) -{ - struct GNUNET_NETWORK_FDSet *r; - unsigned int i; - - if (NULL == server->listen_sockets[0]) - return; /* nothing to do, no listen sockets! */ - if (NULL == server->listen_sockets[1]) - { - /* simplified method: no fd set needed; this is then much simpler and - much more efficient */ - server->listen_task = - GNUNET_SCHEDULER_add_read_net_with_priority (GNUNET_TIME_UNIT_FOREVER_REL, - GNUNET_SCHEDULER_PRIORITY_HIGH, - server->listen_sockets[0], - &process_listen_socket, server); - return; - } - r = GNUNET_NETWORK_fdset_create (); - i = 0; - while (NULL != server->listen_sockets[i]) - GNUNET_NETWORK_fdset_set (r, server->listen_sockets[i++]); - server->listen_task = - GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_HIGH, - GNUNET_TIME_UNIT_FOREVER_REL, r, NULL, - &process_listen_socket, server); - GNUNET_NETWORK_fdset_destroy (r); -} - - -/** * Scheduler says our listen socket is ready. Process it! * * @param cls handle to our server for which we are processing the listen @@ -389,7 +347,7 @@ process_listen_socket (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) { /* ignore shutdown, someone else will take care of it! */ - schedule_listen_task (server); + GNUNET_SERVER_resume (server); return; } i = 0; @@ -412,7 +370,7 @@ process_listen_socket (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) i++; } /* listen for more! */ - schedule_listen_task (server); + GNUNET_SERVER_resume (server); } @@ -426,7 +384,6 @@ process_listen_socket (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) static struct GNUNET_NETWORK_Handle * open_listen_socket (const struct sockaddr *serverAddr, socklen_t socklen) { - static int on = 1; struct GNUNET_NETWORK_Handle *sock; uint16_t port; int eno; @@ -454,20 +411,6 @@ open_listen_socket (const struct sockaddr *serverAddr, socklen_t socklen) errno = 0; return NULL; } - if (0 != port) - { - if (GNUNET_NETWORK_socket_setsockopt - (sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) != GNUNET_OK) - LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, - "setsockopt"); -#ifdef IPV6_V6ONLY - if ((AF_INET6 == serverAddr->sa_family) && - (GNUNET_NETWORK_socket_setsockopt - (sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof (on)) != GNUNET_OK)) - LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, - "setsockopt"); -#endif - } /* bind the socket */ if (GNUNET_OK != GNUNET_NETWORK_socket_bind (sock, serverAddr, socklen)) { @@ -493,10 +436,17 @@ open_listen_socket (const struct sockaddr *serverAddr, socklen_t socklen) "bind", port, (AF_INET == serverAddr->sa_family) ? "IPv4" : "IPv6"); else if (AF_UNIX == serverAddr->sa_family) - LOG (GNUNET_ERROR_TYPE_WARNING, - _("`%s' failed for `%s': address already in use\n"), "bind", - ((const struct sockaddr_un *) serverAddr)->sun_path); + { + const struct sockaddr_un *un = (const struct sockaddr_un *) serverAddr; + unsigned int off = 0; + if ('\0' == un->sun_path[0]) + off = 1; /* some UNIXPATHs start with 0 */ + LOG (GNUNET_ERROR_TYPE_WARNING, + _("`%s' failed for `%.*s': address already in use\n"), "bind", + (int) ((sizeof (un->sun_path) - off)), + (&un->sun_path[off])); + } } GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock)); errno = eno; @@ -544,7 +494,7 @@ GNUNET_SERVER_create_with_sockets (GNUNET_CONNECTION_AccessCheck access, server->access_cls = access_cls; server->require_found = require_found; if (NULL != lsocks) - schedule_listen_task (server); + GNUNET_SERVER_resume (server); return server; } @@ -679,6 +629,60 @@ test_monitor_clients (struct GNUNET_SERVER_Handle *server) /** + * Suspend accepting connections from the listen socket temporarily. + * + * @param server server to stop accepting connections. + */ +void +GNUNET_SERVER_suspend (struct GNUNET_SERVER_Handle *server) +{ + if (GNUNET_SCHEDULER_NO_TASK != server->listen_task) + { + GNUNET_SCHEDULER_cancel (server->listen_task); + server->listen_task = GNUNET_SCHEDULER_NO_TASK; + } +} + + +/** + * Resume accepting connections from the listen socket. + * + * @param server server to stop accepting connections. + */ +void +GNUNET_SERVER_resume (struct GNUNET_SERVER_Handle *server) +{ + struct GNUNET_NETWORK_FDSet *r; + unsigned int i; + + if (NULL == server->listen_sockets) + return; + if (NULL == server->listen_sockets[0]) + return; /* nothing to do, no listen sockets! */ + if (NULL == server->listen_sockets[1]) + { + /* simplified method: no fd set needed; this is then much simpler and + much more efficient */ + server->listen_task = + GNUNET_SCHEDULER_add_read_net_with_priority (GNUNET_TIME_UNIT_FOREVER_REL, + GNUNET_SCHEDULER_PRIORITY_HIGH, + server->listen_sockets[0], + &process_listen_socket, server); + return; + } + r = GNUNET_NETWORK_fdset_create (); + i = 0; + while (NULL != server->listen_sockets[i]) + GNUNET_NETWORK_fdset_set (r, server->listen_sockets[i++]); + server->listen_task = + GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_HIGH, + GNUNET_TIME_UNIT_FOREVER_REL, r, NULL, + &process_listen_socket, server); + GNUNET_NETWORK_fdset_destroy (r); +} + + +/** * Stop the listen socket and get ready to shutdown the server * once only 'monitor' clients are left. * @@ -823,11 +827,9 @@ warn_no_receive_done (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) &warn_no_receive_done, client); if (0 == (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) LOG (GNUNET_ERROR_TYPE_WARNING, - _ - ("Processing code for message of type %u did not call GNUNET_SERVER_receive_done after %llums\n"), + _("Processing code for message of type %u did not call `GNUNET_SERVER_receive_done' after %s\n"), (unsigned int) client->warn_type, - (unsigned long long) - GNUNET_TIME_absolute_get_duration (client->warn_start).rel_value); + GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (client->warn_start), GNUNET_YES)); } diff --git a/src/util/service.c b/src/util/service.c index 6a6fb6c..b9050f8 100644 --- a/src/util/service.c +++ b/src/util/service.c @@ -36,6 +36,12 @@ #include "gnunet_server_lib.h" #include "gnunet_service_lib.h" +#if HAVE_MALLINFO +#include <malloc.h> +#include "gauger.h" +#endif + + #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall) @@ -62,6 +68,7 @@ struct IPv4NetworkSet }; /** + * @brief network in CIDR notation for IPV6. */ struct IPv6NetworkSet @@ -653,10 +660,12 @@ check_access (void *cls, const struct GNUNET_CONNECTION_Credentials *uc, if (GNUNET_YES == sctx->match_uid) { /* UID match required */ - ret = (NULL != uc) && (uc->uid == geteuid ()); + ret = (NULL != uc) && ( (0 == uc->uid) || (uc->uid == geteuid ()) ); } else if ( (GNUNET_YES == sctx->match_gid) && - ( (NULL == uc) || (uc->uid != geteuid ()) ) ) + ( (NULL == uc) || + ( (0 != uc->uid) && + (uc->uid != geteuid ()) ) ) ) { /* group match required and UID does not match */ if (NULL == uc) @@ -931,9 +940,14 @@ GNUNET_SERVICE_get_server_addresses (const char *service_name, port = 0; if (GNUNET_CONFIGURATION_have_value (cfg, service_name, "PORT")) { - GNUNET_break (GNUNET_OK == - GNUNET_CONFIGURATION_get_value_number (cfg, service_name, - "PORT", &port)); + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_number (cfg, service_name, + "PORT", &port)) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + _("Require valid port number for service `%s' in configuration!\n"), + service_name); + } if (port > 65535) { LOG (GNUNET_ERROR_TYPE_ERROR, @@ -968,12 +982,15 @@ GNUNET_SERVICE_get_server_addresses (const char *service_name, { LOG (GNUNET_ERROR_TYPE_WARNING, _("UNIXPATH `%s' too long, maximum length is %llu\n"), unixpath, - sizeof (s_un.sun_path)); - GNUNET_free_non_null (hostname); - GNUNET_free (unixpath); - return GNUNET_SYSERR; - } + (unsigned long long) sizeof (s_un.sun_path)); + unixpath = GNUNET_NETWORK_shorten_unixpath (unixpath); + LOG (GNUNET_ERROR_TYPE_INFO, + _("Using `%s' instead\n"), unixpath); + } + } + if (NULL != unixpath) + { desc = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_STREAM, 0); if (NULL == desc) { @@ -1487,6 +1504,8 @@ service_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) struct GNUNET_SERVICE_Context *sctx = cls; unsigned int i; + if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) + return; GNUNET_RESOLVER_connect (sctx->cfg); if (NULL != sctx->lsocks) sctx->server = @@ -1712,6 +1731,7 @@ GNUNET_SERVICE_run (int argc, char *const *argv, const char *service_name, #define HANDLE_ERROR do { GNUNET_break (0); goto shutdown; } while (0) int err; + int ret; char *cfg_fn; char *loglev; char *logfile; @@ -1731,7 +1751,7 @@ GNUNET_SERVICE_run (int argc, char *const *argv, const char *service_name, GNUNET_GETOPT_OPTION_HELP (NULL), GNUNET_GETOPT_OPTION_LOGLEVEL (&loglev), GNUNET_GETOPT_OPTION_LOGFILE (&logfile), - GNUNET_GETOPT_OPTION_VERSION (PACKAGE_VERSION), + GNUNET_GETOPT_OPTION_VERSION (PACKAGE_VERSION " " VCS_VERSION), GNUNET_GETOPT_OPTION_END }; err = 1; @@ -1748,14 +1768,29 @@ GNUNET_SERVICE_run (int argc, char *const *argv, const char *service_name, sctx.task_cls = task_cls; sctx.service_name = service_name; sctx.cfg = cfg = GNUNET_CONFIGURATION_create (); + /* setup subsystems */ - if (GNUNET_SYSERR == - GNUNET_GETOPT_run (service_name, service_options, argc, argv)) + ret = GNUNET_GETOPT_run (service_name, service_options, argc, argv); + if (GNUNET_SYSERR == ret) goto shutdown; + if (GNUNET_NO == ret) + { + err = 0; + goto shutdown; + } if (GNUNET_OK != GNUNET_log_setup (service_name, loglev, logfile)) HANDLE_ERROR; - if (GNUNET_OK != GNUNET_CONFIGURATION_load (cfg, cfg_fn)) - goto shutdown; + if (GNUNET_YES == + GNUNET_DISK_file_test (cfg_fn)) + (void) GNUNET_CONFIGURATION_load (cfg, cfg_fn); + else + { + (void) GNUNET_CONFIGURATION_load (cfg, NULL); + if (0 != strcmp (cfg_fn, GNUNET_DEFAULT_USER_CONFIG_FILE)) + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Could not access configuration file `%s'\n"), + cfg_fn); + } if (GNUNET_OK != setup_service (&sctx)) goto shutdown; if ((1 == do_daemonize) && (GNUNET_OK != detach_terminal (&sctx))) @@ -1791,7 +1826,26 @@ shutdown: LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "write"); GNUNET_break (0 == CLOSE (sctx.ready_confirm_fd)); } - +#if HAVE_MALLINFO + { + char *counter; + + if ( (GNUNET_YES == + GNUNET_CONFIGURATION_have_value (sctx.cfg, service_name, + "GAUGER_HEAP")) && + (GNUNET_OK == + GNUNET_CONFIGURATION_get_value_string (sctx.cfg, service_name, + "GAUGER_HEAP", + &counter)) ) + { + struct mallinfo mi; + + mi = mallinfo (); + GAUGER (service_name, counter, mi.usmblks, "blocks"); + GNUNET_free (counter); + } + } +#endif GNUNET_SPEEDUP_stop_ (); GNUNET_CONFIGURATION_destroy (cfg); i = 0; @@ -1891,6 +1945,26 @@ GNUNET_SERVICE_stop (struct GNUNET_SERVICE_Context *sctx) { unsigned int i; +#if HAVE_MALLINFO + { + char *counter; + + if ( (GNUNET_YES == + GNUNET_CONFIGURATION_have_value (sctx->cfg, sctx->service_name, + "GAUGER_HEAP")) && + (GNUNET_OK == + GNUNET_CONFIGURATION_get_value_string (sctx->cfg, sctx->service_name, + "GAUGER_HEAP", + &counter)) ) + { + struct mallinfo mi; + + mi = mallinfo (); + GAUGER (sctx->service_name, counter, mi.usmblks, "blocks"); + GNUNET_free (counter); + } + } +#endif if (GNUNET_SCHEDULER_NO_TASK != sctx->shutdown_task) { GNUNET_SCHEDULER_cancel (sctx->shutdown_task); diff --git a/src/util/speedup.c b/src/util/speedup.c index 0a005c0..e5f71d0 100644 --- a/src/util/speedup.c +++ b/src/util/speedup.c @@ -83,8 +83,9 @@ GNUNET_SPEEDUP_stop_ ( ) GNUNET_SCHEDULER_cancel (speedup_task); speedup_task = GNUNET_SCHEDULER_NO_TASK; } - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Stopped execution speed up\n"); + if ((0 != interval.rel_value) && (0 != delta.rel_value)) + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Stopped execution speed up\n"); } diff --git a/src/util/strings.c b/src/util/strings.c index 11134f1..70986a9 100644 --- a/src/util/strings.c +++ b/src/util/strings.c @@ -32,6 +32,8 @@ #include "gnunet_common.h" #include "gnunet_strings_lib.h" #include <unicase.h> +#include <unistr.h> +#include <uniconv.h> #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) @@ -289,17 +291,25 @@ GNUNET_STRINGS_fancy_time_to_relative (const char *fancy_time, { "ms", 1}, { "s", 1000}, { "\"", 1000}, + { "m", 60 * 1000}, { "min", 60 * 1000}, { "minutes", 60 * 1000}, { "'", 60 * 1000}, { "h", 60 * 60 * 1000}, { "d", 24 * 60 * 60 * 1000}, + { "day", 24 * 60 * 60 * 1000}, + { "days", 24 * 60 * 60 * 1000}, { "a", 31536000000LL /* year */ }, { NULL, 0} }; int ret; unsigned long long val; + if (0 == strcasecmp ("forever", fancy_time)) + { + *rtime = GNUNET_TIME_UNIT_FOREVER_REL; + return GNUNET_OK; + } ret = convert_with_table (fancy_time, table, &val); @@ -307,6 +317,48 @@ GNUNET_STRINGS_fancy_time_to_relative (const char *fancy_time, return ret; } + +/** + * Convert a given fancy human-readable time to our internal + * representation. + * + * @param fancy_time human readable string (i.e. %Y-%m-%d %H:%M:%S) + * @param atime set to the absolute time + * @return GNUNET_OK on success, GNUNET_SYSERR on error + */ +int +GNUNET_STRINGS_fancy_time_to_absolute (const char *fancy_time, + struct GNUNET_TIME_Absolute *atime) +{ + struct tm tv; + time_t t; + + if (0 == strcasecmp ("end of time", fancy_time)) + { + *atime = GNUNET_TIME_UNIT_FOREVER_ABS; + return GNUNET_OK; + } + memset (&tv, 0, sizeof (tv)); + if ( (NULL == strptime (fancy_time, "%a %b %d %H:%M:%S %Y", &tv)) && + (NULL == strptime (fancy_time, "%c", &tv)) && + (NULL == strptime (fancy_time, "%Ec", &tv)) && + (NULL == strptime (fancy_time, "%Y-%m-%d %H:%M:%S", &tv)) && + (NULL == strptime (fancy_time, "%Y-%m-%d %H:%M", &tv)) && + (NULL == strptime (fancy_time, "%x", &tv)) && + (NULL == strptime (fancy_time, "%Ex", &tv)) && + (NULL == strptime (fancy_time, "%Y-%m-%d", &tv)) && + (NULL == strptime (fancy_time, "%Y-%m", &tv)) && + (NULL == strptime (fancy_time, "%Y", &tv)) ) + return GNUNET_SYSERR; + t = mktime (&tv); + atime->abs_value = (uint64_t) ((uint64_t) t * 1000LL); +#if LINUX + atime->abs_value -= 1000LL * timezone; +#endif + return GNUNET_OK; +} + + /** * Convert the len characters long character sequence * given in input that is in the given input charset @@ -319,58 +371,51 @@ char * GNUNET_STRINGS_conv (const char *input, size_t len, const char *input_charset, const char *output_charset) { char *ret; - -#if ENABLE_NLS && HAVE_ICONV - size_t tmpSize; - size_t finSize; - char *tmp; - char *itmp; - iconv_t cd; - - cd = iconv_open (output_charset, input_charset); - if (cd == (iconv_t) - 1) + uint8_t *u8_string; + char *encoded_string; + size_t u8_string_length; + size_t encoded_string_length; + + u8_string = u8_conv_from_encoding (input_charset, + iconveh_error, + input, len, + NULL, NULL, + &u8_string_length); + if (NULL == u8_string) { - LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "iconv_open"); - LOG (GNUNET_ERROR_TYPE_WARNING, _("Character sets requested were `%s'->`%s'\n"), - input_charset, output_charset); - ret = GNUNET_malloc (len + 1); - memcpy (ret, input, len); - ret[len] = '\0'; - return ret; + LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "u8_conv_from_encoding"); + goto fail; } - tmpSize = 3 * len + 4; - tmp = GNUNET_malloc (tmpSize); - itmp = tmp; - finSize = tmpSize; - if (iconv (cd, -#if FREEBSD || DARWIN || WINDOWS - (const char **) &input, -#else - (char **) &input, -#endif - &len, &itmp, &finSize) == SIZE_MAX) + if (0 == strcmp (output_charset, "UTF-8")) { - LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "iconv"); - iconv_close (cd); - GNUNET_free (tmp); - ret = GNUNET_malloc (len + 1); - memcpy (ret, input, len); - ret[len] = '\0'; + ret = GNUNET_malloc (u8_string_length + 1); + memcpy (ret, u8_string, u8_string_length); + ret[u8_string_length] = '\0'; + free (u8_string); return ret; } - ret = GNUNET_malloc (tmpSize - finSize + 1); - memcpy (ret, tmp, tmpSize - finSize); - ret[tmpSize - finSize] = '\0'; - GNUNET_free (tmp); - if (0 != iconv_close (cd)) - LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "iconv_close"); + encoded_string = u8_conv_to_encoding (output_charset, iconveh_error, + u8_string, u8_string_length, + NULL, NULL, + &encoded_string_length); + free (u8_string); + if (NULL == encoded_string) + { + LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "u8_conv_to_encoding"); + goto fail; + } + ret = GNUNET_malloc (encoded_string_length + 1); + memcpy (ret, encoded_string, encoded_string_length); + ret[encoded_string_length] = '\0'; + free (encoded_string); return ret; -#else + fail: + LOG (GNUNET_ERROR_TYPE_WARNING, _("Character sets requested were `%s'->`%s'\n"), + "UTF-8", output_charset); ret = GNUNET_malloc (len + 1); memcpy (ret, input, len); ret[len] = '\0'; return ret; -#endif } @@ -388,10 +433,11 @@ GNUNET_STRINGS_to_utf8 (const char *input, size_t len, const char *charset) return GNUNET_STRINGS_conv (input, len, charset, "UTF-8"); } + /** * Convert the len bytes-long UTF-8 string * given in input to the given charset. - + * * @return the converted string (0-terminated), * if conversion fails, a copy of the orignal * string is returned. @@ -402,6 +448,7 @@ GNUNET_STRINGS_from_utf8 (const char *input, size_t len, const char *charset) return GNUNET_STRINGS_conv (input, len, "UTF-8", charset); } + /** * Convert the utf-8 input string to lowercase * Output needs to be allocated appropriately @@ -422,6 +469,7 @@ GNUNET_STRINGS_utf8_tolower(const char* input, char** output) free(tmp_in); } + /** * Convert the utf-8 input string to uppercase * Output needs to be allocated appropriately @@ -454,7 +502,6 @@ char * GNUNET_STRINGS_filename_expand (const char *fil) { char *buffer; - #ifndef MINGW size_t len; size_t n; @@ -563,67 +610,83 @@ GNUNET_STRINGS_filename_expand (const char *fil) /** * Give relative time in human-readable fancy format. + * This is one of the very few calls in the entire API that is + * NOT reentrant! * * @param delta time in milli seconds + * @param do_round are we allowed to round a bit? * @return time as human-readable string */ -char * -GNUNET_STRINGS_relative_time_to_string (struct GNUNET_TIME_Relative delta) +const char * +GNUNET_STRINGS_relative_time_to_string (struct GNUNET_TIME_Relative delta, + int do_round) { + static char buf[128]; const char *unit = _( /* time unit */ "ms"); - char *ret; uint64_t dval = delta.rel_value; - if (delta.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value) - return GNUNET_strdup (_("eternity")); - if (dval > 5 * 1000) + if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value == delta.rel_value) + return _("forever"); + if (0 == delta.rel_value) + return _("0 ms"); + if ( ( (GNUNET_YES == do_round) && + (dval > 5 * 1000) ) || + (0 == (dval % 1000) )) { dval = dval / 1000; unit = _( /* time unit */ "s"); - if (dval > 5 * 60) + if ( ( (GNUNET_YES == do_round) && + (dval > 5 * 60) ) || + (0 == (dval % 60) ) ) { dval = dval / 60; unit = _( /* time unit */ "m"); - if (dval > 5 * 60) + if ( ( (GNUNET_YES == do_round) && + (dval > 5 * 60) ) || + (0 == (dval % 60) )) { dval = dval / 60; unit = _( /* time unit */ "h"); - if (dval > 5 * 24) - { + if ( ( (GNUNET_YES == do_round) && + (dval > 5 * 24) ) || + (0 == (dval % 24)) ) + { dval = dval / 24; - unit = _( /* time unit */ " days"); + if (1 == dval) + unit = _( /* time unit */ "day"); + else + unit = _( /* time unit */ "days"); } } } } - GNUNET_asprintf (&ret, "%llu %s", dval, unit); - return ret; + GNUNET_snprintf (buf, sizeof (buf), + "%llu %s", dval, unit); + return buf; } /** - * "man ctime_r", except for GNUnet time; also, unlike ctime, the - * return value does not include the newline character. + * "asctime", except for GNUnet time. + * This is one of the very few calls in the entire API that is + * NOT reentrant! * * @param t time to convert * @return absolute time in human-readable format */ -char * +const char * GNUNET_STRINGS_absolute_time_to_string (struct GNUNET_TIME_Absolute t) { + static char buf[255]; time_t tt; - char *ret; + struct tm *tp; if (t.abs_value == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value) - return GNUNET_strdup (_("end of time")); + return _("end of time"); tt = t.abs_value / 1000; -#ifdef ctime_r - ret = ctime_r (&tt, GNUNET_malloc (32)); -#else - ret = GNUNET_strdup (ctime (&tt)); -#endif - ret[strlen (ret) - 1] = '\0'; - return ret; + tp = gmtime (&tt); + strftime (buf, sizeof (buf), "%a %b %d %H:%M:%S %Y", tp); + return buf; } @@ -919,7 +982,6 @@ GNUNET_STRINGS_path_is_absolute (const char *filename, int can_be_uri, } else { - is_uri = GNUNET_NO; if (r_is_uri) *r_is_uri = GNUNET_NO; } @@ -981,7 +1043,6 @@ GNUNET_STRINGS_check_filename (const char *filename, } - /** * Tries to convert 'zt_addr' string to an IPv6 address. * The string is expected to have the format "[ABCD::01]:80". @@ -1113,4 +1174,95 @@ GNUNET_STRINGS_to_address_ip (const char *addr, return GNUNET_STRINGS_to_address_ipv4 (addr, addrlen, (struct sockaddr_in *) r_buf); } + +/** + * Makes a copy of argv that consists of a single memory chunk that can be + * freed with a single call to GNUNET_free (); + */ +static char *const * +_make_continuous_arg_copy (int argc, char *const *argv) +{ + size_t argvsize = 0; + int i; + char **new_argv; + char *p; + for (i = 0; i < argc; i++) + argvsize += strlen (argv[i]) + 1 + sizeof (char *); + new_argv = GNUNET_malloc (argvsize + sizeof (char *)); + p = (char *) &new_argv[argc + 1]; + for (i = 0; i < argc; i++) + { + new_argv[i] = p; + strcpy (p, argv[i]); + p += strlen (argv[i]) + 1; + } + new_argv[argc] = NULL; + return (char *const *) new_argv; +} + + +/** + * Returns utf-8 encoded arguments. + * Does nothing (returns a copy of argc and argv) on any platform + * other than W32. + * Returned argv has u8argv[u8argc] == NULL. + * Returned argv is a single memory block, and can be freed with a single + * GNUNET_free () call. + * + * @param argc argc (as given by main()) + * @param argv argv (as given by main()) + * @param u8argc a location to store new argc in (though it's th same as argc) + * @param u8argv a location to store new argv in + * @return GNUNET_OK on success, GNUNET_SYSERR on failure + */ +int +GNUNET_STRINGS_get_utf8_args (int argc, char *const *argv, int *u8argc, char *const **u8argv) +{ +#if WINDOWS + wchar_t *wcmd; + wchar_t **wargv; + int wargc; + int i; + char **split_u8argv; + + wcmd = GetCommandLineW (); + if (NULL == wcmd) + return GNUNET_SYSERR; + wargv = CommandLineToArgvW (wcmd, &wargc); + if (NULL == wargv) + return GNUNET_SYSERR; + + split_u8argv = GNUNET_malloc (argc * sizeof (char *)); + + for (i = 0; i < wargc; i++) + { + size_t strl; + /* Hopefully it will allocate us NUL-terminated strings... */ + split_u8argv[i] = (char *) u16_to_u8 (wargv[i], wcslen (wargv[i]) + 1, NULL, &strl); + if (split_u8argv == NULL) + { + int j; + for (j = 0; j < i; j++) + free (split_u8argv[j]); + GNUNET_free (split_u8argv); + LocalFree (wargv); + return GNUNET_SYSERR; + } + } + + *u8argv = _make_continuous_arg_copy (wargc, split_u8argv); + *u8argc = wargc; + + for (i = 0; i < wargc; i++) + free (split_u8argv[i]); + free (split_u8argv); + return GNUNET_OK; +#else + char *const *new_argv = (char *const *) _make_continuous_arg_copy (argc, argv); + *u8argv = new_argv; + *u8argc = argc; + return GNUNET_OK; +#endif +} + /* end of strings.c */ diff --git a/src/util/test_client.c b/src/util/test_client.c index 54881b2..7d7ec8c 100644 --- a/src/util/test_client.c +++ b/src/util/test_client.c @@ -29,7 +29,6 @@ #include "gnunet_server_lib.h" #include "gnunet_time_lib.h" -#define VERBOSE GNUNET_NO #define PORT 14325 @@ -174,15 +173,14 @@ task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) } -/** - * Main method, starts scheduler with task1, - * checks that "ok" is correct at the end. - */ -static int -check () +int +main (int argc, char *argv[]) { int ok; + GNUNET_log_setup ("test_client", + "WARNING", + NULL); cfg = GNUNET_CONFIGURATION_create (); GNUNET_CONFIGURATION_set_value_number (cfg, MYNAME, "PORT", PORT); GNUNET_CONFIGURATION_set_value_string (cfg, MYNAME, "HOSTNAME", "localhost"); @@ -194,21 +192,4 @@ check () return ok; } -int -main (int argc, char *argv[]) -{ - int ret = 0; - - GNUNET_log_setup ("test_client", -#if VERBOSE - "DEBUG", -#else - "WARNING", -#endif - NULL); - ret += check (); - - return ret; -} - /* end of test_client.c */ diff --git a/src/util/test_common_logging_runtime_loglevels.c b/src/util/test_common_logging_runtime_loglevels.c index b914ae1..58b722b 100644 --- a/src/util/test_common_logging_runtime_loglevels.c +++ b/src/util/test_common_logging_runtime_loglevels.c @@ -42,6 +42,8 @@ static struct GNUNET_DISK_PipeHandle *pipe_stdout; static GNUNET_SCHEDULER_TaskIdentifier die_task; +static GNUNET_SCHEDULER_TaskIdentifier read_task; + static void runone (void); @@ -50,13 +52,21 @@ end_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ending phase %d, ok is %d\n", phase, ok); - if (0 != GNUNET_OS_process_kill (proc, SIGTERM)) + if (NULL != proc) + { + if (0 != GNUNET_OS_process_kill (proc, SIGTERM)) + { + GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); + } + GNUNET_OS_process_wait (proc); + GNUNET_OS_process_destroy (proc); + proc = NULL; + } + if (GNUNET_SCHEDULER_NO_TASK != read_task) { - GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); + GNUNET_SCHEDULER_cancel (read_task); + read_task = GNUNET_SCHEDULER_NO_TASK; } - GNUNET_OS_process_wait (proc); - GNUNET_OS_process_destroy (proc); - proc = NULL; GNUNET_DISK_pipe_close (pipe_stdout); if (ok == 1) { @@ -158,12 +168,13 @@ int bytes; static void read_call (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { - struct GNUNET_DISK_FileHandle *stdout_read_handle = cls; + const struct GNUNET_DISK_FileHandle *stdout_read_handle = cls; char level[8]; long delay; long delays[8]; int rd; + read_task = GNUNET_SCHEDULER_NO_TASK; rd = GNUNET_DISK_file_read (stdout_read_handle, buf_ptr, sizeof (buf) - bytes); if (rd > 0) @@ -173,9 +184,9 @@ read_call (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) #if VERBOSE FPRINTF (stderr, "got %d bytes, reading more\n", rd); #endif - GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, - stdout_read_handle, &read_call, - (void *) stdout_read_handle); + read_task = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, + stdout_read_handle, &read_call, + (void*) stdout_read_handle); return; } @@ -314,13 +325,14 @@ runone () break; } - proc = GNUNET_OS_start_process (GNUNET_NO, NULL, pipe_stdout, + proc = GNUNET_OS_start_process (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, pipe_stdout, #if MINGW "test_common_logging_dummy", #else "./test_common_logging_dummy", #endif "test_common_logging_dummy", NULL); + GNUNET_assert (NULL != proc); putenv ("GNUNET_FORCE_LOG="); putenv ("GNUNET_LOG="); @@ -339,9 +351,9 @@ runone () buf_ptr = buf; memset (&buf, 0, sizeof (buf)); - GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, - stdout_read_handle, &read_call, - (void *) stdout_read_handle); + read_task = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, + stdout_read_handle, &read_call, + (void*) stdout_read_handle); } static void @@ -351,34 +363,16 @@ task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) runone (); } -/** - * Main method, starts scheduler with task1, - * checks that "ok" is correct at the end. - */ -static int -check () -{ - ok = 1; - GNUNET_SCHEDULER_run (&task, &ok); - return ok; -} - int main (int argc, char *argv[]) { - int ret; - GNUNET_log_setup ("test-common-logging-runtime-loglevels", -#if VERBOSE - "DEBUG", -#else "WARNING", -#endif NULL); - ret = check (); - - return ret; + ok = 1; + GNUNET_SCHEDULER_run (&task, &ok); + return ok; } /* end of test_common_logging_runtime_loglevels.c */ diff --git a/src/util/test_configuration.c b/src/util/test_configuration.c index 1242a5c..62ad5fa 100644 --- a/src/util/test_configuration.c +++ b/src/util/test_configuration.c @@ -231,7 +231,8 @@ checkDiffs (struct GNUNET_CONFIGURATION_Handle *cfgDefault, int option) /* Compare the dumped configuration with modifications done */ cfg = GNUNET_CONFIGURATION_create (); GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_parse (cfg, diffsFileName)); - remove (diffsFileName); + if (0 != remove (diffsFileName)) + GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "remove", diffsFileName); cbData.callBackOption = COMPARE; cbData.cfgDiffs = cfgDiffs; GNUNET_CONFIGURATION_iterate (cfg, diffsCallBack, &cbData); diff --git a/src/util/test_connection.c b/src/util/test_connection.c index 4568f8e..e129c80 100644 --- a/src/util/test_connection.c +++ b/src/util/test_connection.c @@ -27,8 +27,6 @@ #include "gnunet_scheduler_lib.h" #include "gnunet_time_lib.h" -#define VERBOSE GNUNET_NO - #define PORT 12435 @@ -80,17 +78,13 @@ receive_check (void *cls, const void *buf, size_t available, { int *ok = cls; -#if VERBOSE GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Receive validates incoming data\n"); -#endif GNUNET_assert (buf != NULL); /* no timeout */ if (0 == memcmp (&"Hello World"[sofar], buf, available)) sofar += available; if (sofar < 12) { -#if VERBOSE GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Receive needs more data\n"); -#endif GNUNET_CONNECTION_receive (asock, 1024, GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5), &receive_check, @@ -98,9 +92,7 @@ receive_check (void *cls, const void *buf, size_t available, } else { -#if VERBOSE GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Receive closes accepted socket\n"); -#endif *ok = 0; GNUNET_CONNECTION_destroy (asock); GNUNET_CONNECTION_destroy (csock); @@ -111,41 +103,33 @@ receive_check (void *cls, const void *buf, size_t available, static void run_accept (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { -#if VERBOSE GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test accepts connection\n"); -#endif asock = GNUNET_CONNECTION_create_from_accept (NULL, NULL, ls); GNUNET_assert (asock != NULL); GNUNET_assert (GNUNET_YES == GNUNET_CONNECTION_check (asock)); -#if VERBOSE GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test destroys listen socket\n"); -#endif GNUNET_CONNECTION_destroy (lsock); -#if VERBOSE GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test asks to receive on accepted socket\n"); -#endif GNUNET_CONNECTION_receive (asock, 1024, GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5), &receive_check, cls); } + static size_t make_hello (void *cls, size_t size, void *buf) { -#if VERBOSE GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test prepares to transmit on connect socket\n"); -#endif GNUNET_assert (size >= 12); strcpy ((char *) buf, "Hello World"); -#if VERBOSE GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test destroys client socket\n"); -#endif return 12; } + static void task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { @@ -154,30 +138,26 @@ task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) GNUNET_assert (lsock != NULL); csock = GNUNET_CONNECTION_create_from_connect (cfg, "localhost", PORT); GNUNET_assert (csock != NULL); -#if VERBOSE GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test asks for write notification\n"); -#endif GNUNET_assert (NULL != GNUNET_CONNECTION_notify_transmit_ready (csock, 12, GNUNET_TIME_UNIT_SECONDS, &make_hello, NULL)); -#if VERBOSE GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test prepares to accept\n"); -#endif GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, ls, &run_accept, cls); } -/** - * Main method, starts scheduler with task , - * checks that "ok" is correct at the end. - */ -static int -check () +int +main (int argc, char *argv[]) { int ok; + GNUNET_log_setup ("test_connection", + "WARNING", + NULL); + ok = 1; cfg = GNUNET_CONFIGURATION_create (); GNUNET_CONFIGURATION_set_value_string (cfg, "resolver", "HOSTNAME", @@ -187,22 +167,4 @@ check () return ok; } - - -int -main (int argc, char *argv[]) -{ - int ret = 0; - - GNUNET_log_setup ("test_connection", -#if VERBOSE - "DEBUG", -#else - "WARNING", -#endif - NULL); - ret += check (); - return ret; -} - /* end of test_connection.c */ diff --git a/src/util/test_connection_addressing.c b/src/util/test_connection_addressing.c index ba7acae..e5c8ede 100644 --- a/src/util/test_connection_addressing.c +++ b/src/util/test_connection_addressing.c @@ -27,7 +27,6 @@ #include "gnunet_scheduler_lib.h" #include "gnunet_time_lib.h" -#define VERBOSE GNUNET_NO #define PORT 12435 @@ -174,36 +173,17 @@ task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) } -/** - * Main method, starts scheduler with task , - * checks that "ok" is correct at the end. - */ -static int -check () -{ - int ok; - - ok = 1; - GNUNET_SCHEDULER_run (&task, &ok); - return ok; -} - - - int main (int argc, char *argv[]) { - int ret = 0; + int ok; GNUNET_log_setup ("test_connection_addressing", -#if VERBOSE - "DEBUG", -#else "WARNING", -#endif NULL); - ret += check (); - return ret; + ok = 1; + GNUNET_SCHEDULER_run (&task, &ok); + return ok; } /* end of test_connection_addressing.c */ diff --git a/src/util/test_connection_receive_cancel.c b/src/util/test_connection_receive_cancel.c index 93fcd5f..9049034 100644 --- a/src/util/test_connection_receive_cancel.c +++ b/src/util/test_connection_receive_cancel.c @@ -27,8 +27,6 @@ #include "gnunet_scheduler_lib.h" #include "gnunet_time_lib.h" -#define VERBOSE GNUNET_NO - #define PORT 12435 diff --git a/src/util/test_connection_timeout.c b/src/util/test_connection_timeout.c index c0597b2..8d3f775 100644 --- a/src/util/test_connection_timeout.c +++ b/src/util/test_connection_timeout.c @@ -27,8 +27,6 @@ #include "gnunet_scheduler_lib.h" #include "gnunet_time_lib.h" -#define VERBOSE GNUNET_NO - #define PORT 12435 static struct GNUNET_CONNECTION_Handle *csock; @@ -78,18 +76,14 @@ send_kilo (void *cls, size_t size, void *buf) if (size == 0) { -#if VERBOSE GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got the desired timeout!\n"); -#endif GNUNET_assert (buf == NULL); *ok = 0; GNUNET_CONNECTION_destroy (lsock); GNUNET_CONNECTION_destroy (csock); return 0; } -#if VERBOSE GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending kilo to fill buffer.\n"); -#endif GNUNET_assert (size >= 1024); memset (buf, 42, 1024); @@ -117,15 +111,15 @@ task_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) } - -/** - * Main method, starts scheduler with task_timeout. - */ -static int -check_timeout () +int +main (int argc, char *argv[]) { int ok; + GNUNET_log_setup ("test_connection_timeout", + "WARNING", + NULL); + ok = 1; cfg = GNUNET_CONFIGURATION_create (); GNUNET_CONFIGURATION_set_value_string (cfg, "resolver", "HOSTNAME", @@ -135,20 +129,4 @@ check_timeout () return ok; } -int -main (int argc, char *argv[]) -{ - int ret = 0; - - GNUNET_log_setup ("test_connection_timeout", -#if VERBOSE - "DEBUG", -#else - "WARNING", -#endif - NULL); - ret += check_timeout (); - return ret; -} - /* end of test_connection_timeout.c */ diff --git a/src/util/test_connection_timeout_no_connect.c b/src/util/test_connection_timeout_no_connect.c index 2e8f9be..50eaf70 100644 --- a/src/util/test_connection_timeout_no_connect.c +++ b/src/util/test_connection_timeout_no_connect.c @@ -27,8 +27,6 @@ #include "gnunet_scheduler_lib.h" #include "gnunet_time_lib.h" -#define VERBOSE GNUNET_NO - #define PORT 13425 static struct GNUNET_CONNECTION_Handle *csock; @@ -40,10 +38,7 @@ handle_timeout (void *cls, size_t size, void *buf) { int *ok = cls; -#if VERBOSE GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received timeout signal.\n"); -#endif - GNUNET_assert (size == 0); GNUNET_assert (buf == NULL); *ok = 0; @@ -64,15 +59,14 @@ task_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) } - -/** - * Main method, starts scheduler with task_timeout. - */ -static int -check_timeout () +int +main (int argc, char *argv[]) { int ok; + GNUNET_log_setup ("test_connection_timeout_no_connect", + "WARNING", + NULL); ok = 1; cfg = GNUNET_CONFIGURATION_create (); GNUNET_CONFIGURATION_set_value_string (cfg, "resolver", "HOSTNAME", @@ -82,20 +76,4 @@ check_timeout () return ok; } -int -main (int argc, char *argv[]) -{ - int ret = 0; - - GNUNET_log_setup ("test_connection_timeout_no_connect", -#if VERBOSE - "DEBUG", -#else - "WARNING", -#endif - NULL); - ret += check_timeout (); - return ret; -} - /* end of test_connection_timeout_no_connect.c */ diff --git a/src/util/test_connection_transmit_cancel.c b/src/util/test_connection_transmit_cancel.c index fec72d2..195ac68 100644 --- a/src/util/test_connection_transmit_cancel.c +++ b/src/util/test_connection_transmit_cancel.c @@ -27,8 +27,6 @@ #include "gnunet_scheduler_lib.h" #include "gnunet_time_lib.h" -#define VERBOSE GNUNET_NO - #define PORT 12435 static struct GNUNET_CONFIGURATION_Handle *cfg; @@ -61,16 +59,14 @@ task_transmit_cancel (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) } - - -/** - * Main method, starts scheduler with task_timeout. - */ -static int -check_transmit_cancel () +int +main (int argc, char *argv[]) { int ok; + GNUNET_log_setup ("test_connection_transmit_cancel", + "WARNING", + NULL); ok = 1; cfg = GNUNET_CONFIGURATION_create (); GNUNET_CONFIGURATION_set_value_string (cfg, "resolver", "HOSTNAME", @@ -80,22 +76,4 @@ check_transmit_cancel () return ok; } - -int -main (int argc, char *argv[]) -{ - int ret = 0; - - GNUNET_log_setup ("test_connection_transmit_cancel", -#if VERBOSE - "DEBUG", -#else - "WARNING", -#endif - NULL); - ret += check_transmit_cancel (); - - return ret; -} - /* end of test_connection_transmit_cancel.c */ diff --git a/src/util/test_container_bloomfilter.c b/src/util/test_container_bloomfilter.c index f881bb3..f9743bd 100644 --- a/src/util/test_container_bloomfilter.c +++ b/src/util/test_container_bloomfilter.c @@ -36,16 +36,16 @@ * Generate a random hashcode. */ static void -nextHC (GNUNET_HashCode * hc) +nextHC (struct GNUNET_HashCode * hc) { GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK, hc); } static int -add_iterator (void *cls, GNUNET_HashCode * next) +add_iterator (void *cls, struct GNUNET_HashCode * next) { int *ret = cls; - GNUNET_HashCode pos; + struct GNUNET_HashCode pos; if (0 == (*ret)--) return GNUNET_NO; @@ -59,7 +59,7 @@ main (int argc, char *argv[]) { struct GNUNET_CONTAINER_BloomFilter *bf; struct GNUNET_CONTAINER_BloomFilter *bfi; - GNUNET_HashCode tmp; + struct GNUNET_HashCode tmp; int i; int ok1; int ok2; diff --git a/src/util/test_container_multihashmap.c b/src/util/test_container_multihashmap.c index ba621c1..ff50df1 100644 --- a/src/util/test_container_multihashmap.c +++ b/src/util/test_container_multihashmap.c @@ -35,12 +35,12 @@ static int testMap (int i) { struct GNUNET_CONTAINER_MultiHashMap *m; - GNUNET_HashCode k1; - GNUNET_HashCode k2; + struct GNUNET_HashCode k1; + struct GNUNET_HashCode k2; const char *ret; int j; - CHECK (NULL != (m = GNUNET_CONTAINER_multihashmap_create (i))); + CHECK (NULL != (m = GNUNET_CONTAINER_multihashmap_create (i, GNUNET_NO))); memset (&k1, 0, sizeof (k1)); memset (&k2, 1, sizeof (k2)); CHECK (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (m, &k1)); diff --git a/src/util/test_crypto_ecc.c b/src/util/test_crypto_ecc.c new file mode 100644 index 0000000..6dac176 --- /dev/null +++ b/src/util/test_crypto_ecc.c @@ -0,0 +1,241 @@ +/* + This file is part of GNUnet. + (C) 2002, 2003, 2004, 2006, 2009 Christian Grothoff (and other contributing authors) + + GNUnet 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 3, or (at your + option) any later version. + + GNUnet 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 GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + +*/ +/** + * @file util/test_crypto_ecc.c + * @brief testcase for ECC public key crypto + * @author Christian Grothoff + */ +#include "platform.h" +#include "gnunet_common.h" +#include "gnunet_util_lib.h" +#include "gnunet_signatures.h" +#include <gcrypt.h> + +#define TESTSTRING "Hello World\0" +#define MAX_TESTVAL sizeof(struct GNUNET_CRYPTO_AesSessionKey) +#define ITER 25 +#define KEYFILE "/tmp/test-gnunet-crypto-ecc.key" + +#define PERF GNUNET_YES + +static struct GNUNET_CRYPTO_EccPrivateKey *key; + + +static int +testSignVerify () +{ + struct GNUNET_CRYPTO_EccSignature sig; + struct GNUNET_CRYPTO_EccSignaturePurpose purp; + struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded pkey; + int i; + struct GNUNET_TIME_Absolute start; + int ok = GNUNET_OK; + + FPRINTF (stderr, "%s", "W"); + GNUNET_CRYPTO_ecc_key_get_public (key, &pkey); + start = GNUNET_TIME_absolute_get (); + purp.size = htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose)); + purp.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TEST); + + for (i = 0; i < ITER; i++) + { + FPRINTF (stderr, "%s", "."); + if (GNUNET_SYSERR == GNUNET_CRYPTO_ecc_sign (key, &purp, &sig)) + { + FPRINTF (stderr, "%s", "GNUNET_CRYPTO_ecc_sign returned SYSERR\n"); + ok = GNUNET_SYSERR; + continue; + } + if (GNUNET_SYSERR == + GNUNET_CRYPTO_ecc_verify (GNUNET_SIGNATURE_PURPOSE_TEST, &purp, &sig, + &pkey)) + { + printf ("GNUNET_CRYPTO_ecc_verify failed!\n"); + ok = GNUNET_SYSERR; + continue; + } + if (GNUNET_SYSERR != + GNUNET_CRYPTO_ecc_verify (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_OWN, + &purp, &sig, &pkey)) + { + printf ("GNUNET_CRYPTO_ecc_verify failed to fail!\n"); + ok = GNUNET_SYSERR; + continue; + } + } + printf ("%d ECC sign/verify operations %s\n", ITER, + GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (start), GNUNET_YES)); + return ok; +} + + +#if PERF +static int +testSignPerformance () +{ + struct GNUNET_CRYPTO_EccSignaturePurpose purp; + struct GNUNET_CRYPTO_EccSignature sig; + struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded pkey; + int i; + struct GNUNET_TIME_Absolute start; + int ok = GNUNET_OK; + + purp.size = htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose)); + purp.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TEST); + FPRINTF (stderr, "%s", "W"); + GNUNET_CRYPTO_ecc_key_get_public (key, &pkey); + start = GNUNET_TIME_absolute_get (); + for (i = 0; i < ITER; i++) + { + FPRINTF (stderr, "%s", "."); + if (GNUNET_SYSERR == GNUNET_CRYPTO_ecc_sign (key, &purp, &sig)) + { + FPRINTF (stderr, "%s", "GNUNET_CRYPTO_ecc_sign returned SYSERR\n"); + ok = GNUNET_SYSERR; + continue; + } + } + printf ("%d ECC sign operations %llu ms\n", ITER, + (unsigned long long) + GNUNET_TIME_absolute_get_duration (start).rel_value); + return ok; +} +#endif + + +static int +testCreateFromFile () +{ + struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded p1; + struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded p2; + + key = GNUNET_CRYPTO_ecc_key_create_from_file (KEYFILE); + GNUNET_assert (NULL != key); + GNUNET_CRYPTO_ecc_key_get_public (key, &p1); + GNUNET_CRYPTO_ecc_key_free (key); + key = GNUNET_CRYPTO_ecc_key_create_from_file (KEYFILE); + GNUNET_assert (NULL != key); + GNUNET_CRYPTO_ecc_key_get_public (key, &p2); + GNUNET_assert (0 == memcmp (&p1, &p2, sizeof (p1))); + GNUNET_CRYPTO_ecc_key_free (key); + GNUNET_assert (0 == UNLINK (KEYFILE)); + key = GNUNET_CRYPTO_ecc_key_create_from_file (KEYFILE); + GNUNET_assert (NULL != key); + GNUNET_CRYPTO_ecc_key_get_public (key, &p2); + GNUNET_assert (0 != memcmp (&p1, &p2, sizeof (p1))); + return GNUNET_OK; +} + + +static void +key_cont (void *cls, + struct GNUNET_CRYPTO_EccPrivateKey *pk, + const char *emsg) +{ + const char *txt = cls; + struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded pub1; + struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded pub2; + + GNUNET_assert (0 == strcmp ("ok", txt)); + GNUNET_CRYPTO_ecc_key_get_public (pk, &pub1); + GNUNET_CRYPTO_ecc_key_get_public (key, &pub2); + GNUNET_assert (0 == memcmp (&pub1, &pub2, + sizeof (pub1))); + GNUNET_CRYPTO_ecc_key_free (pk); +} + + +static void +test_async_creation (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + struct GNUNET_CRYPTO_EccKeyGenerationContext *gc; + + gc = GNUNET_CRYPTO_ecc_key_create_start (KEYFILE, + &key_cont, + (void*) "bug"); + GNUNET_CRYPTO_ecc_key_create_stop (gc); + gc = GNUNET_CRYPTO_ecc_key_create_start (KEYFILE, + &key_cont, + (void*) "ok"); +} + + +static void +test_ecdh () +{ + struct GNUNET_CRYPTO_EccPrivateKey *priv1; + struct GNUNET_CRYPTO_EccPrivateKey *priv2; + struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded pub1; + struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded pub2; + struct GNUNET_HashCode ecdh1; + struct GNUNET_HashCode ecdh2; + + priv1 = GNUNET_CRYPTO_ecc_key_create (); + priv2 = GNUNET_CRYPTO_ecc_key_create (); + GNUNET_CRYPTO_ecc_key_get_public (priv1, &pub1); + GNUNET_CRYPTO_ecc_key_get_public (priv2, &pub2); + GNUNET_CRYPTO_ecc_ecdh (priv1, &pub2, &ecdh1); + GNUNET_CRYPTO_ecc_ecdh (priv2, &pub1, &ecdh2); + GNUNET_CRYPTO_ecc_key_free (priv1); + GNUNET_CRYPTO_ecc_key_free (priv2); + GNUNET_assert (0 == memcmp (&ecdh1, &ecdh2, + sizeof (struct GNUNET_HashCode))); +} + + +int +main (int argc, char *argv[]) +{ + int failureCount = 0; + + if (!gcry_check_version ("1.5.0")) + { + FPRINTF (stderr, + _ + ("libgcrypt has not the expected version (version %s is required).\n"), + "1.5.0"); + return 0; + } + GNUNET_log_setup ("test-crypto-ecc", "WARNING", NULL); + GNUNET_CRYPTO_random_disable_entropy_gathering (); + if (GNUNET_OK != testCreateFromFile ()) + failureCount++; + GNUNET_SCHEDULER_run (&test_async_creation, NULL); +#if PERF + if (GNUNET_OK != testSignPerformance ()) + failureCount++; +#endif + if (GNUNET_OK != testSignVerify ()) + failureCount++; + GNUNET_CRYPTO_ecc_key_free (key); + GNUNET_assert (0 == UNLINK (KEYFILE)); + test_ecdh (); + + if (failureCount != 0) + { + printf ("\n\n%d TESTS FAILED!\n\n", failureCount); + return -1; + } + return 0; +} + +/* end of test_crypto_ecc.c */ diff --git a/src/util/test_crypto_hash.c b/src/util/test_crypto_hash.c index bc04114..a8ef39a 100644 --- a/src/util/test_crypto_hash.c +++ b/src/util/test_crypto_hash.c @@ -35,18 +35,18 @@ static char block[65536]; static int test (int number) { - GNUNET_HashCode h1; - GNUNET_HashCode h2; + struct GNUNET_HashCode h1; + struct GNUNET_HashCode h2; struct GNUNET_CRYPTO_HashAsciiEncoded enc; - memset (&h1, number, sizeof (GNUNET_HashCode)); + memset (&h1, number, sizeof (struct GNUNET_HashCode)); GNUNET_CRYPTO_hash_to_enc (&h1, &enc); if (GNUNET_OK != GNUNET_CRYPTO_hash_from_string ((char *) &enc, &h2)) { printf ("enc2hash failed!\n"); return 1; } - if (0 != memcmp (&h1, &h2, sizeof (GNUNET_HashCode))) + if (0 != memcmp (&h1, &h2, sizeof (struct GNUNET_HashCode))) return 1; return 0; } @@ -67,10 +67,10 @@ testArithmetic () { static struct GNUNET_CRYPTO_AesSessionKey zskey; static struct GNUNET_CRYPTO_AesInitializationVector ziv; - GNUNET_HashCode h1; - GNUNET_HashCode h2; - GNUNET_HashCode d; - GNUNET_HashCode s; + struct GNUNET_HashCode h1; + struct GNUNET_HashCode h2; + struct GNUNET_HashCode d; + struct GNUNET_HashCode s; struct GNUNET_CRYPTO_AesSessionKey skey; struct GNUNET_CRYPTO_AesInitializationVector iv; @@ -107,10 +107,10 @@ testArithmetic () } static void -finished_task (void *cls, const GNUNET_HashCode * res) +finished_task (void *cls, const struct GNUNET_HashCode * res) { int *ret = cls; - GNUNET_HashCode want; + struct GNUNET_HashCode want; GNUNET_CRYPTO_hash (block, sizeof (block), &want); if (0 != memcmp (res, &want, sizeof (want))) diff --git a/src/util/test_crypto_ksk.c b/src/util/test_crypto_ksk.c index 58c4595..f062e31 100644 --- a/src/util/test_crypto_ksk.c +++ b/src/util/test_crypto_ksk.c @@ -25,9 +25,9 @@ */ #include "platform.h" #include "gnunet_common.h" -#include "gnunet_crypto_lib.h" +#include "gnunet_util_lib.h" #include "gnunet_signatures.h" -#include "gnunet_time_lib.h" + #define TESTSTRING "Hello World\0" #define MAX_TESTVAL 20 @@ -40,7 +40,7 @@ testCorrectKey () { const char *want = "010601000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b73c215f7a5e6b09bec55713c901786c09324a150980e014bdb0d04426934929c3b4971a9711af5455536cd6eeb8bfa004ee904972a737455f53c752987d8c82b755bc02882b44950c4acdc1672ba74c3b94d81a4c1ea3d74e7700ae5594c3a4f3c559e4bff2df6844fac302e4b66175e14dc8bad3ce44281d2fec1a1abef06301010000"; - GNUNET_HashCode in; + struct GNUNET_HashCode in; struct GNUNET_CRYPTO_RsaPrivateKey *hostkey; struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey; int i; @@ -79,7 +79,7 @@ testCorrectKey () static int testMultiKey (const char *word) { - GNUNET_HashCode in; + struct GNUNET_HashCode in; struct GNUNET_CRYPTO_RsaPrivateKey *hostkey; struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey; struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey1; @@ -167,9 +167,10 @@ testEncryptDecrypt (struct GNUNET_CRYPTO_RsaPrivateKey *hostkey) continue; } } - printf ("%d RSA encrypt/decrypt operations %llums (%d failures)\n", ITER, - (unsigned long long) - GNUNET_TIME_absolute_get_duration (start).rel_value, ok); + printf ("%d RSA encrypt/decrypt operations %s (%d failures)\n", + ITER, + GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (start), GNUNET_YES), + ok); if (ok == 0) return GNUNET_OK; else @@ -217,9 +218,9 @@ testSignVerify (struct GNUNET_CRYPTO_RsaPrivateKey *hostkey) continue; } } - printf ("%d RSA sign/verify operations %llums\n", ITER, - (unsigned long long) - GNUNET_TIME_absolute_get_duration (start).rel_value); + printf ("%d RSA sign/verify operations %s\n", + ITER, + GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (start), GNUNET_YES)); return ok; } @@ -228,7 +229,7 @@ int main (int argc, char *argv[]) { int failureCount = 0; - GNUNET_HashCode in; + struct GNUNET_HashCode in; struct GNUNET_CRYPTO_RsaPrivateKey *hostkey; GNUNET_log_setup ("test-crypto-ksk", "WARNING", NULL); diff --git a/src/util/test_crypto_rsa.c b/src/util/test_crypto_rsa.c index f6800af..ee67378 100644 --- a/src/util/test_crypto_rsa.c +++ b/src/util/test_crypto_rsa.c @@ -25,9 +25,8 @@ */ #include "platform.h" #include "gnunet_common.h" -#include "gnunet_crypto_lib.h" +#include "gnunet_util_lib.h" #include "gnunet_signatures.h" -#include "gnunet_time_lib.h" #define TESTSTRING "Hello World\0" #define MAX_TESTVAL sizeof(struct GNUNET_CRYPTO_AesSessionKey) @@ -36,10 +35,12 @@ #define PERF GNUNET_YES +static struct GNUNET_CRYPTO_RsaPrivateKey *key; + + static int testEncryptDecrypt () { - struct GNUNET_CRYPTO_RsaPrivateKey *hostkey; struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey; struct GNUNET_CRYPTO_RsaEncryptedData target; char result[MAX_TESTVAL]; @@ -48,9 +49,7 @@ testEncryptDecrypt () int ok; FPRINTF (stderr, "%s", "W"); - hostkey = GNUNET_CRYPTO_rsa_key_create (); - GNUNET_CRYPTO_rsa_key_get_public (hostkey, &pkey); - + GNUNET_CRYPTO_rsa_key_get_public (key, &pkey); ok = 0; start = GNUNET_TIME_absolute_get (); for (i = 0; i < ITER; i++) @@ -65,7 +64,7 @@ testEncryptDecrypt () continue; } if (-1 == - GNUNET_CRYPTO_rsa_decrypt (hostkey, &target, result, + GNUNET_CRYPTO_rsa_decrypt (key, &target, result, strlen (TESTSTRING) + 1)) { FPRINTF (stderr, "%s", "GNUNET_CRYPTO_rsa_decrypt returned SYSERR\n"); @@ -81,21 +80,20 @@ testEncryptDecrypt () continue; } } - printf ("%d RSA encrypt/decrypt operations %llums (%d failures)\n", ITER, - (unsigned long long) - GNUNET_TIME_absolute_get_duration (start).rel_value, ok); - GNUNET_CRYPTO_rsa_key_free (hostkey); + printf ("%d RSA encrypt/decrypt operations %s (%d failures)\n", + ITER, + GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (start), GNUNET_YES), + ok); if (ok == 0) return GNUNET_OK; - else - return GNUNET_SYSERR; + return GNUNET_SYSERR; } + #if PERF static int testEncryptPerformance () { - struct GNUNET_CRYPTO_RsaPrivateKey *hostkey; struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey; struct GNUNET_CRYPTO_RsaEncryptedData target; int i; @@ -103,9 +101,7 @@ testEncryptPerformance () int ok; FPRINTF (stderr, "%s", "W"); - hostkey = GNUNET_CRYPTO_rsa_key_create (); - GNUNET_CRYPTO_rsa_key_get_public (hostkey, &pkey); - + GNUNET_CRYPTO_rsa_key_get_public (key, &pkey); ok = 0; start = GNUNET_TIME_absolute_get (); for (i = 0; i < ITER; i++) @@ -123,7 +119,6 @@ testEncryptPerformance () printf ("%d RSA encrypt operations %llu ms (%d failures)\n", ITER, (unsigned long long) GNUNET_TIME_absolute_get_duration (start).rel_value, ok); - GNUNET_CRYPTO_rsa_key_free (hostkey); if (ok != 0) return GNUNET_SYSERR; return GNUNET_OK; @@ -133,7 +128,6 @@ testEncryptPerformance () static int testEncryptDecryptSK () { - struct GNUNET_CRYPTO_RsaPrivateKey *hostkey; struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey; struct GNUNET_CRYPTO_RsaEncryptedData target; struct GNUNET_CRYPTO_AesSessionKey insk; @@ -143,9 +137,7 @@ testEncryptDecryptSK () int ok; FPRINTF (stderr, "%s", "W"); - hostkey = GNUNET_CRYPTO_rsa_key_create (); - GNUNET_CRYPTO_rsa_key_get_public (hostkey, &pkey); - + GNUNET_CRYPTO_rsa_key_get_public (key, &pkey); ok = 0; start = GNUNET_TIME_absolute_get (); for (i = 0; i < ITER; i++) @@ -162,7 +154,7 @@ testEncryptDecryptSK () continue; } if (-1 == - GNUNET_CRYPTO_rsa_decrypt (hostkey, &target, &outsk, + GNUNET_CRYPTO_rsa_decrypt (key, &target, &outsk, sizeof (struct GNUNET_CRYPTO_AesSessionKey))) { FPRINTF (stderr, "%s", "GNUNET_CRYPTO_rsa_decrypt returned SYSERR\n"); @@ -177,10 +169,10 @@ testEncryptDecryptSK () continue; } } - printf ("%d RSA encrypt/decrypt SK operations %llums (%d failures)\n", ITER, - (unsigned long long) - GNUNET_TIME_absolute_get_duration (start).rel_value, ok); - GNUNET_CRYPTO_rsa_key_free (hostkey); + printf ("%d RSA encrypt/decrypt SK operations %s (%d failures)\n", + ITER, + GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (start), GNUNET_YES), + ok); if (ok != 0) return GNUNET_SYSERR; return GNUNET_OK; @@ -190,7 +182,6 @@ testEncryptDecryptSK () static int testSignVerify () { - struct GNUNET_CRYPTO_RsaPrivateKey *hostkey; struct GNUNET_CRYPTO_RsaSignature sig; struct GNUNET_CRYPTO_RsaSignaturePurpose purp; struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey; @@ -199,8 +190,7 @@ testSignVerify () int ok = GNUNET_OK; FPRINTF (stderr, "%s", "W"); - hostkey = GNUNET_CRYPTO_rsa_key_create (); - GNUNET_CRYPTO_rsa_key_get_public (hostkey, &pkey); + GNUNET_CRYPTO_rsa_key_get_public (key, &pkey); start = GNUNET_TIME_absolute_get (); purp.size = htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose)); purp.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TEST); @@ -208,7 +198,7 @@ testSignVerify () for (i = 0; i < ITER; i++) { FPRINTF (stderr, "%s", "."); - if (GNUNET_SYSERR == GNUNET_CRYPTO_rsa_sign (hostkey, &purp, &sig)) + if (GNUNET_SYSERR == GNUNET_CRYPTO_rsa_sign (key, &purp, &sig)) { FPRINTF (stderr, "%s", "GNUNET_CRYPTO_rsa_sign returned SYSERR\n"); ok = GNUNET_SYSERR; @@ -231,10 +221,8 @@ testSignVerify () continue; } } - printf ("%d RSA sign/verify operations %llums\n", ITER, - (unsigned long long) - GNUNET_TIME_absolute_get_duration (start).rel_value); - GNUNET_CRYPTO_rsa_key_free (hostkey); + printf ("%d RSA sign/verify operations %s\n", ITER, + GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (start), GNUNET_YES)); return ok; } @@ -243,7 +231,6 @@ testSignVerify () static int testSignPerformance () { - struct GNUNET_CRYPTO_RsaPrivateKey *hostkey; struct GNUNET_CRYPTO_RsaSignaturePurpose purp; struct GNUNET_CRYPTO_RsaSignature sig; struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey; @@ -254,13 +241,12 @@ testSignPerformance () purp.size = htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose)); purp.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TEST); FPRINTF (stderr, "%s", "W"); - hostkey = GNUNET_CRYPTO_rsa_key_create (); - GNUNET_CRYPTO_rsa_key_get_public (hostkey, &pkey); + GNUNET_CRYPTO_rsa_key_get_public (key, &pkey); start = GNUNET_TIME_absolute_get (); for (i = 0; i < ITER; i++) { FPRINTF (stderr, "%s", "."); - if (GNUNET_SYSERR == GNUNET_CRYPTO_rsa_sign (hostkey, &purp, &sig)) + if (GNUNET_SYSERR == GNUNET_CRYPTO_rsa_sign (key, &purp, &sig)) { FPRINTF (stderr, "%s", "GNUNET_CRYPTO_rsa_sign returned SYSERR\n"); ok = GNUNET_SYSERR; @@ -270,7 +256,6 @@ testSignPerformance () printf ("%d RSA sign operations %llu ms\n", ITER, (unsigned long long) GNUNET_TIME_absolute_get_duration (start).rel_value); - GNUNET_CRYPTO_rsa_key_free (hostkey); return ok; } #endif @@ -279,7 +264,6 @@ testSignPerformance () static int testCreateFromFile () { - struct GNUNET_CRYPTO_RsaPrivateKey *key; struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded p1; struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded p2; @@ -297,12 +281,44 @@ testCreateFromFile () GNUNET_assert (NULL != key); GNUNET_CRYPTO_rsa_key_get_public (key, &p2); GNUNET_assert (0 != memcmp (&p1, &p2, sizeof (p1))); - GNUNET_CRYPTO_rsa_key_free (key); - GNUNET_assert (0 == UNLINK (KEYFILE)); return GNUNET_OK; } +static void +key_cont (void *cls, + struct GNUNET_CRYPTO_RsaPrivateKey *pk, + const char *emsg) +{ + const char *txt = cls; + struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub1; + struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub2; + + GNUNET_assert (0 == strcmp ("ok", txt)); + GNUNET_CRYPTO_rsa_key_get_public (pk, &pub1); + GNUNET_CRYPTO_rsa_key_get_public (key, &pub2); + GNUNET_assert (0 == memcmp (&pub1, &pub2, + sizeof (pub1))); + GNUNET_CRYPTO_rsa_key_free (pk); +} + + +static void +test_async_creation (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + struct GNUNET_CRYPTO_RsaKeyGenerationContext *gc; + + gc = GNUNET_CRYPTO_rsa_key_create_start (KEYFILE, + &key_cont, + (void*) "bug"); + GNUNET_CRYPTO_rsa_key_create_stop (gc); + gc = GNUNET_CRYPTO_rsa_key_create_start (KEYFILE, + &key_cont, + (void*) "ok"); +} + + int main (int argc, char *argv[]) { @@ -312,6 +328,7 @@ main (int argc, char *argv[]) GNUNET_CRYPTO_random_disable_entropy_gathering (); if (GNUNET_OK != testCreateFromFile ()) failureCount++; + GNUNET_SCHEDULER_run (&test_async_creation, NULL); #if PERF if (GNUNET_OK != testEncryptPerformance ()) failureCount++; @@ -324,6 +341,8 @@ main (int argc, char *argv[]) failureCount++; if (GNUNET_OK != testSignVerify ()) failureCount++; + GNUNET_CRYPTO_rsa_key_free (key); + GNUNET_assert (0 == UNLINK (KEYFILE)); if (failureCount != 0) { diff --git a/src/util/test_disk.c b/src/util/test_disk.c index 149cec0..804a870 100644 --- a/src/util/test_disk.c +++ b/src/util/test_disk.c @@ -250,7 +250,7 @@ testDirMani () return 1; if (GNUNET_OK != GNUNET_DISK_directory_create ("test")) return 1; - if (GNUNET_YES != GNUNET_DISK_directory_test ("test")) + if (GNUNET_YES != GNUNET_DISK_directory_test ("test", GNUNET_YES)) return 1; if (GNUNET_OK != GNUNET_DISK_directory_remove ("test")) return 1; diff --git a/src/util/test_getopt.c b/src/util/test_getopt.c index a517887..313167d 100644 --- a/src/util/test_getopt.c +++ b/src/util/test_getopt.c @@ -26,7 +26,6 @@ #include "gnunet_configuration_lib.h" #include "gnunet_getopt_lib.h" -#define VERBOSE 0 static int testMinimal () @@ -45,6 +44,7 @@ testMinimal () return 0; } + static int testVerbose () { @@ -75,6 +75,7 @@ testVerbose () return 0; } + static int testVersion () { @@ -84,11 +85,11 @@ testVersion () NULL }; const struct GNUNET_GETOPT_CommandLineOption versionoptionlist[] = { - GNUNET_GETOPT_OPTION_VERSION (PACKAGE_VERSION), + GNUNET_GETOPT_OPTION_VERSION (PACKAGE_VERSION " " VCS_VERSION), GNUNET_GETOPT_OPTION_END }; - if (-1 != GNUNET_GETOPT_run ("test_getopt", versionoptionlist, 2, myargv)) + if (0 != GNUNET_GETOPT_run ("test_getopt", versionoptionlist, 2, myargv)) { GNUNET_break (0); return 1; @@ -96,6 +97,7 @@ testVersion () return 0; } + static int testAbout () { @@ -109,7 +111,7 @@ testAbout () GNUNET_GETOPT_OPTION_END }; - if (-1 != GNUNET_GETOPT_run ("test_getopt", aboutoptionlist, 2, myargv)) + if (0 != GNUNET_GETOPT_run ("test_getopt", aboutoptionlist, 2, myargv)) { GNUNET_break (0); return 1; @@ -117,6 +119,7 @@ testAbout () return 0; } + static int testLogOpts () { @@ -153,6 +156,7 @@ testLogOpts () return 0; } + static int testFlagNum () { @@ -190,6 +194,7 @@ testFlagNum () return 0; } + int main (int argc, char *argv[]) { diff --git a/src/util/test_os_network.c b/src/util/test_os_network.c index 4486e6a..2cdd750 100644 --- a/src/util/test_os_network.c +++ b/src/util/test_os_network.c @@ -26,7 +26,6 @@ #include "gnunet_configuration_lib.h" #include "gnunet_os_lib.h" -#define VERBOSE 1 /** * Check if the address we got is IPv4 or IPv6 loopback (which should @@ -40,20 +39,20 @@ proc (void *cls, const char *name, int isDefault, const struct sockaddr *addr, { int *ok = cls; char buf[INET6_ADDRSTRLEN]; + const char * protocol; if (NULL == addr) return GNUNET_OK; -#if VERBOSE - const char * protocol; if (addrlen == sizeof (struct sockaddr_in)) protocol = "IPv4"; else protocol = "IPv6"; - printf ("%s Address `%s'\n", protocol, GNUNET_a2s ((const struct sockaddr *) addr,addrlen) ); - printf (" Netmask `%s'\n", GNUNET_a2s ((const struct sockaddr *) netmask, addrlen) ); - printf (" Broadcast `%s'\n", GNUNET_a2s ((const struct sockaddr *) broadcast_addr,addrlen) ); -#endif - + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "%s Address `%s'\n", protocol, GNUNET_a2s ((const struct sockaddr *) addr,addrlen) ); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Netmask `%s'\n", GNUNET_a2s ((const struct sockaddr *) netmask, addrlen) ); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "`%s'\n", GNUNET_a2s ((const struct sockaddr *) broadcast_addr,addrlen) ); inet_ntop (addr->sa_family, (addr->sa_family == AF_INET) ? (void *) &((struct sockaddr_in *) addr)->sin_addr @@ -64,23 +63,16 @@ proc (void *cls, const char *name, int isDefault, const struct sockaddr *addr, return GNUNET_OK; } -static int -testifcs () + +int +main (int argc, char *argv[]) { int ret; + GNUNET_log_setup ("test-os-network", "WARNING", NULL); ret = 1; GNUNET_OS_network_interfaces_list (&proc, &ret); return ret; } -int -main (int argc, char *argv[]) -{ - int errCnt = 0; - - GNUNET_log_setup ("test-os-network", "WARNING", NULL); - if (0 != testifcs ()) - errCnt++; - return errCnt; -} +/* end of test_os_network.c */ diff --git a/src/util/test_os_priority.c b/src/util/test_os_priority.c index 94e2719..bb740db 100644 --- a/src/util/test_os_priority.c +++ b/src/util/test_os_priority.c @@ -25,7 +25,6 @@ #include "gnunet_common.h" #include "gnunet_os_lib.h" -#define VERBOSE 0 static int testprio () diff --git a/src/util/test_os_start_process.c b/src/util/test_os_start_process.c index 0d14818..5994518 100644 --- a/src/util/test_os_start_process.c +++ b/src/util/test_os_start_process.c @@ -33,21 +33,26 @@ #include "gnunet_scheduler_lib.h" #include "disk.h" -#define VERBOSE GNUNET_NO -static char *test_phrase = "HELLO WORLD"; +static const char *test_phrase = "HELLO WORLD"; + static int ok; static struct GNUNET_OS_Process *proc; -/* Pipe to write to started processes stdin (on write end) */ +/** + * Pipe to write to started processes stdin (on write end) + */ static struct GNUNET_DISK_PipeHandle *hello_pipe_stdin; -/* Pipe to read from started processes stdout (on read end) */ +/** + * Pipe to read from started processes stdout (on read end) + */ static struct GNUNET_DISK_PipeHandle *hello_pipe_stdout; static GNUNET_SCHEDULER_TaskIdentifier die_task; + static void end_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { @@ -62,6 +67,7 @@ end_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) GNUNET_DISK_pipe_close (hello_pipe_stdin); } + static void read_call (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { @@ -73,9 +79,7 @@ read_call (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) bytes = GNUNET_DISK_file_read (stdout_read_handle, &buf, sizeof (buf)); -#if VERBOSE - FPRINTF (stderr, "bytes is %d\n", bytes); -#endif + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "bytes is %d\n", bytes); if (bytes < 1) { @@ -87,10 +91,8 @@ read_call (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) } ok = strncmp (&buf[0], test_phrase, strlen (test_phrase)); -#if VERBOSE - FPRINTF (stderr, "read %s\n", &buf[0]); -#endif - if (ok == 0) + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "read %s\n", &buf[0]); + if (0 == ok) { GNUNET_SCHEDULER_cancel (die_task); GNUNET_SCHEDULER_add_now (&end_task, NULL); @@ -111,7 +113,11 @@ run_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) const struct GNUNET_DISK_FileHandle *stdout_read_handle; const struct GNUNET_DISK_FileHandle *wh; +#if !WINDOWS GNUNET_asprintf (&fn, "cat"); +#else + GNUNET_asprintf (&fn, "w32cat"); +#endif hello_pipe_stdin = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_YES, GNUNET_NO); hello_pipe_stdout = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO, GNUNET_YES); @@ -125,7 +131,7 @@ run_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) } proc = - GNUNET_OS_start_process (GNUNET_NO, hello_pipe_stdin, hello_pipe_stdout, fn, + GNUNET_OS_start_process (GNUNET_NO, GNUNET_OS_INHERIT_STD_ERR, hello_pipe_stdin, hello_pipe_stdout, fn, "test_gnunet_echo_hello", "-", NULL); GNUNET_free (fn); @@ -181,20 +187,26 @@ check_run () static int check_kill () { + char *fn; +#if !WINDOWS + GNUNET_asprintf (&fn, "cat"); +#else + GNUNET_asprintf (&fn, "w32cat"); +#endif hello_pipe_stdin = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_YES, GNUNET_NO); hello_pipe_stdout = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO, GNUNET_YES); if ((hello_pipe_stdout == NULL) || (hello_pipe_stdin == NULL)) { + GNUNET_free (fn); return 1; } proc = - GNUNET_OS_start_process (GNUNET_YES, hello_pipe_stdin, hello_pipe_stdout, "cat", + GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_ERR, hello_pipe_stdin, hello_pipe_stdout, fn, "gnunet-service-resolver", "-", NULL); - sleep (1); /* give process time to start and open pipe */ + sleep (1); /* give process time to start, so we actually use the pipe-kill mechanism! */ + GNUNET_free (fn); if (0 != GNUNET_OS_process_kill (proc, SIGTERM)) - { GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); - } GNUNET_assert (GNUNET_OK == GNUNET_OS_process_wait (proc)); GNUNET_OS_process_destroy (proc); proc = NULL; @@ -210,19 +222,27 @@ check_kill () static int check_instant_kill () { + char *fn; +#if !WINDOWS + GNUNET_asprintf (&fn, "cat"); +#else + GNUNET_asprintf (&fn, "w32cat"); +#endif hello_pipe_stdin = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_YES, GNUNET_NO); hello_pipe_stdout = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO, GNUNET_YES); if ((hello_pipe_stdout == NULL) || (hello_pipe_stdin == NULL)) { + GNUNET_free (fn); return 1; } proc = - GNUNET_OS_start_process (GNUNET_YES, hello_pipe_stdin, hello_pipe_stdout, "cat", + GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_ERR, hello_pipe_stdin, hello_pipe_stdout, fn, "gnunet-service-resolver", "-", NULL); if (0 != GNUNET_OS_process_kill (proc, SIGTERM)) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); } + GNUNET_free (fn); GNUNET_assert (GNUNET_OK == GNUNET_OS_process_wait (proc)); GNUNET_OS_process_destroy (proc); proc = NULL; @@ -238,16 +258,13 @@ main (int argc, char *argv[]) int ret; GNUNET_log_setup ("test-os-start-process", -#if VERBOSE - "DEBUG", -#else "WARNING", -#endif NULL); ret = 0; ret |= check_run (); ret |= check_kill (); ret |= check_instant_kill (); - return ret; } + +/* end of test_os_start_process.c */ diff --git a/src/util/test_peer.c b/src/util/test_peer.c index 2a48401..fa4d31b 100644 --- a/src/util/test_peer.c +++ b/src/util/test_peer.c @@ -29,8 +29,6 @@ #define NUMBER_OF_PEERS 10 -#define VERBOSE GNUNET_NO - /** * A list of Peer ID's to play with */ @@ -46,9 +44,8 @@ generatePeerIdList () { GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK, &pidArr[i].hashPubKey); -#if VERBOSE - printf ("Peer %d: %s\n", i, GNUNET_i2s (&pidArr[i])); -#endif + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Peer %d: %s\n", i, GNUNET_i2s (&pidArr[i])); } } @@ -124,7 +121,7 @@ check () int main () { - int i; + unsigned int i; GNUNET_log_setup ("test-peer", "ERROR", NULL); for (i = 0; i < 1; i++) diff --git a/src/util/test_plugin.c b/src/util/test_plugin.c index 428cdaf..f2abfa7 100644 --- a/src/util/test_plugin.c +++ b/src/util/test_plugin.c @@ -24,7 +24,6 @@ #include "platform.h" #include "gnunet_plugin_lib.h" -#define VERBOSE GNUNET_NO static void test_cb (void *cls, const char *libname, void *lib_ret) @@ -36,14 +35,16 @@ test_cb (void *cls, const char *libname, void *lib_ret) ret = GNUNET_PLUGIN_unload (libname, "out"); GNUNET_assert (NULL != ret); GNUNET_assert (0 == strcmp (ret, "World")); + GNUNET_free (ret); } -static int -check () +int +main (int argc, char *argv[]) { void *ret; + GNUNET_log_setup ("test-plugin", "WARNING", NULL); GNUNET_log_skip (1, GNUNET_NO); ret = GNUNET_PLUGIN_load ("libgnunet_plugin_missing", NULL); GNUNET_log_skip (0, GNUNET_NO); @@ -52,7 +53,7 @@ check () ret = GNUNET_PLUGIN_load ("libgnunet_plugin_test", "in"); if (ret == NULL) return 1; - if (0 != strcmp (ret, "Hello")) + if (0 != strcmp (ret, "Hello")) return 2; ret = GNUNET_PLUGIN_unload ("libgnunet_plugin_test", "out"); if (ret == NULL) @@ -60,20 +61,8 @@ check () if (0 != strcmp (ret, "World")) return 4; free (ret); - GNUNET_PLUGIN_load_all ("libgnunet_plugin_tes", "in", &test_cb, "test"); return 0; } -int -main (int argc, char *argv[]) -{ - int ret; - - GNUNET_log_setup ("test-plugin", "WARNING", NULL); - ret = check (); - - return ret; -} - /* end of test_plugin.c */ diff --git a/src/util/test_pseudonym.c b/src/util/test_pseudonym.c index 4ce8b38..9b5085b 100644 --- a/src/util/test_pseudonym.c +++ b/src/util/test_pseudonym.c @@ -35,16 +35,16 @@ static struct GNUNET_CONTAINER_MetaData *meta; -static GNUNET_HashCode id1; +static struct GNUNET_HashCode id1; static int -iter (void *cls, const GNUNET_HashCode * pseudonym, +iter (void *cls, const struct GNUNET_HashCode * pseudonym, const char *name, const char *unique_name, const struct GNUNET_CONTAINER_MetaData *md, int rating) { int *ok = cls; - if ((0 == memcmp (pseudonym, &id1, sizeof (GNUNET_HashCode))) && + if ((0 == memcmp (pseudonym, &id1, sizeof (struct GNUNET_HashCode))) && (!GNUNET_CONTAINER_meta_data_test_equal (md, meta))) { *ok = GNUNET_NO; @@ -54,7 +54,7 @@ iter (void *cls, const GNUNET_HashCode * pseudonym, } static int -noti_callback (void *cls, const GNUNET_HashCode * pseudonym, +noti_callback (void *cls, const struct GNUNET_HashCode * pseudonym, const char *name, const char *unique_name, const struct GNUNET_CONTAINER_MetaData *md, int rating) { @@ -65,7 +65,7 @@ noti_callback (void *cls, const GNUNET_HashCode * pseudonym, } static int -fake_noti_callback (void *cls, const GNUNET_HashCode * pseudonym, +fake_noti_callback (void *cls, const struct GNUNET_HashCode * pseudonym, const char *name, const char *unique_name, const struct GNUNET_CONTAINER_MetaData *md, int rating) { @@ -76,7 +76,7 @@ fake_noti_callback (void *cls, const GNUNET_HashCode * pseudonym, } static int -false_callback (void *cls, const GNUNET_HashCode * pseudonym, +false_callback (void *cls, const struct GNUNET_HashCode * pseudonym, const char *name, const char *unique_name, const struct GNUNET_CONTAINER_MetaData *md, int rating) { @@ -87,11 +87,11 @@ int main (int argc, char *argv[]) { int ok; - GNUNET_HashCode rid1; - GNUNET_HashCode id2; - GNUNET_HashCode rid2; - GNUNET_HashCode fid; - GNUNET_HashCode id3; + struct GNUNET_HashCode rid1; + struct GNUNET_HashCode id2; + struct GNUNET_HashCode rid2; + struct GNUNET_HashCode fid; + struct GNUNET_HashCode id3; int old; int newVal; @@ -174,13 +174,13 @@ main (int argc, char *argv[]) CHECK (GNUNET_SYSERR == GNUNET_PSEUDONYM_name_to_id (cfg, name1, &rid1)); CHECK (GNUNET_OK == GNUNET_PSEUDONYM_name_to_id (cfg, name2_unique, &rid2)); CHECK (GNUNET_OK == GNUNET_PSEUDONYM_name_to_id (cfg, name1_unique, &rid1)); - CHECK (0 == memcmp (&id1, &rid1, sizeof (GNUNET_HashCode))); - CHECK (0 == memcmp (&id2, &rid2, sizeof (GNUNET_HashCode))); + CHECK (0 == memcmp (&id1, &rid1, sizeof (struct GNUNET_HashCode))); + CHECK (0 == memcmp (&id2, &rid2, sizeof (struct GNUNET_HashCode))); GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK, &fid); GNUNET_log_skip (1, GNUNET_NO); CHECK (0 == GNUNET_PSEUDONYM_rank (cfg, &fid, 0)); - GNUNET_log_skip (0, GNUNET_YES); + GNUNET_log_skip (0, GNUNET_NO); CHECK (GNUNET_OK == GNUNET_PSEUDONYM_get_info (cfg, &fid, NULL, NULL, &noname, &noname_is_a_dup)); CHECK (noname != NULL); CHECK (noname_is_a_dup == GNUNET_YES); diff --git a/src/util/test_resolver_api.c b/src/util/test_resolver_api.c index 4a3a203..ea18629 100644 --- a/src/util/test_resolver_api.c +++ b/src/util/test_resolver_api.c @@ -22,15 +22,10 @@ * @brief testcase for resolver_api.c */ #include "platform.h" -#include "gnunet_common.h" -#include "gnunet_getopt_lib.h" -#include "gnunet_os_lib.h" -#include "gnunet_program_lib.h" -#include "gnunet_scheduler_lib.h" +#include "gnunet_util_lib.h" #include "gnunet_resolver_service.h" #include "resolver.h" -#define VERBOSE GNUNET_NO /** * Using DNS root servers to check gnunet's resolver service @@ -40,12 +35,13 @@ #define ROOTSERVER_NAME "a.root-servers.net" #define ROOTSERVER_IP "198.41.0.4" + static void check_hostname (void *cls, const struct sockaddr *sa, socklen_t salen) { int *ok = cls; - if (salen == 0) + if (0 == salen) { (*ok) &= ~8; return; @@ -82,7 +78,7 @@ check_localhost (void *cls, const char *hostname) { int *ok = cls; - if (hostname == NULL) + if (NULL == hostname) return; if (0 == strcmp (hostname, "localhost")) { @@ -98,13 +94,14 @@ check_localhost (void *cls, const char *hostname) } } + static void check_127 (void *cls, const struct sockaddr *sa, socklen_t salen) { int *ok = cls; const struct sockaddr_in *sai = (const struct sockaddr_in *) sa; - if (sa == NULL) + if (NULL == sa) return; GNUNET_assert (sizeof (struct sockaddr_in) == salen); if (sai->sin_addr.s_addr == htonl (INADDR_LOOPBACK)) @@ -122,6 +119,7 @@ check_127 (void *cls, const struct sockaddr *sa, socklen_t salen) } } + static void check_local_fqdn (void *cls, const char *gnunet_fqdn) { @@ -159,14 +157,13 @@ check_local_fqdn (void *cls, const char *gnunet_fqdn) } - static void check_rootserver_ip (void *cls, const struct sockaddr *sa, socklen_t salen) { int *ok = cls; const struct sockaddr_in *sai = (const struct sockaddr_in *) sa; - if (sa == NULL) + if (NULL == sa) return; GNUNET_assert (sizeof (struct sockaddr_in) == salen); @@ -184,12 +181,13 @@ check_rootserver_ip (void *cls, const struct sockaddr *sa, socklen_t salen) } } + static void check_rootserver_name (void *cls, const char *hostname) { int *ok = cls; - if (hostname == NULL) + if (NULL == hostname) return; if (0 == strcmp (hostname, ROOTSERVER_NAME)) @@ -206,6 +204,7 @@ check_rootserver_name (void *cls, const char *hostname) } } + static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) @@ -347,36 +346,33 @@ run (void *cls, char *const *args, const char *cfgfile, } -static int -check () + +int +main (int argc, char *argv[]) { int ok = 1 + 2 + 4 + 8; char *fn; - char *pfx; struct GNUNET_OS_Process *proc; - - char *const argv[] = - { "test-resolver-api", "-c", "test_resolver_api_data.conf", -#if VERBOSE - "-L", "DEBUG", -#endif - NULL + char *const argvx[] = { + "test-resolver-api", "-c", "test_resolver_api_data.conf", NULL }; struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END }; - pfx = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_BINDIR); - GNUNET_asprintf (&fn, "%s%cgnunet-service-resolver", pfx, DIR_SEPARATOR); - GNUNET_free (pfx); - proc = GNUNET_OS_start_process (GNUNET_YES, NULL, NULL, fn, "gnunet-service-resolver", -#if VERBOSE - "-L", "DEBUG", -#endif + + GNUNET_log_setup ("test-resolver-api", + "WARNING", + NULL); + fn = GNUNET_OS_get_libexec_binary_path ("gnunet-service-resolver"); + proc = GNUNET_OS_start_process (GNUNET_YES, + GNUNET_OS_INHERIT_STD_OUT_AND_ERR, + NULL, NULL, fn, + "gnunet-service-resolver", "-c", "test_resolver_api_data.conf", NULL); GNUNET_assert (NULL != proc); GNUNET_free (fn); GNUNET_assert (GNUNET_OK == - GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, - argv, "test-resolver-api", "nohelp", + GNUNET_PROGRAM_run ((sizeof (argvx) / sizeof (char *)) - 1, + argvx, "test-resolver-api", "nohelp", options, &run, &ok)); if (0 != GNUNET_OS_process_kill (proc, SIGTERM)) { @@ -386,26 +382,10 @@ check () GNUNET_OS_process_wait (proc); GNUNET_OS_process_destroy (proc); proc = NULL; - if (ok != 0) + if (0 != ok) FPRINTF (stderr, "Missed some resolutions: %u\n", ok); return ok; } -int -main (int argc, char *argv[]) -{ - int ret; - - GNUNET_log_setup ("test-resolver-api", -#if VERBOSE - "DEBUG", -#else - "WARNING", -#endif - NULL); - ret = check (); - - return ret; -} /* end of test_resolver_api.c */ diff --git a/src/util/test_resolver_api_data.conf b/src/util/test_resolver_api_data.conf index 745cb7b..3e264eb 100644 --- a/src/util/test_resolver_api_data.conf +++ b/src/util/test_resolver_api_data.conf @@ -4,5 +4,4 @@ SERVICEHOME = /tmp/test-gnunetd-statistics/ [resolver] PORT = 22354 HOSTNAME = localhost -DEBUG = YES diff --git a/src/util/test_scheduler.c b/src/util/test_scheduler.c index 9832ade..2a9ed2d 100644 --- a/src/util/test_scheduler.c +++ b/src/util/test_scheduler.c @@ -27,7 +27,11 @@ #include "gnunet_time_lib.h" #include "gnunet_disk_lib.h" -#define VERBOSE GNUNET_NO + +struct GNUNET_DISK_PipeHandle *p; + +static const struct GNUNET_DISK_FileHandle *fds[2]; + static void task2 (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) @@ -51,9 +55,6 @@ task3 (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) (*ok) = 4; } -struct GNUNET_DISK_PipeHandle *p; -static const struct GNUNET_DISK_FileHandle *fds[2]; - static void taskWrt (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) @@ -74,6 +75,7 @@ taskNeverRun (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) GNUNET_assert (0); } + static void taskLast (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { @@ -84,6 +86,7 @@ taskLast (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) (*ok) = 0; } + static void taskRd (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { @@ -132,7 +135,6 @@ task1 (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) } - /** * Main method, starts scheduler with task1, * checks that "ok" is correct at the end. @@ -229,7 +231,6 @@ checkCancel () } - int main (int argc, char *argv[]) { diff --git a/src/util/test_scheduler_delay.c b/src/util/test_scheduler_delay.c index 8ba35f5..1320669 100644 --- a/src/util/test_scheduler_delay.c +++ b/src/util/test_scheduler_delay.c @@ -28,8 +28,6 @@ #include "gnunet_scheduler_lib.h" #include "gnunet_time_lib.h" -#define VERBOSE GNUNET_NO - static struct GNUNET_TIME_Absolute target; static int i; @@ -71,9 +69,11 @@ test_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) i += INCR; } -static int -check () + +int +main (int argc, char *argv[]) { + GNUNET_log_setup ("test-scheduler-delay", "WARNING", NULL); target = GNUNET_TIME_absolute_get (); GNUNET_SCHEDULER_run (&test_task, NULL); FPRINTF (stdout, "Sleep precision: %llu ms. ", @@ -89,15 +89,4 @@ check () return 0; } -int -main (int argc, char *argv[]) -{ - int ret; - - GNUNET_log_setup ("test-scheduler-delay", "WARNING", NULL); - ret = check (); - - return ret; -} - /* end of test_scheduler_delay.c */ diff --git a/src/util/test_server.c b/src/util/test_server.c index 0faf61b..19f9932 100644 --- a/src/util/test_server.c +++ b/src/util/test_server.c @@ -28,8 +28,6 @@ #include "gnunet_server_lib.h" #include "gnunet_time_lib.h" -#define VERBOSE GNUNET_NO - #define PORT 12435 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2) diff --git a/src/util/test_server_disconnect.c b/src/util/test_server_disconnect.c index c54f9cb..b54df48 100644 --- a/src/util/test_server_disconnect.c +++ b/src/util/test_server_disconnect.c @@ -28,7 +28,6 @@ #include "gnunet_server_lib.h" #include "gnunet_time_lib.h" -#define VERBOSE GNUNET_NO #define PORT 12435 diff --git a/src/util/test_server_mst_interrupt.c b/src/util/test_server_mst_interrupt.c index fd34bd0..8fd7a2b 100644 --- a/src/util/test_server_mst_interrupt.c +++ b/src/util/test_server_mst_interrupt.c @@ -30,7 +30,7 @@ #include "gnunet_time_lib.h" static struct GNUNET_SERVER_MessageStreamTokenizer * mst; -static int ret; + /* Callback destroying mst with data in buffer */ static int @@ -42,40 +42,23 @@ mst_cb (void *cls, void *client, return GNUNET_SYSERR; } -/** - * Main method - */ -static int -check () -{ +int +main (int argc, char *argv[]) +{ struct GNUNET_PeerIdentity id; struct GNUNET_MessageHeader msg[2]; - /* Prepare */ - memset (&id, sizeof (id), '\0'); + GNUNET_log_setup ("test_server_mst_interrupt", "WARNING", NULL); + memset (&id, 0, sizeof (id)); msg[0].size = htons (sizeof (msg)); msg[0].type = htons (sizeof (GNUNET_MESSAGE_TYPE_DUMMY)); - mst = GNUNET_SERVER_mst_create(mst_cb, NULL); - - GNUNET_SERVER_mst_receive(mst, &id, (const char *) &msg, 2 * sizeof (msg), GNUNET_NO, GNUNET_NO); - + GNUNET_SERVER_mst_receive (mst, &id, + (const char *) &msg, 2 * sizeof (msg), + GNUNET_NO, GNUNET_NO); /* If we reach this line, it did not crash */ - ret = 0; - - return ret; -} - -int -main (int argc, char *argv[]) -{ - ret = 1; - - GNUNET_log_setup ("test_server", "WARNING", NULL); - check (); - - return ret; + return 0; } /* end of test_server_mst_interrupt.c */ diff --git a/src/util/test_server_with_client.c b/src/util/test_server_with_client.c index ad56071..c494563 100644 --- a/src/util/test_server_with_client.c +++ b/src/util/test_server_with_client.c @@ -30,8 +30,6 @@ #include "gnunet_server_lib.h" #include "gnunet_time_lib.h" -#define VERBOSE GNUNET_NO - #define PORT 22335 #define MY_TYPE 128 @@ -190,35 +188,15 @@ task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) } -/** - * Main method, starts scheduler with task1, - * checks that "ok" is correct at the end. - */ -static int -check () -{ - - ok = 1; - GNUNET_SCHEDULER_run (&task, NULL); - return ok; -} - - int main (int argc, char *argv[]) { - int ret = 0; - GNUNET_log_setup ("test_server_with_client", -#if VERBOSE - "DEBUG", -#else "WARNING", -#endif NULL); - ret += check (); - - return ret; + ok = 1; + GNUNET_SCHEDULER_run (&task, NULL); + return ok; } /* end of test_server_with_client.c */ diff --git a/src/util/test_server_with_client_unix.c b/src/util/test_server_with_client_unix.c index eae80e4..57a67d3 100644 --- a/src/util/test_server_with_client_unix.c +++ b/src/util/test_server_with_client_unix.c @@ -30,8 +30,6 @@ #include "gnunet_server_lib.h" #include "gnunet_time_lib.h" -#define VERBOSE GNUNET_NO - #define MY_TYPE 128 @@ -43,6 +41,7 @@ static struct GNUNET_CONFIGURATION_Handle *cfg; static int ok; + static void send_done (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { @@ -150,7 +149,6 @@ task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) un.sun_path[0] = '\0'; #endif - sap[0] = (struct sockaddr *) &un; slens[0] = sizeof (un); sap[1] = NULL; @@ -178,35 +176,15 @@ task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) } -/** - * Main method, starts scheduler with task1, - * checks that "ok" is correct at the end. - */ -static int -check () -{ - - ok = 1; - GNUNET_SCHEDULER_run (&task, NULL); - return ok; -} - - int main (int argc, char *argv[]) { - int ret = 0; - GNUNET_log_setup ("test_server_with_client_unix", -#if VERBOSE - "DEBUG", -#else "WARNING", -#endif NULL); - ret += check (); - - return ret; + ok = 1; + GNUNET_SCHEDULER_run (&task, NULL); + return ok; } /* end of test_server_with_client_unix.c */ diff --git a/src/util/test_service.c b/src/util/test_service.c index 5547249..be49d18 100644 --- a/src/util/test_service.c +++ b/src/util/test_service.c @@ -31,8 +31,6 @@ #include "gnunet_time_lib.h" -#define VERBOSE GNUNET_NO - #define PORT 12435 #define MY_TYPE 256 @@ -148,17 +146,11 @@ check () "test_service", "-c", "test_service_data.conf", - "-L", -#if VERBOSE - "DEBUG", -#else - "WARNING", -#endif NULL }; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting service\n"); GNUNET_assert (GNUNET_OK == - GNUNET_SERVICE_run (5, argv, "test_service", + GNUNET_SERVICE_run (3, argv, "test_service", GNUNET_SERVICE_OPTION_NONE, &runner, &ok)); GNUNET_assert (0 == ok); return ok; @@ -201,17 +193,11 @@ check6 () "test_service6", "-c", "test_service_data.conf", - "-L", -#if VERBOSE - "DEBUG", -#else - "WARNING", -#endif NULL }; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting v6 service\n"); GNUNET_assert (GNUNET_OK == - GNUNET_SERVICE_run (5, argv, "test_service6", + GNUNET_SERVICE_run (3, argv, "test_service6", GNUNET_SERVICE_OPTION_NONE, &runner6, &ok)); GNUNET_assert (0 == ok); @@ -241,12 +227,6 @@ check_start_stop () "test-service-program", "-c", "test_service_data.conf", - "-L", -#if VERBOSE - "DEBUG", -#else - "WARNING", -#endif NULL }; const struct GNUNET_GETOPT_CommandLineOption options[] = { @@ -255,9 +235,9 @@ check_start_stop () int ret = 1; GNUNET_assert (GNUNET_OK == - GNUNET_PROGRAM_run (5, argv, "test-service-program", "no help", + GNUNET_PROGRAM_run (3, argv, "test-service-program", "no help", options, &start_stop_main, &ret)); - + GNUNET_break (0 == ret); return ret; } @@ -270,11 +250,7 @@ main (int argc, char *argv[]) struct GNUNET_NETWORK_Handle *s = NULL; GNUNET_log_setup ("test-service", -#if VERBOSE - "DEBUG", -#else "WARNING", -#endif NULL); ret += check (); ret += check (); diff --git a/src/util/test_strings.c b/src/util/test_strings.c index b662623..bc41694 100644 --- a/src/util/test_strings.c +++ b/src/util/test_strings.c @@ -25,20 +25,23 @@ #include "gnunet_common.h" #include "gnunet_strings_lib.h" -#define VERBOSE GNUNET_NO #define WANT(a,b) if (0 != strcmp(a,b)) { fprintf(stderr, "Got `%s', wanted `%s'\n", b, a); GNUNET_free(b); GNUNET_break(0); return 1;} else { GNUNET_free (b); } +#define WANTNF(a,b) do { if (0 != strcmp(a,b)) { fprintf(stderr, "Got `%s', wanted `%s'\n", b, a); GNUNET_break(0); return 1;} } while (0) #define WANTB(a,b,l) if (0 != memcmp(a,b,l)) { GNUNET_break(0); return 1;} else { } -static int -check () +int +main (int argc, char *argv[]) { char buf[128]; char *r; char *b; + const char *bc; struct GNUNET_TIME_Absolute at; + struct GNUNET_TIME_Absolute atx; const char *hdir; + GNUNET_log_setup ("test_strings", "ERROR", NULL); sprintf (buf, "4 %s", _( /* size unit */ "b")); b = GNUNET_STRINGS_byte_size_fancy (4); WANT (buf, b); @@ -49,20 +52,20 @@ check () b = GNUNET_STRINGS_byte_size_fancy (10240LL * 1024LL * 1024LL * 1024LL); WANT (buf, b); sprintf (buf, "4 %s", _( /* time unit */ "ms")); - b = GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_MILLISECONDS, - 4)); - WANT (buf, b); + bc = GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_relative_multiply + (GNUNET_TIME_UNIT_MILLISECONDS, + 4), GNUNET_YES); + WANTNF (buf, bc); sprintf (buf, "7 %s", _( /* time unit */ "s")); - b = GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_MILLISECONDS, - 7 * 1000)); - WANT (buf, b); + bc = GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_relative_multiply + (GNUNET_TIME_UNIT_MILLISECONDS, + 7 * 1000), GNUNET_YES); + WANTNF (buf, bc); sprintf (buf, "7 %s", _( /* time unit */ "h")); - b = GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_relative_multiply + bc = GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, - 7 * 60 * 60 * 1000)); - WANT (buf, b); + 7 * 60 * 60 * 1000), GNUNET_YES); + WANTNF (buf, bc); #ifndef MINGW hdir = getenv ("HOME"); #else @@ -83,37 +86,31 @@ check () if (0 != GNUNET_STRINGS_buffer_tokenize (buf, 2, 2, &r, &b)) return 1; at.abs_value = 5000; - r = GNUNET_STRINGS_absolute_time_to_string (at); - /* r should be something like "Wed Dec 31 17:00:05 1969" + bc = GNUNET_STRINGS_absolute_time_to_string (at); + /* bc should be something like "Wed Dec 31 17:00:05 1969" * where the details of the day and hour depend on the timezone; * however, the "0:05 19" should always be there; hence: */ - if (NULL == strstr (r, "0:05 19")) + if (NULL == strstr (bc, "0:05 19")) { - FPRINTF (stderr, "Got %s\n", r); + FPRINTF (stderr, "Got %s\n", bc); GNUNET_break (0); - GNUNET_free (r); return 1; } - GNUNET_free (r); b = GNUNET_STRINGS_to_utf8 ("TEST", 4, "ASCII"); WANT ("TEST", b); -#if ENABLE_NLS && HAVE_ICONV + + at = GNUNET_TIME_UNIT_FOREVER_ABS; + bc = GNUNET_STRINGS_absolute_time_to_string (at); + GNUNET_assert (GNUNET_OK == + GNUNET_STRINGS_fancy_time_to_absolute (bc, &atx)); + GNUNET_assert (atx.abs_value == at.abs_value); + GNUNET_log_skip (2, GNUNET_NO); b = GNUNET_STRINGS_to_utf8 ("TEST", 4, "unknown"); GNUNET_log_skip (0, GNUNET_YES); WANT ("TEST", b); -#endif return 0; } -int -main (int argc, char *argv[]) -{ - int ret; - - GNUNET_log_setup ("test_strings", "ERROR", NULL); - ret = check (); - return ret; -} /* end of test_strings.c */ diff --git a/src/util/test_time.c b/src/util/test_time.c index b4c7233..cd11754 100644 --- a/src/util/test_time.c +++ b/src/util/test_time.c @@ -25,10 +25,9 @@ #include "gnunet_common.h" #include "gnunet_time_lib.h" -#define VERBOSE GNUNET_NO -static int -check () +int +main (int argc, char *argv[]) { struct GNUNET_TIME_Absolute now; struct GNUNET_TIME_AbsoluteNBO nown; @@ -43,6 +42,7 @@ check () struct GNUNET_TIME_RelativeNBO reln; unsigned int i; + GNUNET_log_setup ("test-time", "WARNING", NULL); forever = GNUNET_TIME_UNIT_FOREVER_ABS; relForever = GNUNET_TIME_UNIT_FOREVER_REL; relUnit = GNUNET_TIME_UNIT_MILLISECONDS; @@ -230,15 +230,5 @@ check () return 0; } -int -main (int argc, char *argv[]) -{ - int ret; - - GNUNET_log_setup ("test-time", "WARNING", NULL); - ret = check (); - - return ret; -} /* end of test_time.c */ diff --git a/src/util/time.c b/src/util/time.c index 7467b44..afb0c00 100644 --- a/src/util/time.c +++ b/src/util/time.c @@ -484,6 +484,7 @@ GNUNET_TIME_relative_hton (struct GNUNET_TIME_Relative a) return ret; } + /** * Convert relative time from network byte order. * @@ -500,6 +501,7 @@ GNUNET_TIME_relative_ntoh (struct GNUNET_TIME_RelativeNBO a) } + /** * Convert absolute time to network byte order. * @@ -515,6 +517,7 @@ GNUNET_TIME_absolute_hton (struct GNUNET_TIME_Absolute a) return ret; } + /** * Convert absolute time from network byte order. * @@ -531,26 +534,5 @@ GNUNET_TIME_absolute_ntoh (struct GNUNET_TIME_AbsoluteNBO a) } -/** - * Convert a relative time to a string. - * This is one of the very few calls in the entire API that is - * NOT reentrant! - * - * @param time the time to print - * - * @return string form of the time (as milliseconds) - */ -const char * -GNUNET_TIME_relative_to_string (struct GNUNET_TIME_Relative time) -{ - static char time_string[21]; - - memset (time_string, 0, sizeof (time_string)); - - sprintf (time_string, "%llu", (unsigned long long) time.rel_value); - return (const char *) time_string; -} - - /* end of time.c */ diff --git a/src/util/util.conf b/src/util/util.conf index f3d301e..ea8ddc0 100644 --- a/src/util/util.conf +++ b/src/util/util.conf @@ -9,6 +9,9 @@ SERVICEHOME = ~/.gnunet/ [gnunetd] HOSTKEY = $SERVICEHOME/.hostkey +[PEER] +PRIVATE_KEY = $SERVICEHOME/private.ecc + [client] HOME = $SERVICEHOME diff --git a/src/util/w32cat.c b/src/util/w32cat.c new file mode 100644 index 0000000..292bd6d --- /dev/null +++ b/src/util/w32cat.c @@ -0,0 +1,108 @@ +/* + W32 version of 'cat' program + (C) 2012 LRN + + cat 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 3, or (at your + option) any later version. + + cat 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 cat; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include <stdio.h> +#include <windows.h> + +int +main (int argc, char **argv) +{ + HANDLE stdi, stdo; + BOOL b; + wchar_t *commandlinew, **argvw; + int argcw; + int i; + + stdo = GetStdHandle (STD_OUTPUT_HANDLE); + if (stdo == INVALID_HANDLE_VALUE || stdo == NULL) + return 1; + + commandlinew = GetCommandLineW (); + argvw = CommandLineToArgvW (commandlinew, &argcw); + if (argvw == NULL) + return 1; + + for (i = 1; i < argcw || argcw == 1; i++) + { + DWORD r, w; + int is_dash = wcscmp (argvw[i], L"-") == 0; + if (argcw == 1 || is_dash) + { + stdi = GetStdHandle (STD_INPUT_HANDLE); + if (stdi == INVALID_HANDLE_VALUE) + { + fprintf (stderr, "cat: Failed to obtain stdin handle.\n"); + return 4; + } + if (stdi == NULL) + { + fprintf (stderr, "cat: Have no stdin.\n"); + return 5; + } + } + else + { + stdi = CreateFileW (argvw[i], GENERIC_READ, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL); + if (stdi == INVALID_HANDLE_VALUE) + { + wchar_t *msgbuf; + DWORD le = GetLastError (); + if (0 < FormatMessageW (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 0, le, 0, (wchar_t *) &msgbuf, 0, NULL)) + { + fprintf (stderr, "cat: Failed to open file `%S'. Error %lu.\n", argvw[i], le); + return 3; + } + fprintf (stderr, "cat: Failed to open file `%S'. Error %lu: %S\n", argvw[i], le, msgbuf); + if (msgbuf != NULL) + LocalFree (msgbuf); + return 2; + } + } + do + { + unsigned char c; + b = ReadFile (stdi, &c, 1, &r, NULL); + if (b && r > 0) + { + b = WriteFile (stdo, &c, 1, &w, NULL); + if (b == 0) + { + wchar_t *msgbuf; + DWORD le = GetLastError (); + if (0 < FormatMessageW (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 0, le, 0, (wchar_t *) &msgbuf, 0, NULL)) + { + fprintf (stderr, "cat: Failed to write into stdout. Error %lu.\n", le); + return 3; + } + fprintf (stderr, "cat: Failed to write into stdout. Error %lu: %S\n", le, msgbuf); + if (msgbuf != NULL) + LocalFree (msgbuf); + return 6; + } + } + } while (b && r > 0); + if (argcw == 1) + break; + if (!is_dash) + CloseHandle (stdi); + } + LocalFree (argvw); + return 0; +} diff --git a/src/util/win.cc b/src/util/win.c index 1f66072..99b8b69 100644 --- a/src/util/win.cc +++ b/src/util/win.c @@ -1,1266 +1,1329 @@ -/*
- This file is part of GNUnet.
- (C) 2001, 2002, 2003, 2004, 2005, 2006 Christian Grothoff (and other contributing authors)
-
- GNUnet 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.
-
- GNUnet 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 GNUnet; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file util/win.cc
- * @brief Helper functions for MS Windows in C++
- * @author Nils Durner
- */
-
-#ifndef _WIN_CC
-#define _WIN_CC
-
-#include "winproc.h"
-#include "platform.h"
-#include "gnunet_common.h"
-#include "gnunet_connection_lib.h"
-
-#include <list>
-using namespace std;
-#include <ntdef.h>
-
-#ifndef INHERITED_ACE
-#define INHERITED_ACE 0x10
-#endif
-
-extern "C" {
-
-int plibc_conv_to_win_path(const char *pszUnix, char *pszWindows);
-
-#define _IP_ADAPTER_UNICAST_ADDRESS_HEAD \
- union { \
- struct { \
- ULONG Length; \
- DWORD Flags; \
- }; \
- }; \
-
-#define _IP_ADAPTER_UNICAST_ADDRESS_BASE \
- SOCKET_ADDRESS Address; \
- IP_PREFIX_ORIGIN PrefixOrigin; \
- IP_SUFFIX_ORIGIN SuffixOrigin; \
- IP_DAD_STATE DadState; \
- ULONG ValidLifetime; \
- ULONG PreferredLifetime; \
- ULONG LeaseLifetime;
-
-#define _IP_ADAPTER_UNICAST_ADDRESS_ADD_VISTA \
- UINT8 OnLinkPrefixLength;
-
-
-#define _IP_ADAPTER_UNICAST_ADDRESS_DEFINE(suffix,addition) \
-typedef struct _IP_ADAPTER_UNICAST_ADDRESS##suffix { \
- _IP_ADAPTER_UNICAST_ADDRESS_HEAD \
- struct _IP_ADAPTER_UNICAST_ADDRESS##suffix *Next; \
- _IP_ADAPTER_UNICAST_ADDRESS_BASE \
- addition \
-} IP_ADAPTER_UNICAST_ADDRESS##suffix, *PIP_ADAPTER_UNICAST_ADDRESS##suffix;
-
-/* _IP_ADAPTER_UNICAST_ADDRESS_DEFINE(,) defined in w32api headers */
-_IP_ADAPTER_UNICAST_ADDRESS_DEFINE(_VISTA,_IP_ADAPTER_UNICAST_ADDRESS_ADD_VISTA)
-
-
-typedef struct _IP_ADAPTER_WINS_SERVER_ADDRESS {
- union {
- ULONGLONG Alignment;
- struct {
- ULONG Length;
- DWORD Reserved;
- };
- };
- struct _IP_ADAPTER_WINS_SERVER_ADDRESS *Next;
- SOCKET_ADDRESS Address;
-} IP_ADAPTER_WINS_SERVER_ADDRESS, *PIP_ADAPTER_WINS_SERVER_ADDRESS, *PIP_ADAPTER_WINS_SERVER_ADDRESS_LH;
-
-typedef struct _IP_ADAPTER_GATEWAY_ADDRESS {
- union {
- ULONGLONG Alignment;
- struct {
- ULONG Length;
- DWORD Reserved;
- };
- };
- struct _IP_ADAPTER_GATEWAY_ADDRESS *Next;
- SOCKET_ADDRESS Address;
-} IP_ADAPTER_GATEWAY_ADDRESS, *PIP_ADAPTER_GATEWAY_ADDRESS, *PIP_ADAPTER_GATEWAY_ADDRESS_LH;
-
-typedef UINT32 NET_IF_COMPARTMENT_ID;
-typedef GUID NET_IF_NETWORK_GUID;
-
-typedef enum _NET_IF_CONNECTION_TYPE {
- NET_IF_CONNECTION_DEDICATED = 1,
- NET_IF_CONNECTION_PASSIVE,
- NET_IF_CONNECTION_DEMAND,
- NET_IF_CONNECTION_MAXIMUM
-} NET_IF_CONNECTION_TYPE, *PNET_IF_CONNECTION_TYPE;
-
-typedef enum {
- TUNNEL_TYPE_NONE = 0,
- TUNNEL_TYPE_OTHER,
- TUNNEL_TYPE_DIRECT,
- TUNNEL_TYPE_6TO4,
- TUNNEL_TYPE_ISATAP,
- TUNNEL_TYPE_TEREDO,
- TUNNEL_TYPE_IPHTTPS
-} TUNNEL_TYPE, *PTUNNEL_TYPE;
-
-/*
-A DUID consists of a two-octet type code represented in network byte
- order, followed by a variable number of octets that make up the
- actual identifier. A DUID can be no more than 128 octets long (not
- including the type code).
-*/
-#define MAX_DHCPV6_DUID_LENGTH 130
-
-typedef union _NET_LUID {
- ULONG64 Value;
- struct {
- ULONG64 Reserved :24;
- ULONG64 NetLuidIndex :24;
- ULONG64 IfType :16;
- } Info;
-} NET_LUID, *PNET_LUID, IF_LUID;
-
-#define MAX_DNS_SUFFIX_STRING_LENGTH 246
-
-typedef struct _IP_ADAPTER_DNS_SUFFIX {
- struct _IP_ADAPTER_DNS_SUFFIX *Next;
- WCHAR String[MAX_DNS_SUFFIX_STRING_LENGTH];
-} IP_ADAPTER_DNS_SUFFIX, *PIP_ADAPTER_DNS_SUFFIX;
-
-
-
-#define _IP_ADAPTER_ADDRESSES_HEAD \
- union { \
- ULONGLONG Alignment; \
- struct { \
- ULONG Length; \
- DWORD IfIndex; \
- }; \
- };
-
-#define _IP_ADAPTER_ADDRESSES_BASE \
- PCHAR AdapterName; \
- PIP_ADAPTER_UNICAST_ADDRESS FirstUnicastAddress; \
- PIP_ADAPTER_ANYCAST_ADDRESS FirstAnycastAddress; \
- PIP_ADAPTER_MULTICAST_ADDRESS FirstMulticastAddress; \
- PIP_ADAPTER_DNS_SERVER_ADDRESS FirstDnsServerAddress; \
- PWCHAR DnsSuffix; \
- PWCHAR Description; \
- PWCHAR FriendlyName; \
- BYTE PhysicalAddress[MAX_ADAPTER_ADDRESS_LENGTH]; \
- DWORD PhysicalAddressLength; \
- DWORD Flags; \
- DWORD Mtu; \
- DWORD IfType; \
- IF_OPER_STATUS OperStatus;
-
-#define _IP_ADAPTER_ADDRESSES_ADD_XPSP1 \
- DWORD Ipv6IfIndex; \
- DWORD ZoneIndices[16]; \
- PIP_ADAPTER_PREFIX FirstPrefix; \
-
-
-#define _IP_ADAPTER_ADDRESSES_ADD_VISTA \
- _IP_ADAPTER_ADDRESSES_ADD_XPSP1 \
- ULONG64 TransmitLinkSpeed; \
- ULONG64 ReceiveLinkSpeed; \
- PIP_ADAPTER_WINS_SERVER_ADDRESS_LH FirstWinsServerAddress; \
- PIP_ADAPTER_GATEWAY_ADDRESS_LH FirstGatewayAddress; \
- ULONG Ipv4Metric; \
- ULONG Ipv6Metric; \
- IF_LUID Luid; \
- SOCKET_ADDRESS Dhcpv4Server; \
- NET_IF_COMPARTMENT_ID CompartmentId; \
- NET_IF_NETWORK_GUID NetworkGuid; \
- NET_IF_CONNECTION_TYPE ConnectionType; \
- TUNNEL_TYPE TunnelType; \
- SOCKET_ADDRESS Dhcpv6Server; \
- BYTE Dhcpv6ClientDuid[MAX_DHCPV6_DUID_LENGTH]; \
- ULONG Dhcpv6ClientDuidLength; \
- ULONG Dhcpv6Iaid;
-
-#define _IP_ADAPTER_ADDRESSES_ADD_2008_OR_VISTASP1 \
- _IP_ADAPTER_ADDRESSES_ADD_VISTA \
- PIP_ADAPTER_DNS_SUFFIX FirstDnsSuffix;
-
-#define _IP_ADAPTER_ADDRESSES_DEFINE(suffix,addition) \
-typedef struct _IP_ADAPTER_ADDRESSES##suffix { \
- _IP_ADAPTER_ADDRESSES_HEAD \
- struct _IP_ADAPTER_ADDRESSES##suffix *Next; \
- _IP_ADAPTER_ADDRESSES_BASE \
- addition \
-} IP_ADAPTER_ADDRESSES##suffix, *PIP_ADAPTER_ADDRESSES##suffix;
-
-
-/* _IP_ADAPTER_ADDRESSES_DEFINE(,) defined in w32api headers */
-_IP_ADAPTER_ADDRESSES_DEFINE(_XPSP1,_IP_ADAPTER_ADDRESSES_ADD_XPSP1)
-_IP_ADAPTER_ADDRESSES_DEFINE(_VISTA,_IP_ADAPTER_ADDRESSES_ADD_VISTA)
-_IP_ADAPTER_ADDRESSES_DEFINE(_2008_OR_VISTASP1,_IP_ADAPTER_ADDRESSES_ADD_2008_OR_VISTASP1)
-
-static int
-EnumNICs_IPv6_get_ifs_count (SOCKET s)
-{
- DWORD dwret = 0, err;
- int iret;
- iret = WSAIoctl (s, SIO_ADDRESS_LIST_QUERY, NULL, 0, NULL, 0,
- &dwret, NULL, NULL);
- err = GetLastError ();
- if (iret == SOCKET_ERROR && err == WSAEFAULT)
- return dwret;
- else if (iret == 0)
- return 0;
- return GNUNET_SYSERR;
-}
-
-static int
-EnumNICs_IPv6_get_ifs (SOCKET s, SOCKET_ADDRESS_LIST *inf, int size)
-{
- int iret;
- DWORD dwret = 0;
- iret = WSAIoctl (s, SIO_ADDRESS_LIST_QUERY, NULL, 0, inf, size,
- &dwret, NULL, NULL);
-
- if (iret != 0 || dwret != size)
- {
- /* It's supposed to succeed! And size should be the same */
- return GNUNET_SYSERR;
- }
- return GNUNET_OK;
-}
-
-#undef GNUNET_malloc
-#define GNUNET_malloc(a) HeapAlloc(GetProcessHeap (), HEAP_ZERO_MEMORY | \
- HEAP_GENERATE_EXCEPTIONS, a)
-
-#undef GNUNET_free
-#define GNUNET_free(a) HeapFree(GetProcessHeap (), 0, a)
-
-#undef GNUNET_free_non_null
-#define GNUNET_free_non_null(a) do { if ((a) != NULL) GNUNET_free(a); } while (0)
-
-static int
-EnumNICs_IPv4_get_ifs (SOCKET s, INTERFACE_INFO **inf, int *size)
-{
- int iret;
- DWORD dwret = 0;
- DWORD error;
- INTERFACE_INFO *ii = NULL;
- DWORD ii_size = sizeof (INTERFACE_INFO) * 15;
- while (TRUE)
- {
- if (ii_size >= sizeof (INTERFACE_INFO) * 1000)
- return GNUNET_SYSERR;
- ii = (INTERFACE_INFO *) GNUNET_malloc (ii_size);
- dwret = 0;
- iret = WSAIoctl (s, SIO_GET_INTERFACE_LIST, NULL, 0, ii, ii_size,
- &dwret, NULL, NULL);
- error = GetLastError ();
- if (iret == SOCKET_ERROR)
- {
- if (error == WSAEFAULT)
- {
- GNUNET_free (ii);
- ii_size *= 2;
- continue;
- }
- GNUNET_free (ii);
- return GNUNET_SYSERR;
- }
- else
- {
- *inf = ii;
- *size = dwret;
- return GNUNET_OK;
- }
- }
- return GNUNET_SYSERR;
-}
-
-int
-EnumNICs2 (INTERFACE_INFO **ifs4, int *ifs4_len, SOCKET_ADDRESS_LIST **ifs6)
-{
- int result = 0;
- SOCKET s4 = INVALID_SOCKET, s6 = INVALID_SOCKET;
- DWORD dwret1 = 0, dwret2;
- DWORD err1, err2;
- int ifs4len = 0, ifs6len = 0;
- INTERFACE_INFO *interfaces4 = NULL;
- SOCKET_ADDRESS_LIST *interfaces6 = NULL;
- SetLastError (0);
- s4 = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
- err1 = GetLastError ();
- SetLastError (0);
- s6 = socket (AF_INET6, SOCK_STREAM, IPPROTO_TCP);
- err2 = GetLastError ();
- if (s6 != INVALID_SOCKET)
- {
- ifs6len = EnumNICs_IPv6_get_ifs_count (s6);
- if (ifs6len > 0)
- {
- interfaces6 = (SOCKET_ADDRESS_LIST *) GNUNET_malloc (ifs6len);
- result = EnumNICs_IPv6_get_ifs (s6, interfaces6, ifs6len) || result;
- }
- closesocket (s6);
- s6 = INVALID_SOCKET;
- }
-
- if (s4 != INVALID_SOCKET)
- {
- result = EnumNICs_IPv4_get_ifs (s4, &interfaces4, &ifs4len) || result;
- closesocket (s4);
- s4 = INVALID_SOCKET;
- }
- if (ifs6len + ifs4len == 0)
- goto error;
-
- if (!result)
- {
- *ifs4 = interfaces4;
- *ifs4_len = ifs4len;
- *ifs6 = interfaces6;
- return GNUNET_OK;
- }
-error:
- if (interfaces4 != NULL)
- GNUNET_free (interfaces4);
- if (interfaces6 != NULL)
- GNUNET_free (interfaces6);
- if (s4 != INVALID_SOCKET)
- closesocket (s4);
- if (s6 != INVALID_SOCKET)
- closesocket (s6);
- return GNUNET_SYSERR;
-}
-
-/**
- * Returns GNUNET_OK on OK, GNUNET_SYSERR on error
- */
-int
-EnumNICs3 (struct EnumNICs3_results **results, int *results_count)
-{
- DWORD dwRetVal = 0;
- int count = 0;
- ULONG flags = /*GAA_FLAG_INCLUDE_PREFIX |*/ GAA_FLAG_SKIP_ANYCAST |
- GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER;
- struct sockaddr_in6 examplecom6;
- IPAddr examplecom;
- DWORD best_interface = 0;
- DWORD best_interface6 = 0;
-
- int use_enum2 = 0;
- INTERFACE_INFO *interfaces4 = NULL;
- int interfaces4_len = 0;
- SOCKET_ADDRESS_LIST *interfaces6 = NULL;
-
- unsigned long outBufLen = sizeof (IP_ADAPTER_ADDRESSES);
- IP_ADAPTER_ADDRESSES *pCurrentAddress = NULL;
- IP_ADAPTER_ADDRESSES *pAddresses = (IP_ADAPTER_ADDRESSES *) GNUNET_malloc (outBufLen);
-
- if (GetAdaptersAddresses (AF_UNSPEC, flags, NULL, pAddresses, &outBufLen)
- == ERROR_BUFFER_OVERFLOW)
- {
- GNUNET_free (pAddresses);
- pAddresses = (IP_ADAPTER_ADDRESSES *) GNUNET_malloc (outBufLen);
- }
-
- dwRetVal = GetAdaptersAddresses (AF_UNSPEC, flags, NULL, pAddresses, &outBufLen);
-
- if (dwRetVal != NO_ERROR)
- {
- GNUNET_free (pAddresses);
- return GNUNET_SYSERR;
- }
-
- if (pAddresses->Length < sizeof (IP_ADAPTER_ADDRESSES_VISTA))
- {
- use_enum2 = 1;
-
- /* Enumerate NICs using WSAIoctl() */
- if (GNUNET_OK != EnumNICs2 (&interfaces4, &interfaces4_len, &interfaces6))
- {
- GNUNET_free (pAddresses);
- return GNUNET_SYSERR;
- }
- }
-
- examplecom = inet_addr("192.0.34.166"); /* www.example.com */
- if (GetBestInterface (examplecom, &best_interface) != NO_ERROR)
- best_interface = 0;
-
- if (GNGetBestInterfaceEx != NULL)
- {
- examplecom6.sin6_family = AF_INET6;
- examplecom6.sin6_port = 0;
- examplecom6.sin6_flowinfo = 0;
- examplecom6.sin6_scope_id = 0;
- inet_pton (AF_INET6, "2001:500:88:200:0:0:0:10",
- (struct sockaddr *) &examplecom6.sin6_addr);
- dwRetVal = GNGetBestInterfaceEx ((struct sockaddr *) &examplecom6,
- &best_interface6);
- if (dwRetVal != NO_ERROR)
- best_interface6 = 0;
- }
-
- /* Give IPv6 a priority */
- if (best_interface6 != 0)
- best_interface = best_interface6;
-
- count = 0;
- for (pCurrentAddress = pAddresses;
- pCurrentAddress != NULL; pCurrentAddress = pCurrentAddress->Next)
- {
- if (pCurrentAddress->OperStatus == IfOperStatusUp)
- {
- IP_ADAPTER_UNICAST_ADDRESS *unicast = NULL;
- for (unicast = pCurrentAddress->FirstUnicastAddress; unicast != NULL;
- unicast = unicast->Next)
- {
- if ((unicast->Address.lpSockaddr->sa_family == AF_INET ||
- unicast->Address.lpSockaddr->sa_family == AF_INET6) &&
- (unicast->DadState == IpDadStateDeprecated ||
- unicast->DadState == IpDadStatePreferred))
- count += 1;
- }
- }
- }
-
- if (count == 0)
- {
- *results = NULL;
- *results_count = 0;
- GNUNET_free (pAddresses);
- GNUNET_free_non_null (interfaces4);
- GNUNET_free_non_null (interfaces6);
- return GNUNET_OK;
- }
-
- *results = (struct EnumNICs3_results *) GNUNET_malloc (
- sizeof (struct EnumNICs3_results) * count);
- *results_count = count;
-
- count = 0;
- for (pCurrentAddress = pAddresses;
- pCurrentAddress != NULL; pCurrentAddress = pCurrentAddress->Next)
- {
- struct EnumNICs3_results *r;
- IP_ADAPTER_UNICAST_ADDRESS *unicast = NULL;
- if (pCurrentAddress->OperStatus != IfOperStatusUp)
- continue;
- for (unicast = pCurrentAddress->FirstUnicastAddress; unicast != NULL;
- unicast = unicast->Next)
- {
- int i, j;
- int mask_length = -1;
- char dst[INET6_ADDRSTRLEN + 1];
-
- if ((unicast->Address.lpSockaddr->sa_family != AF_INET &&
- unicast->Address.lpSockaddr->sa_family != AF_INET6) ||
- (unicast->DadState != IpDadStateDeprecated &&
- unicast->DadState != IpDadStatePreferred))
- continue;
-
- r = &(*results)[count];
- r->flags = 0;
- if (pCurrentAddress->IfIndex > 0 &&
- pCurrentAddress->IfIndex == best_interface &&
- unicast->Address.lpSockaddr->sa_family == AF_INET)
- r->is_default = 1;
- else if (pCurrentAddress->Ipv6IfIndex > 0 &&
- pCurrentAddress->Ipv6IfIndex == best_interface6 &&
- unicast->Address.lpSockaddr->sa_family == AF_INET6)
- r->is_default = 1;
- else
- r->is_default = 0;
-
- /* Don't choose default interface twice */
- if (r->is_default)
- best_interface = best_interface6 = 0;
-
- if (!use_enum2)
- {
- memcpy (&r->address, unicast->Address.lpSockaddr,
- unicast->Address.iSockaddrLength);
- memset (&r->mask, 0, sizeof (struct sockaddr));
- mask_length = ((IP_ADAPTER_UNICAST_ADDRESS_VISTA *) unicast)->
- OnLinkPrefixLength;
- /* OnLinkPrefixLength is the number of leading 1s in the mask.
- * OnLinkPrefixLength is available on Vista and later (hence use_enum2).
- */
- if (unicast->Address.lpSockaddr->sa_family == AF_INET)
- {
- struct sockaddr_in *m = (struct sockaddr_in *) &r->mask;
- for (i = 0; i < mask_length; i++)
- ((unsigned char *) &m->sin_addr)[i / 8] |= 0x80 >> (i % 8);
- }
- else if (unicast->Address.lpSockaddr->sa_family == AF_INET6)
- {
- struct sockaddr_in6 *m = (struct sockaddr_in6 *) &r->mask;
- struct sockaddr_in6 *b = (struct sockaddr_in6 *) &r->broadcast;
- for (i = 0; i < mask_length; i++)
- ((unsigned char *) &m->sin6_addr)[i / 8] |= 0x80 >> (i % 8);
- memcpy (&r->broadcast, &r->address, unicast->Address.iSockaddrLength);
- for (i = mask_length; i < 128; i++)
- ((unsigned char *) &b->sin6_addr)[i / 8] |= 0x80 >> (i % 8);
- }
- r->flags |= ENUMNICS3_MASK_OK;
- }
- else
- {
- int found = 0;
- if (unicast->Address.lpSockaddr->sa_family == AF_INET)
- {
- for (i = 0; !found && i < interfaces4_len / sizeof (INTERFACE_INFO); i++)
- {
- struct sockaddr_in *m = (struct sockaddr_in *) &r->mask;
- if (memcpy (&interfaces4[i].iiAddress.Address,
- unicast->Address.lpSockaddr,
- unicast->Address.iSockaddrLength) != 0)
- continue;
- found = 1;
- memcpy (&r->address, &interfaces4[i].iiAddress.Address,
- sizeof (struct sockaddr_in));
- memcpy (&r->mask, &interfaces4[i].iiNetmask.Address,
- sizeof (struct sockaddr_in));
- for (mask_length = 0;
- ((unsigned char *) &m->sin_addr)[mask_length / 8] &
- 0x80 >> (mask_length % 8); mask_length++)
- {
- }
- r->flags |= ENUMNICS3_MASK_OK;
- }
- }
- else if (unicast->Address.lpSockaddr->sa_family == AF_INET6)
- {
- for (i = 0;
- interfaces6 != NULL && !found && i < interfaces6->iAddressCount;
- i++)
- {
- if (memcpy (interfaces6->Address[i].lpSockaddr,
- unicast->Address.lpSockaddr,
- unicast->Address.iSockaddrLength) != 0)
- continue;
- found = 1;
- memcpy (&r->address, interfaces6->Address[i].lpSockaddr,
- sizeof (struct sockaddr_in6));
- /* TODO: Find a way to reliably get network mask for IPv6 on XP */
- memset (&r->mask, 0, sizeof (struct sockaddr));
- r->flags &= ~ENUMNICS3_MASK_OK;
- }
- }
- if (!found)
- {
- DebugBreak ();
- }
- }
- if (unicast->Address.lpSockaddr->sa_family == AF_INET)
- {
- struct sockaddr_in *m = (struct sockaddr_in *) &r->mask;
- struct sockaddr_in *a = (struct sockaddr_in *) &r->address;
- /* copy address to broadcast, then flip all the trailing bits not
- * falling under netmask to 1,
- * so we get, 192.168.0.255 from, say, 192.168.0.43 with mask == 24.
- */
- memcpy (&r->broadcast, &r->address, unicast->Address.iSockaddrLength);
- for (i = mask_length; i < 32; i++)
- ((unsigned char *) &m->sin_addr)[i / 8] |= 0x80 >> (i % 8);
- r->flags |= ENUMNICS3_BCAST_OK;
- r->addr_size = sizeof (struct sockaddr_in);
- inet_ntop (AF_INET, &a->sin_addr, dst, INET_ADDRSTRLEN);
- }
- else if (unicast->Address.lpSockaddr->sa_family == AF_INET6)
- {
- struct sockaddr_in6 *a = (struct sockaddr_in6 *) &r->address;
- /* for IPv6 broadcast is not defined, zero it down */
- memset (&r->broadcast, 0, sizeof (struct sockaddr));
- r->flags &= ~ENUMNICS3_BCAST_OK;
- r->addr_size = sizeof (struct sockaddr_in6);
- inet_ntop (AF_INET6, &a->sin6_addr, dst, INET6_ADDRSTRLEN);
- }
-
- i = 0;
- i += snprintf (&r->pretty_name[i], 1000 - i > 0 ? 1000 - i : 0,
- "%S (%s", pCurrentAddress->FriendlyName, dst);
- for (j = 0; j < pCurrentAddress->PhysicalAddressLength; j++)
- i += snprintf (&r->pretty_name[i], 1000 - i > 0 ? 1000 - i : 0,
- "%s%02X",j > 0 ? ":" : " - ", pCurrentAddress->PhysicalAddress[j]);
- i += snprintf (&r->pretty_name[i], 1000 - i > 0 ? 1000 - i : 0, ")");
- r->pretty_name[1000] = '\0';
- count += 1;
- }
- }
-
- if (use_enum2)
- {
- GNUNET_free_non_null (interfaces4);
- GNUNET_free_non_null (interfaces6);
- }
-
- GNUNET_free (pAddresses);
- return GNUNET_OK;
-}
-
-void
-EnumNICs3_free (struct EnumNICs3_results *r)
-{
- GNUNET_free_non_null (r);
-}
-
-
-/**
- * Lists all network interfaces in a combo box
- * Used by the basic GTK configurator
- *
- * @param callback function to call for each NIC
- * @param callback_cls closure for callback
- */
-int
-ListNICs (void (*callback) (void *, const char *, int), void * callback_cls)
-{
- int r;
- int i;
- struct EnumNICs3_results *results = NULL;
- int results_count;
-
- r = EnumNICs3 (&results, &results_count);
- if (r != GNUNET_OK)
- return GNUNET_NO;
-
- for (i = 0; i < results_count; i++)
- callback (callback_cls, results[i].pretty_name, results[i].is_default);
- GNUNET_free_non_null (results);
- return GNUNET_YES;
-}
-
-/**
- * @brief Installs the Windows service
- * @param servicename name of the service as diplayed by the SCM
- * @param application path to the application binary
- * @param username the name of the service's user account
- * @returns 0 on success
- * 1 if the Windows version doesn't support services
- * 2 if the SCM could not be opened
- * 3 if the service could not be created
- */
-int InstallAsService(char *servicename, char *application, char *username)
-{
- SC_HANDLE hManager, hService;
- char szEXE[_MAX_PATH + 17] = "\"";
- char *user = NULL;
-
- if (! GNOpenSCManager)
- return 1;
-
- plibc_conv_to_win_path(application, szEXE + 1);
- strcat(szEXE, "\" --win-service");
- hManager = GNOpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
- if (! hManager)
- return 2;
-
- if (username)
- {
- user = (char *) malloc(strlen(username) + 3);
- sprintf(user, ".\\%s", username);
- }
-
- hService = GNCreateService(hManager, (LPCTSTR) servicename, (LPCTSTR) servicename, 0,
- SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, (LPCTSTR) szEXE,
- NULL, NULL, NULL, (LPCTSTR) user, (LPCTSTR) username);
-
- if (user)
- free(user);
-
- if (! hService)
- return 3;
-
- GNCloseServiceHandle(hService);
-
- return 0;
-}
-
-/**
- * @brief Uninstall Windows service
- * @param servicename name of the service to delete
- * @returns 0 on success
- * 1 if the Windows version doesn't support services
- * 2 if the SCM could not be openend
- * 3 if the service cannot be accessed
- * 4 if the service cannot be deleted
- */
-int UninstallService(char *servicename)
-{
- SC_HANDLE hManager, hService;
-
- if (! GNOpenSCManager)
- return 1;
-
- hManager = GNOpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
- if (! hManager)
- return 2;
-
- if (! (hService = GNOpenService(hManager, (LPCTSTR) servicename, DELETE)))
- if (GetLastError() != ERROR_SERVICE_DOES_NOT_EXIST)
- return 3;
- else
- goto closeSCM;
-
- if (! GNDeleteService(hService))
- if (GetLastError() != ERROR_SERVICE_MARKED_FOR_DELETE)
- return 4;
-
-closeSCM:
- GNCloseServiceHandle(hService);
-
- return 0;
-}
-
-/**
- * @author Scott Field, Microsoft
- * @see http://support.microsoft.com/?scid=kb;en-us;132958
- * @date 12-Jul-95
- */
-void _InitLsaString(PLSA_UNICODE_STRING LsaString, LPWSTR String)
-{
- DWORD StringLength;
-
- if(String == NULL)
- {
- LsaString->Buffer = NULL;
- LsaString->Length = 0;
- LsaString->MaximumLength = 0;
- return;
- }
-
- StringLength = wcslen(String);
- LsaString->Buffer = String;
- LsaString->Length = (USHORT) StringLength *sizeof(WCHAR);
- LsaString->MaximumLength = (USHORT) (StringLength + 1) * sizeof(WCHAR);
-}
-
-
-/**
- * @author Scott Field, Microsoft
- * @see http://support.microsoft.com/?scid=kb;en-us;132958
- * @date 12-Jul-95
- */
-NTSTATUS _OpenPolicy(LPWSTR ServerName, DWORD DesiredAccess, PLSA_HANDLE PolicyHandle)
-{
- LSA_OBJECT_ATTRIBUTES ObjectAttributes;
- LSA_UNICODE_STRING ServerString;
- PLSA_UNICODE_STRING Server = NULL;
-
- /* Always initialize the object attributes to all zeroes. */
- ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
-
- if(ServerName != NULL)
- {
- /* Make a LSA_UNICODE_STRING out of the LPWSTR passed in */
- _InitLsaString(&ServerString, ServerName);
- Server = &ServerString;
- }
-
- /* Attempt to open the policy. */
- return GNLsaOpenPolicy(Server,
- &ObjectAttributes, DesiredAccess, PolicyHandle);
-}
-
-/**
- * @brief Obtain a SID representing the supplied account on the supplied system
- * @return TRUE on success, FALSE on failure
- * @author Scott Field, Microsoft
- * @date 12-Jul-95
- * @remarks A buffer is allocated which contains the SID representing the
- * supplied account. This buffer should be freed when it is no longer
- * needed by calling\n
- * HeapFree(GetProcessHeap(), 0, buffer)
- * @remarks Call GetLastError() to obtain extended error information.
- * @see http://support.microsoft.com/?scid=kb;en-us;132958
- */
-BOOL _GetAccountSid(LPCTSTR SystemName, LPCTSTR AccountName, PSID * Sid)
-{
- LPTSTR ReferencedDomain = NULL;
- DWORD cbSid = 128; /* initial allocation attempt */
- DWORD cchReferencedDomain = 16; /* initial allocation size */
- SID_NAME_USE peUse;
- BOOL bSuccess = FALSE; /* assume this function will fail */
-
- /* initial memory allocations */
- if ((*Sid = HeapAlloc (GetProcessHeap (), 0, cbSid)) == NULL)
- return FALSE;
-
- if ((ReferencedDomain = (LPTSTR) HeapAlloc (GetProcessHeap (),
- 0,
- cchReferencedDomain *
- sizeof (TCHAR))) == NULL)
- return FALSE;
-
- /* Obtain the SID of the specified account on the specified system. */
- while (!GNLookupAccountName(SystemName, /* machine to lookup account on */
- AccountName, /* account to lookup */
- *Sid, /* SID of interest */
- &cbSid, /* size of SID */
- ReferencedDomain, /* domain account was found on */
- &cchReferencedDomain, &peUse))
- {
- if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
- {
- /* reallocate memory */
- if ((*Sid = HeapReAlloc (GetProcessHeap (), 0, *Sid, cbSid)) == NULL)
- return FALSE;
-
- if ((ReferencedDomain = (LPTSTR) HeapReAlloc (GetProcessHeap (),
- 0,
- ReferencedDomain,
- cchReferencedDomain
- * sizeof (TCHAR))) == NULL)
- return FALSE;
- }
- else
- goto end;
- }
-
- /* Indicate success. */
- bSuccess = TRUE;
-
-end:
- /* Cleanup and indicate failure, if appropriate. */
- HeapFree (GetProcessHeap (), 0, ReferencedDomain);
-
- if (!bSuccess)
- {
- if (*Sid != NULL)
- {
- HeapFree (GetProcessHeap (), 0, *Sid);
- *Sid = NULL;
- }
- }
-
- return bSuccess;
-}
-
-/**
- * @author Scott Field, Microsoft
- * @see http://support.microsoft.com/?scid=kb;en-us;132958
- * @date 12-Jul-95
- */
-NTSTATUS _SetPrivilegeOnAccount(LSA_HANDLE PolicyHandle,/* open policy handle */
- PSID AccountSid, /* SID to grant privilege to */
- LPWSTR PrivilegeName, /* privilege to grant (Unicode) */
- BOOL bEnable /* enable or disable */
- )
-{
- LSA_UNICODE_STRING PrivilegeString;
-
- /* Create a LSA_UNICODE_STRING for the privilege name. */
- _InitLsaString(&PrivilegeString, PrivilegeName);
-
- /* grant or revoke the privilege, accordingly */
- if(bEnable)
- {
- NTSTATUS i;
-
- i = GNLsaAddAccountRights(PolicyHandle, /* open policy handle */
- AccountSid, /* target SID */
- &PrivilegeString, /* privileges */
- 1 /* privilege count */
- );
- }
- else
- {
- return GNLsaRemoveAccountRights(PolicyHandle, /* open policy handle */
- AccountSid, /* target SID */
- FALSE, /* do not disable all rights */
- &PrivilegeString, /* privileges */
- 1 /* privilege count */
- );
- }
-}
-
-/**
- * @brief Create a Windows service account
- * @return 0 on success, > 0 otherwise
- * @param pszName the name of the account
- * @param pszDesc description of the account
- */
-int CreateServiceAccount(const char *pszName, const char *pszDesc)
-{
- USER_INFO_1 ui;
- USER_INFO_1008 ui2;
- NET_API_STATUS nStatus;
- wchar_t wszName[MAX_NAME_LENGTH], wszDesc[MAX_NAME_LENGTH];
- DWORD dwErr;
- LSA_HANDLE hPolicy;
- PSID pSID;
-
- if (! GNNetUserAdd)
- return 1;
- mbstowcs(wszName, pszName, strlen(pszName) + 1);
- mbstowcs(wszDesc, pszDesc, strlen(pszDesc) + 1);
-
- memset(&ui, 0, sizeof(ui));
- ui.usri1_name = wszName;
- ui.usri1_password = wszName; /* account is locked anyway */
- ui.usri1_priv = USER_PRIV_USER;
- ui.usri1_comment = wszDesc;
- ui.usri1_flags = UF_SCRIPT;
-
- nStatus = GNNetUserAdd(NULL, 1, (LPBYTE)&ui, NULL);
-
- if (nStatus != NERR_Success && nStatus != NERR_UserExists)
- return 2;
-
- ui2.usri1008_flags = UF_PASSWD_CANT_CHANGE | UF_DONT_EXPIRE_PASSWD;
- GNNetUserSetInfo(NULL, wszName, 1008, (LPBYTE)&ui2, NULL);
-
- if (_OpenPolicy(NULL, POLICY_ALL_ACCESS, &hPolicy) !=
- STATUS_SUCCESS)
- return 3;
-
- _GetAccountSid(NULL, (LPCTSTR) pszName, &pSID);
-
- if (_SetPrivilegeOnAccount(hPolicy, pSID, (LPWSTR) L"SeServiceLogonRight", TRUE) != STATUS_SUCCESS)
- return 4;
-
- _SetPrivilegeOnAccount(hPolicy, pSID, (LPWSTR) L"SeDenyInteractiveLogonRight", TRUE);
- _SetPrivilegeOnAccount(hPolicy, pSID, (LPWSTR) L"SeDenyBatchLogonRight", TRUE);
- _SetPrivilegeOnAccount(hPolicy, pSID, (LPWSTR) L"SeDenyNetworkLogonRight", TRUE);
-
- GNLsaClose(hPolicy);
-
- return 0;
-}
-
-/**
- * @brief Grant permission to a file
- * @param lpszFileName the name of the file or directory
- * @param lpszAccountName the user account
- * @param dwAccessMask the desired access (e.g. GENERIC_ALL)
- * @return TRUE on success
- * @remark based on http://support.microsoft.com/default.aspx?scid=KB;EN-US;Q102102&
- */
-BOOL AddPathAccessRights(char *lpszFileName, char *lpszAccountName,
- DWORD dwAccessMask)
-{
- /* SID variables. */
- SID_NAME_USE snuType;
- TCHAR * szDomain = NULL;
- DWORD cbDomain = 0;
- LPVOID pUserSID = NULL;
- DWORD cbUserSID = 0;
-
- /* File SD variables. */
- PSECURITY_DESCRIPTOR pFileSD = NULL;
- DWORD cbFileSD = 0;
-
- /* New SD variables. */
- SECURITY_DESCRIPTOR newSD;
-
- /* ACL variables. */
- PACL pACL = NULL;
- BOOL fDaclPresent;
- BOOL fDaclDefaulted;
- ACL_SIZE_INFORMATION AclInfo;
-
- /* New ACL variables. */
- PACL pNewACL = NULL;
- DWORD cbNewACL = 0;
-
- /* Temporary ACE. */
- LPVOID pTempAce = NULL;
- UINT CurrentAceIndex = 0;
-
- UINT newAceIndex = 0;
-
- /* Assume function will fail. */
- BOOL fResult = FALSE;
- BOOL fAPISuccess;
-
- SECURITY_INFORMATION secInfo = DACL_SECURITY_INFORMATION;
-
- /**
- * STEP 1: Get SID of the account name specified.
- */
- fAPISuccess = GNLookupAccountName(NULL, (LPCTSTR) lpszAccountName,
- pUserSID, &cbUserSID, (LPTSTR) szDomain, &cbDomain, &snuType);
-
- /* API should have failed with insufficient buffer. */
- if (fAPISuccess)
- goto end;
- else if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
- goto end;
- }
-
- pUserSID = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbUserSID);
- if (!pUserSID) {
- goto end;
- }
-
- szDomain = (TCHAR *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbDomain * sizeof(TCHAR));
- if (!szDomain) {
- goto end;
- }
-
- fAPISuccess = GNLookupAccountName(NULL, (LPCTSTR) lpszAccountName,
- pUserSID, &cbUserSID, (LPTSTR) szDomain, &cbDomain, &snuType);
- if (!fAPISuccess) {
- goto end;
- }
-
- /**
- * STEP 2: Get security descriptor (SD) of the file specified.
- */
- fAPISuccess = GNGetFileSecurity((LPCTSTR) lpszFileName,
- secInfo, pFileSD, 0, &cbFileSD);
-
- /* API should have failed with insufficient buffer. */
- if (fAPISuccess)
- goto end;
- else if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
- goto end;
- }
-
- pFileSD = (PSECURITY_DESCRIPTOR) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
- cbFileSD);
- if (!pFileSD) {
- goto end;
- }
-
- fAPISuccess = GNGetFileSecurity((LPCTSTR) lpszFileName,
- secInfo, pFileSD, cbFileSD, &cbFileSD);
- if (!fAPISuccess) {
- goto end;
- }
-
- /**
- * STEP 3: Initialize new SD.
- */
- if (!GNInitializeSecurityDescriptor(&newSD,
- SECURITY_DESCRIPTOR_REVISION)) {
- goto end;
- }
-
- /**
- * STEP 4: Get DACL from the old SD.
- */
- if (!GNGetSecurityDescriptorDacl(pFileSD, &fDaclPresent, &pACL,
- &fDaclDefaulted)) {
- goto end;
- }
-
- /**
- * STEP 5: Get size information for DACL.
- */
- AclInfo.AceCount = 0; // Assume NULL DACL.
- AclInfo.AclBytesFree = 0;
- AclInfo.AclBytesInUse = sizeof(ACL);
-
- if (pACL == NULL)
- fDaclPresent = FALSE;
-
- /* If not NULL DACL, gather size information from DACL. */
- if (fDaclPresent) {
-
- if (!GNGetAclInformation(pACL, &AclInfo,
- sizeof(ACL_SIZE_INFORMATION), AclSizeInformation)) {
- goto end;
- }
- }
-
- /**
- * STEP 6: Compute size needed for the new ACL.
- */
- cbNewACL = AclInfo.AclBytesInUse + sizeof(ACCESS_ALLOWED_ACE)
- + GetLengthSid(pUserSID) - sizeof(DWORD);
-
- /**
- * STEP 7: Allocate memory for new ACL.
- */
- pNewACL = (PACL) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbNewACL);
- if (!pNewACL) {
- goto end;
- }
-
- /**
- * STEP 8: Initialize the new ACL.
- */
- if (!GNInitializeAcl(pNewACL, cbNewACL, ACL_REVISION2)) {
- goto end;
- }
-
- /**
- * STEP 9 If DACL is present, copy all the ACEs from the old DACL
- * to the new DACL.
- *
- * The following code assumes that the old DACL is
- * already in Windows 2000 preferred order. To conform
- * to the new Windows 2000 preferred order, first we will
- * copy all non-inherited ACEs from the old DACL to the
- * new DACL, irrespective of the ACE type.
- */
-
- newAceIndex = 0;
-
- if (fDaclPresent && AclInfo.AceCount) {
-
- for (CurrentAceIndex = 0;
- CurrentAceIndex < AclInfo.AceCount;
- CurrentAceIndex++) {
-
- /**
- * TEP 10: Get an ACE.
- */
- if (!GNGetAce(pACL, CurrentAceIndex, &pTempAce)) {
- goto end;
- }
-
- /**
- * STEP 11: Check if it is a non-inherited ACE.
- * If it is an inherited ACE, break from the loop so
- * that the new access allowed non-inherited ACE can
- * be added in the correct position, immediately after
- * all non-inherited ACEs.
- */
- if (((ACCESS_ALLOWED_ACE *)pTempAce)->Header.AceFlags
- & INHERITED_ACE)
- break;
-
- /**
- * STEP 12: Skip adding the ACE, if the SID matches
- * with the account specified, as we are going to
- * add an access allowed ACE with a different access
- * mask.
- */
- if (GNEqualSid(pUserSID,
- &(((ACCESS_ALLOWED_ACE *)pTempAce)->SidStart)))
- continue;
-
- /**
- * STEP 13: Add the ACE to the new ACL.
- */
- if (!GNAddAce(pNewACL, ACL_REVISION, MAXDWORD, pTempAce,
- ((PACE_HEADER) pTempAce)->AceSize)) {
- goto end;
- }
-
- newAceIndex++;
- }
- }
-
- /**
- * STEP 14: Add the access-allowed ACE to the new DACL.
- * The new ACE added here will be in the correct position,
- * immediately after all existing non-inherited ACEs.
- */
- if (!GNAddAccessAllowedAce(pNewACL, ACL_REVISION2, dwAccessMask,
- pUserSID)) {
- goto end;
- }
-
- /**
- * STEP 14.5: Make new ACE inheritable
- */
- if (!GetAce(pNewACL, newAceIndex, &pTempAce))
- goto end;
- ((ACCESS_ALLOWED_ACE *)pTempAce)->Header.AceFlags |=
- (CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE);
-
- /**
- * STEP 15: To conform to the new Windows 2000 preferred order,
- * we will now copy the rest of inherited ACEs from the
- * old DACL to the new DACL.
- */
- if (fDaclPresent && AclInfo.AceCount) {
-
- for (;
- CurrentAceIndex < AclInfo.AceCount;
- CurrentAceIndex++) {
-
- /**
- * STEP 16: Get an ACE.
- */
- if (!GNGetAce(pACL, CurrentAceIndex, &pTempAce)) {
- goto end;
- }
-
- /**
- * STEP 17: Add the ACE to the new ACL.
- */
- if (!GNAddAce(pNewACL, ACL_REVISION, MAXDWORD, pTempAce,
- ((PACE_HEADER) pTempAce)->AceSize)) {
- goto end;
- }
- }
- }
-
- /**
- * STEP 18: Set permissions
- */
- if (GNSetNamedSecurityInfo((LPTSTR) lpszFileName, SE_FILE_OBJECT,
- DACL_SECURITY_INFORMATION, NULL, NULL, pNewACL, NULL) != ERROR_SUCCESS) {
- goto end;
- }
-
- fResult = TRUE;
-
-end:
-
- /**
- * STEP 19: Free allocated memory
- */
- if (pUserSID)
- HeapFree(GetProcessHeap(), 0, pUserSID);
-
- if (szDomain)
- HeapFree(GetProcessHeap(), 0, szDomain);
-
- if (pFileSD)
- HeapFree(GetProcessHeap(), 0, pFileSD);
-
- if (pNewACL)
- HeapFree(GetProcessHeap(), 0, pNewACL);
-
- return fResult;
-}
-
-char *winErrorStr(const char *prefix, int dwErr)
-{
- char *err, *ret;
- int mem;
-
- if (! FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
- NULL, (DWORD) dwErr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &err,
- 0, NULL ))
- {
- err = (char *) LocalAlloc (LMEM_FIXED | LMEM_ZEROINIT, 1);
- }
-
- mem = strlen(err) + strlen(prefix) + 20;
- ret = (char *) malloc(mem);
-
- snprintf(ret, mem, "%s: %s (#%u)", prefix, err, dwErr);
-
- LocalFree(err);
-
- return ret;
-}
-
-} /* extern "C" */
-
-#endif
+/* + This file is part of GNUnet. + (C) 2001, 2002, 2003, 2004, 2005, 2006 Christian Grothoff (and other contributing authors) + + GNUnet 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. + + GNUnet 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 GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/** + * @file util/win.c + * @brief Helper functions for MS Windows in C++ + * @author Nils Durner + */ + +#ifndef _WIN_C +#define _WIN_C + +#include "winproc.h" +#include "platform.h" +#include "gnunet_common.h" +#include "gnunet_connection_lib.h" + +#include <ntdef.h> + +#ifndef INHERITED_ACE +#define INHERITED_ACE 0x10 +#endif + +int plibc_conv_to_win_path(const char *pszUnix, char *pszWindows); + +#define _IP_ADAPTER_UNICAST_ADDRESS_HEAD \ + union { \ + struct { \ + ULONG Length; \ + DWORD Flags; \ + }; \ + }; + +#define _IP_ADAPTER_UNICAST_ADDRESS_BASE \ + SOCKET_ADDRESS Address; \ + IP_PREFIX_ORIGIN PrefixOrigin; \ + IP_SUFFIX_ORIGIN SuffixOrigin; \ + IP_DAD_STATE DadState; \ + ULONG ValidLifetime; \ + ULONG PreferredLifetime; \ + ULONG LeaseLifetime; + +#define _IP_ADAPTER_UNICAST_ADDRESS_ADD_VISTA \ + UINT8 OnLinkPrefixLength; + + +#define _IP_ADAPTER_UNICAST_ADDRESS_DEFINE(suffix,addition) \ +typedef struct _IP_ADAPTER_UNICAST_ADDRESS##suffix { \ + _IP_ADAPTER_UNICAST_ADDRESS_HEAD \ + struct _IP_ADAPTER_UNICAST_ADDRESS##suffix *Next; \ + _IP_ADAPTER_UNICAST_ADDRESS_BASE \ + addition \ +} IP_ADAPTER_UNICAST_ADDRESS##suffix, *PIP_ADAPTER_UNICAST_ADDRESS##suffix; + +/* _IP_ADAPTER_UNICAST_ADDRESS_DEFINE(,) defined in w32api headers */ +_IP_ADAPTER_UNICAST_ADDRESS_DEFINE(_VISTA,_IP_ADAPTER_UNICAST_ADDRESS_ADD_VISTA) + + +typedef struct _IP_ADAPTER_WINS_SERVER_ADDRESS { + union { + ULONGLONG Alignment; + struct { + ULONG Length; + DWORD Reserved; + }; + }; + struct _IP_ADAPTER_WINS_SERVER_ADDRESS *Next; + SOCKET_ADDRESS Address; +} IP_ADAPTER_WINS_SERVER_ADDRESS, *PIP_ADAPTER_WINS_SERVER_ADDRESS, *PIP_ADAPTER_WINS_SERVER_ADDRESS_LH; + +typedef struct _IP_ADAPTER_GATEWAY_ADDRESS { + union { + ULONGLONG Alignment; + struct { + ULONG Length; + DWORD Reserved; + }; + }; + struct _IP_ADAPTER_GATEWAY_ADDRESS *Next; + SOCKET_ADDRESS Address; +} IP_ADAPTER_GATEWAY_ADDRESS, *PIP_ADAPTER_GATEWAY_ADDRESS, *PIP_ADAPTER_GATEWAY_ADDRESS_LH; + +typedef UINT32 NET_IF_COMPARTMENT_ID; +typedef GUID NET_IF_NETWORK_GUID; + +typedef enum _NET_IF_CONNECTION_TYPE { + NET_IF_CONNECTION_DEDICATED = 1, + NET_IF_CONNECTION_PASSIVE, + NET_IF_CONNECTION_DEMAND, + NET_IF_CONNECTION_MAXIMUM +} NET_IF_CONNECTION_TYPE, *PNET_IF_CONNECTION_TYPE; + +typedef enum { + TUNNEL_TYPE_NONE = 0, + TUNNEL_TYPE_OTHER, + TUNNEL_TYPE_DIRECT, + TUNNEL_TYPE_6TO4, + TUNNEL_TYPE_ISATAP, + TUNNEL_TYPE_TEREDO, + TUNNEL_TYPE_IPHTTPS +} TUNNEL_TYPE, *PTUNNEL_TYPE; + +/* +A DUID consists of a two-octet type code represented in network byte + order, followed by a variable number of octets that make up the + actual identifier. A DUID can be no more than 128 octets long (not + including the type code). +*/ +#define MAX_DHCPV6_DUID_LENGTH 130 + +typedef union _NET_LUID { + ULONG64 Value; + struct { + ULONG64 Reserved :24; + ULONG64 NetLuidIndex :24; + ULONG64 IfType :16; + } Info; +} NET_LUID, *PNET_LUID, IF_LUID; + +#define MAX_DNS_SUFFIX_STRING_LENGTH 246 + +typedef struct _IP_ADAPTER_DNS_SUFFIX { + struct _IP_ADAPTER_DNS_SUFFIX *Next; + WCHAR String[MAX_DNS_SUFFIX_STRING_LENGTH]; +} IP_ADAPTER_DNS_SUFFIX, *PIP_ADAPTER_DNS_SUFFIX; + + + +#define _IP_ADAPTER_ADDRESSES_HEAD \ + union { \ + ULONGLONG Alignment; \ + struct { \ + ULONG Length; \ + DWORD IfIndex; \ + }; \ + }; + +#define _IP_ADAPTER_ADDRESSES_BASE \ + PCHAR AdapterName; \ + PIP_ADAPTER_UNICAST_ADDRESS FirstUnicastAddress; \ + PIP_ADAPTER_ANYCAST_ADDRESS FirstAnycastAddress; \ + PIP_ADAPTER_MULTICAST_ADDRESS FirstMulticastAddress; \ + PIP_ADAPTER_DNS_SERVER_ADDRESS FirstDnsServerAddress; \ + PWCHAR DnsSuffix; \ + PWCHAR Description; \ + PWCHAR FriendlyName; \ + BYTE PhysicalAddress[MAX_ADAPTER_ADDRESS_LENGTH]; \ + DWORD PhysicalAddressLength; \ + DWORD Flags; \ + DWORD Mtu; \ + DWORD IfType; \ + IF_OPER_STATUS OperStatus; + +#define _IP_ADAPTER_ADDRESSES_ADD_XPSP1 \ + DWORD Ipv6IfIndex; \ + DWORD ZoneIndices[16]; \ + PIP_ADAPTER_PREFIX FirstPrefix; \ + + +#define _IP_ADAPTER_ADDRESSES_ADD_VISTA \ + _IP_ADAPTER_ADDRESSES_ADD_XPSP1 \ + ULONG64 TransmitLinkSpeed; \ + ULONG64 ReceiveLinkSpeed; \ + PIP_ADAPTER_WINS_SERVER_ADDRESS_LH FirstWinsServerAddress; \ + PIP_ADAPTER_GATEWAY_ADDRESS_LH FirstGatewayAddress; \ + ULONG Ipv4Metric; \ + ULONG Ipv6Metric; \ + IF_LUID Luid; \ + SOCKET_ADDRESS Dhcpv4Server; \ + NET_IF_COMPARTMENT_ID CompartmentId; \ + NET_IF_NETWORK_GUID NetworkGuid; \ + NET_IF_CONNECTION_TYPE ConnectionType; \ + TUNNEL_TYPE TunnelType; \ + SOCKET_ADDRESS Dhcpv6Server; \ + BYTE Dhcpv6ClientDuid[MAX_DHCPV6_DUID_LENGTH]; \ + ULONG Dhcpv6ClientDuidLength; \ + ULONG Dhcpv6Iaid; + +#define _IP_ADAPTER_ADDRESSES_ADD_2008_OR_VISTASP1 \ + _IP_ADAPTER_ADDRESSES_ADD_VISTA \ + PIP_ADAPTER_DNS_SUFFIX FirstDnsSuffix; + +#define _IP_ADAPTER_ADDRESSES_DEFINE(suffix,addition) \ +typedef struct _IP_ADAPTER_ADDRESSES##suffix { \ + _IP_ADAPTER_ADDRESSES_HEAD \ + struct _IP_ADAPTER_ADDRESSES##suffix *Next; \ + _IP_ADAPTER_ADDRESSES_BASE \ + addition \ +} IP_ADAPTER_ADDRESSES##suffix, *PIP_ADAPTER_ADDRESSES##suffix; + + +/* _IP_ADAPTER_ADDRESSES_DEFINE(,) defined in w32api headers */ +_IP_ADAPTER_ADDRESSES_DEFINE(_XPSP1,_IP_ADAPTER_ADDRESSES_ADD_XPSP1) +_IP_ADAPTER_ADDRESSES_DEFINE(_VISTA,_IP_ADAPTER_ADDRESSES_ADD_VISTA) +_IP_ADAPTER_ADDRESSES_DEFINE(_2008_OR_VISTASP1,_IP_ADAPTER_ADDRESSES_ADD_2008_OR_VISTASP1) + +static int +EnumNICs_IPv6_get_ifs_count (SOCKET s) +{ + DWORD dwret = 0, err; + int iret; + iret = WSAIoctl (s, SIO_ADDRESS_LIST_QUERY, NULL, 0, NULL, 0, + &dwret, NULL, NULL); + err = GetLastError (); + if (iret == SOCKET_ERROR && err == WSAEFAULT) + return dwret; + else if (iret == 0) + return 0; + return GNUNET_SYSERR; +} + +static int +EnumNICs_IPv6_get_ifs (SOCKET s, SOCKET_ADDRESS_LIST *inf, int size) +{ + int iret; + DWORD dwret = 0; + iret = WSAIoctl (s, SIO_ADDRESS_LIST_QUERY, NULL, 0, inf, size, + &dwret, NULL, NULL); + + if (iret != 0 || dwret != size) + { + /* It's supposed to succeed! And size should be the same */ + return GNUNET_SYSERR; + } + return GNUNET_OK; +} + +#undef GNUNET_malloc +#define GNUNET_malloc(a) HeapAlloc(GetProcessHeap (), HEAP_ZERO_MEMORY | \ + HEAP_GENERATE_EXCEPTIONS, a) + +#undef GNUNET_free +#define GNUNET_free(a) HeapFree(GetProcessHeap (), 0, a) + +#undef GNUNET_free_non_null +#define GNUNET_free_non_null(a) do { if ((a) != NULL) GNUNET_free(a); } while (0) + +static int +EnumNICs_IPv4_get_ifs (SOCKET s, INTERFACE_INFO **inf, int *size) +{ + int iret; + DWORD dwret = 0; + DWORD error; + INTERFACE_INFO *ii = NULL; + DWORD ii_size = sizeof (INTERFACE_INFO) * 15; + while (TRUE) + { + if (ii_size >= sizeof (INTERFACE_INFO) * 1000) + return GNUNET_SYSERR; + ii = (INTERFACE_INFO *) GNUNET_malloc (ii_size); + dwret = 0; + iret = WSAIoctl (s, SIO_GET_INTERFACE_LIST, NULL, 0, ii, ii_size, + &dwret, NULL, NULL); + error = GetLastError (); + if (iret == SOCKET_ERROR) + { + if (error == WSAEFAULT) + { + GNUNET_free (ii); + ii_size *= 2; + continue; + } + GNUNET_free (ii); + return GNUNET_SYSERR; + } + else + { + *inf = ii; + *size = dwret; + return GNUNET_OK; + } + } + return GNUNET_SYSERR; +} + +int +EnumNICs2 (INTERFACE_INFO **ifs4, int *ifs4_len, SOCKET_ADDRESS_LIST **ifs6) +{ + int result = 0; + SOCKET s4 = INVALID_SOCKET, s6 = INVALID_SOCKET; + DWORD dwret1 = 0, dwret2; + DWORD err1, err2; + int ifs4len = 0, ifs6len = 0; + INTERFACE_INFO *interfaces4 = NULL; + SOCKET_ADDRESS_LIST *interfaces6 = NULL; + SetLastError (0); + s4 = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); + err1 = GetLastError (); + SetLastError (0); + s6 = socket (AF_INET6, SOCK_STREAM, IPPROTO_TCP); + err2 = GetLastError (); + if (s6 != INVALID_SOCKET) + { + ifs6len = EnumNICs_IPv6_get_ifs_count (s6); + if (ifs6len > 0) + { + interfaces6 = (SOCKET_ADDRESS_LIST *) GNUNET_malloc (ifs6len); + result = EnumNICs_IPv6_get_ifs (s6, interfaces6, ifs6len) || result; + } + closesocket (s6); + s6 = INVALID_SOCKET; + } + + if (s4 != INVALID_SOCKET) + { + result = EnumNICs_IPv4_get_ifs (s4, &interfaces4, &ifs4len) || result; + closesocket (s4); + s4 = INVALID_SOCKET; + } + if (ifs6len + ifs4len == 0) + goto error; + + if (!result) + { + *ifs4 = interfaces4; + *ifs4_len = ifs4len; + *ifs6 = interfaces6; + return GNUNET_OK; + } +error: + if (interfaces4 != NULL) + GNUNET_free (interfaces4); + if (interfaces6 != NULL) + GNUNET_free (interfaces6); + if (s4 != INVALID_SOCKET) + closesocket (s4); + if (s6 != INVALID_SOCKET) + closesocket (s6); + return GNUNET_SYSERR; +} + +/** + * Returns GNUNET_OK on OK, GNUNET_SYSERR on error + */ +int +EnumNICs3 (struct EnumNICs3_results **results, int *results_count) +{ + DWORD dwRetVal = 0; + int count = 0; + ULONG flags = /*GAA_FLAG_INCLUDE_PREFIX |*/ GAA_FLAG_SKIP_ANYCAST | + GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER; + struct sockaddr_in6 examplecom6; + IPAddr examplecom; + DWORD best_interface = 0; + DWORD best_interface6 = 0; + + int use_enum2 = 0; + INTERFACE_INFO *interfaces4 = NULL; + int interfaces4_len = 0; + SOCKET_ADDRESS_LIST *interfaces6 = NULL; + + unsigned long outBufLen = sizeof (IP_ADAPTER_ADDRESSES); + IP_ADAPTER_ADDRESSES *pCurrentAddress = NULL; + IP_ADAPTER_ADDRESSES *pAddresses = (IP_ADAPTER_ADDRESSES *) GNUNET_malloc (outBufLen); + + if (GetAdaptersAddresses (AF_UNSPEC, flags, NULL, pAddresses, &outBufLen) + == ERROR_BUFFER_OVERFLOW) + { + GNUNET_free (pAddresses); + pAddresses = (IP_ADAPTER_ADDRESSES *) GNUNET_malloc (outBufLen); + } + + dwRetVal = GetAdaptersAddresses (AF_UNSPEC, flags, NULL, pAddresses, &outBufLen); + + if (dwRetVal != NO_ERROR) + { + GNUNET_free (pAddresses); + return GNUNET_SYSERR; + } + + if (pAddresses->Length < sizeof (IP_ADAPTER_ADDRESSES_VISTA)) + { + use_enum2 = 1; + + /* Enumerate NICs using WSAIoctl() */ + if (GNUNET_OK != EnumNICs2 (&interfaces4, &interfaces4_len, &interfaces6)) + { + GNUNET_free (pAddresses); + return GNUNET_SYSERR; + } + } + + examplecom = inet_addr("192.0.34.166"); /* www.example.com */ + if (GetBestInterface (examplecom, &best_interface) != NO_ERROR) + best_interface = 0; + + if (GNGetBestInterfaceEx != NULL) + { + examplecom6.sin6_family = AF_INET6; + examplecom6.sin6_port = 0; + examplecom6.sin6_flowinfo = 0; + examplecom6.sin6_scope_id = 0; + inet_pton (AF_INET6, "2001:500:88:200:0:0:0:10", + (struct sockaddr *) &examplecom6.sin6_addr); + dwRetVal = GNGetBestInterfaceEx ((struct sockaddr *) &examplecom6, + &best_interface6); + if (dwRetVal != NO_ERROR) + best_interface6 = 0; + } + + /* Give IPv6 a priority */ + if (best_interface6 != 0) + best_interface = best_interface6; + + count = 0; + for (pCurrentAddress = pAddresses; + pCurrentAddress != NULL; pCurrentAddress = pCurrentAddress->Next) + { + if (pCurrentAddress->OperStatus == IfOperStatusUp) + { + IP_ADAPTER_UNICAST_ADDRESS *unicast = NULL; + for (unicast = pCurrentAddress->FirstUnicastAddress; unicast != NULL; + unicast = unicast->Next) + { + if ((unicast->Address.lpSockaddr->sa_family == AF_INET || + unicast->Address.lpSockaddr->sa_family == AF_INET6) && + (unicast->DadState == IpDadStateDeprecated || + unicast->DadState == IpDadStatePreferred)) + count += 1; + } + } + } + + if (count == 0) + { + *results = NULL; + *results_count = 0; + GNUNET_free (pAddresses); + GNUNET_free_non_null (interfaces4); + GNUNET_free_non_null (interfaces6); + return GNUNET_OK; + } + + *results = (struct EnumNICs3_results *) GNUNET_malloc ( + sizeof (struct EnumNICs3_results) * count); + *results_count = count; + + count = 0; + for (pCurrentAddress = pAddresses; + pCurrentAddress != NULL; pCurrentAddress = pCurrentAddress->Next) + { + struct EnumNICs3_results *r; + IP_ADAPTER_UNICAST_ADDRESS *unicast = NULL; + if (pCurrentAddress->OperStatus != IfOperStatusUp) + continue; + for (unicast = pCurrentAddress->FirstUnicastAddress; unicast != NULL; + unicast = unicast->Next) + { + int i, j; + int mask_length = -1; + char dst[INET6_ADDRSTRLEN + 1]; + + if ((unicast->Address.lpSockaddr->sa_family != AF_INET && + unicast->Address.lpSockaddr->sa_family != AF_INET6) || + (unicast->DadState != IpDadStateDeprecated && + unicast->DadState != IpDadStatePreferred)) + continue; + + r = &(*results)[count]; + r->flags = 0; + if (pCurrentAddress->IfIndex > 0 && + pCurrentAddress->IfIndex == best_interface && + unicast->Address.lpSockaddr->sa_family == AF_INET) + r->is_default = 1; + else if (pCurrentAddress->Ipv6IfIndex > 0 && + pCurrentAddress->Ipv6IfIndex == best_interface6 && + unicast->Address.lpSockaddr->sa_family == AF_INET6) + r->is_default = 1; + else + r->is_default = 0; + + /* Don't choose default interface twice */ + if (r->is_default) + best_interface = best_interface6 = 0; + + if (!use_enum2) + { + memcpy (&r->address, unicast->Address.lpSockaddr, + unicast->Address.iSockaddrLength); + memset (&r->mask, 0, sizeof (struct sockaddr)); + mask_length = ((IP_ADAPTER_UNICAST_ADDRESS_VISTA *) unicast)-> + OnLinkPrefixLength; + /* OnLinkPrefixLength is the number of leading 1s in the mask. + * OnLinkPrefixLength is available on Vista and later (hence use_enum2). + */ + if (unicast->Address.lpSockaddr->sa_family == AF_INET) + { + struct sockaddr_in *m = (struct sockaddr_in *) &r->mask; + for (i = 0; i < mask_length; i++) + ((unsigned char *) &m->sin_addr)[i / 8] |= 0x80 >> (i % 8); + } + else if (unicast->Address.lpSockaddr->sa_family == AF_INET6) + { + struct sockaddr_in6 *m = (struct sockaddr_in6 *) &r->mask; + struct sockaddr_in6 *b = (struct sockaddr_in6 *) &r->broadcast; + for (i = 0; i < mask_length; i++) + ((unsigned char *) &m->sin6_addr)[i / 8] |= 0x80 >> (i % 8); + memcpy (&r->broadcast, &r->address, unicast->Address.iSockaddrLength); + for (i = mask_length; i < 128; i++) + ((unsigned char *) &b->sin6_addr)[i / 8] |= 0x80 >> (i % 8); + } + r->flags |= ENUMNICS3_MASK_OK; + } + else + { + int found = 0; + if (unicast->Address.lpSockaddr->sa_family == AF_INET) + { + for (i = 0; !found && i < interfaces4_len / sizeof (INTERFACE_INFO); i++) + { + struct sockaddr_in *m = (struct sockaddr_in *) &r->mask; + if (memcpy (&interfaces4[i].iiAddress.Address, + unicast->Address.lpSockaddr, + unicast->Address.iSockaddrLength) != 0) + continue; + found = 1; + memcpy (&r->address, &interfaces4[i].iiAddress.Address, + sizeof (struct sockaddr_in)); + memcpy (&r->mask, &interfaces4[i].iiNetmask.Address, + sizeof (struct sockaddr_in)); + for (mask_length = 0; + ((unsigned char *) &m->sin_addr)[mask_length / 8] & + 0x80 >> (mask_length % 8); mask_length++) + { + } + r->flags |= ENUMNICS3_MASK_OK; + } + } + else if (unicast->Address.lpSockaddr->sa_family == AF_INET6) + { + for (i = 0; + interfaces6 != NULL && !found && i < interfaces6->iAddressCount; + i++) + { + if (memcpy (interfaces6->Address[i].lpSockaddr, + unicast->Address.lpSockaddr, + unicast->Address.iSockaddrLength) != 0) + continue; + found = 1; + memcpy (&r->address, interfaces6->Address[i].lpSockaddr, + sizeof (struct sockaddr_in6)); + /* TODO: Find a way to reliably get network mask for IPv6 on XP */ + memset (&r->mask, 0, sizeof (struct sockaddr)); + r->flags &= ~ENUMNICS3_MASK_OK; + } + } + if (!found) + { + DebugBreak (); + } + } + if (unicast->Address.lpSockaddr->sa_family == AF_INET) + { + struct sockaddr_in *m = (struct sockaddr_in *) &r->mask; + struct sockaddr_in *a = (struct sockaddr_in *) &r->address; + /* copy address to broadcast, then flip all the trailing bits not + * falling under netmask to 1, + * so we get, 192.168.0.255 from, say, 192.168.0.43 with mask == 24. + */ + memcpy (&r->broadcast, &r->address, unicast->Address.iSockaddrLength); + for (i = mask_length; i < 32; i++) + ((unsigned char *) &m->sin_addr)[i / 8] |= 0x80 >> (i % 8); + r->flags |= ENUMNICS3_BCAST_OK; + r->addr_size = sizeof (struct sockaddr_in); + inet_ntop (AF_INET, &a->sin_addr, dst, INET_ADDRSTRLEN); + } + else if (unicast->Address.lpSockaddr->sa_family == AF_INET6) + { + struct sockaddr_in6 *a = (struct sockaddr_in6 *) &r->address; + /* for IPv6 broadcast is not defined, zero it down */ + memset (&r->broadcast, 0, sizeof (struct sockaddr)); + r->flags &= ~ENUMNICS3_BCAST_OK; + r->addr_size = sizeof (struct sockaddr_in6); + inet_ntop (AF_INET6, &a->sin6_addr, dst, INET6_ADDRSTRLEN); + } + + i = 0; + i += snprintf (&r->pretty_name[i], 1000 - i > 0 ? 1000 - i : 0, + "%S (%s", pCurrentAddress->FriendlyName, dst); + for (j = 0; j < pCurrentAddress->PhysicalAddressLength; j++) + i += snprintf (&r->pretty_name[i], 1000 - i > 0 ? 1000 - i : 0, + "%s%02X",j > 0 ? ":" : " - ", pCurrentAddress->PhysicalAddress[j]); + i += snprintf (&r->pretty_name[i], 1000 - i > 0 ? 1000 - i : 0, ")"); + r->pretty_name[1000] = '\0'; + count += 1; + } + } + + if (use_enum2) + { + GNUNET_free_non_null (interfaces4); + GNUNET_free_non_null (interfaces6); + } + + GNUNET_free (pAddresses); + return GNUNET_OK; +} + +void +EnumNICs3_free (struct EnumNICs3_results *r) +{ + GNUNET_free_non_null (r); +} + + +/** + * Lists all network interfaces in a combo box + * Used by the basic GTK configurator + * + * @param callback function to call for each NIC + * @param callback_cls closure for callback + */ +int +ListNICs (void (*callback) (void *, const char *, int), void * callback_cls) +{ + int r; + int i; + struct EnumNICs3_results *results = NULL; + int results_count; + + r = EnumNICs3 (&results, &results_count); + if (r != GNUNET_OK) + return GNUNET_NO; + + for (i = 0; i < results_count; i++) + callback (callback_cls, results[i].pretty_name, results[i].is_default); + GNUNET_free_non_null (results); + return GNUNET_YES; +} + +/** + * @brief Installs the Windows service + * @param servicename name of the service as diplayed by the SCM + * @param application path to the application binary + * @param username the name of the service's user account + * @returns 0 on success + * 1 if the Windows version doesn't support services + * 2 if the SCM could not be opened + * 3 if the service could not be created + */ +int InstallAsService(char *servicename, char *application, char *username) +{ + SC_HANDLE hManager, hService; + char szEXE[_MAX_PATH + 17] = "\""; + char *user = NULL; + + if (! GNOpenSCManager) + return 1; + + plibc_conv_to_win_path(application, szEXE + 1); + strcat(szEXE, "\" --win-service"); + hManager = GNOpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE); + if (! hManager) + return 2; + + if (username) + { + user = (char *) malloc(strlen(username) + 3); + sprintf(user, ".\\%s", username); + } + + hService = GNCreateService(hManager, (LPCTSTR) servicename, (LPCTSTR) servicename, 0, + SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, (LPCTSTR) szEXE, + NULL, NULL, NULL, (LPCTSTR) user, (LPCTSTR) username); + + if (user) + free(user); + + if (! hService) + return 3; + + GNCloseServiceHandle(hService); + + return 0; +} + +/** + * @brief Uninstall Windows service + * @param servicename name of the service to delete + * @returns 0 on success + * 1 if the Windows version doesn't support services + * 2 if the SCM could not be openend + * 3 if the service cannot be accessed + * 4 if the service cannot be deleted + */ +int UninstallService(char *servicename) +{ + SC_HANDLE hManager, hService; + + if (! GNOpenSCManager) + return 1; + + hManager = GNOpenSCManager(NULL, NULL, SC_MANAGER_CONNECT); + if (! hManager) + return 2; + + if (! (hService = GNOpenService(hManager, (LPCTSTR) servicename, DELETE))) + if (GetLastError() != ERROR_SERVICE_DOES_NOT_EXIST) + return 3; + else + goto closeSCM; + + if (! GNDeleteService(hService)) + if (GetLastError() != ERROR_SERVICE_MARKED_FOR_DELETE) + return 4; + +closeSCM: + GNCloseServiceHandle(hService); + + return 0; +} + +/** + * @author Scott Field, Microsoft + * @see http://support.microsoft.com/?scid=kb;en-us;132958 + * @date 12-Jul-95 + */ +void _InitLsaString(PLSA_UNICODE_STRING LsaString, LPWSTR String) +{ + DWORD StringLength; + + if(String == NULL) + { + LsaString->Buffer = NULL; + LsaString->Length = 0; + LsaString->MaximumLength = 0; + return; + } + + StringLength = wcslen(String); + LsaString->Buffer = String; + LsaString->Length = (USHORT) StringLength *sizeof(WCHAR); + LsaString->MaximumLength = (USHORT) (StringLength + 1) * sizeof(WCHAR); +} + + +/** + * @author Scott Field, Microsoft + * @see http://support.microsoft.com/?scid=kb;en-us;132958 + * @date 12-Jul-95 + */ +NTSTATUS _OpenPolicy(LPWSTR ServerName, DWORD DesiredAccess, PLSA_HANDLE PolicyHandle) +{ + LSA_OBJECT_ATTRIBUTES ObjectAttributes; + LSA_UNICODE_STRING ServerString; + PLSA_UNICODE_STRING Server = NULL; + + /* Always initialize the object attributes to all zeroes. */ + ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes)); + + if(ServerName != NULL) + { + /* Make a LSA_UNICODE_STRING out of the LPWSTR passed in */ + _InitLsaString(&ServerString, ServerName); + Server = &ServerString; + } + + /* Attempt to open the policy. */ + return GNLsaOpenPolicy(Server, + &ObjectAttributes, DesiredAccess, PolicyHandle); +} + +/** + * @brief Obtain a SID representing the supplied account on the supplied system + * @return TRUE on success, FALSE on failure + * @author Scott Field, Microsoft + * @date 12-Jul-95 + * @remarks A buffer is allocated which contains the SID representing the + * supplied account. This buffer should be freed when it is no longer + * needed by calling\n + * HeapFree(GetProcessHeap(), 0, buffer) + * @remarks Call GetLastError() to obtain extended error information. + * @see http://support.microsoft.com/?scid=kb;en-us;132958 + */ +BOOL _GetAccountSid(LPCTSTR SystemName, LPCTSTR AccountName, PSID * Sid) +{ + LPTSTR ReferencedDomain = NULL; + DWORD cbSid = 128; /* initial allocation attempt */ + DWORD cchReferencedDomain = 16; /* initial allocation size */ + SID_NAME_USE peUse; + BOOL bSuccess = FALSE; /* assume this function will fail */ + + /* initial memory allocations */ + if ((*Sid = HeapAlloc (GetProcessHeap (), 0, cbSid)) == NULL) + return FALSE; + + if ((ReferencedDomain = (LPTSTR) HeapAlloc (GetProcessHeap (), + 0, + cchReferencedDomain * + sizeof (TCHAR))) == NULL) + return FALSE; + + /* Obtain the SID of the specified account on the specified system. */ + while (!GNLookupAccountName(SystemName, /* machine to lookup account on */ + AccountName, /* account to lookup */ + *Sid, /* SID of interest */ + &cbSid, /* size of SID */ + ReferencedDomain, /* domain account was found on */ + &cchReferencedDomain, &peUse)) + { + if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) + { + /* reallocate memory */ + if ((*Sid = HeapReAlloc (GetProcessHeap (), 0, *Sid, cbSid)) == NULL) + return FALSE; + + if ((ReferencedDomain = (LPTSTR) HeapReAlloc (GetProcessHeap (), + 0, + ReferencedDomain, + cchReferencedDomain + * sizeof (TCHAR))) == NULL) + return FALSE; + } + else + goto end; + } + + /* Indicate success. */ + bSuccess = TRUE; + +end: + /* Cleanup and indicate failure, if appropriate. */ + HeapFree (GetProcessHeap (), 0, ReferencedDomain); + + if (!bSuccess) + { + if (*Sid != NULL) + { + HeapFree (GetProcessHeap (), 0, *Sid); + *Sid = NULL; + } + } + + return bSuccess; +} + +/** + * @author Scott Field, Microsoft + * @see http://support.microsoft.com/?scid=kb;en-us;132958 + * @date 12-Jul-95 + */ +NTSTATUS _SetPrivilegeOnAccount(LSA_HANDLE PolicyHandle,/* open policy handle */ + PSID AccountSid, /* SID to grant privilege to */ + LPWSTR PrivilegeName, /* privilege to grant (Unicode) */ + BOOL bEnable /* enable or disable */ + ) +{ + LSA_UNICODE_STRING PrivilegeString; + + /* Create a LSA_UNICODE_STRING for the privilege name. */ + _InitLsaString(&PrivilegeString, PrivilegeName); + + /* grant or revoke the privilege, accordingly */ + if(bEnable) + { + NTSTATUS i; + + i = GNLsaAddAccountRights(PolicyHandle, /* open policy handle */ + AccountSid, /* target SID */ + &PrivilegeString, /* privileges */ + 1 /* privilege count */ + ); + } + else + { + return GNLsaRemoveAccountRights(PolicyHandle, /* open policy handle */ + AccountSid, /* target SID */ + FALSE, /* do not disable all rights */ + &PrivilegeString, /* privileges */ + 1 /* privilege count */ + ); + } +} + +/** + * @brief Create a Windows service account + * @return 0 on success, > 0 otherwise + * @param pszName the name of the account + * @param pszDesc description of the account + */ +int CreateServiceAccount(const char *pszName, const char *pszDesc) +{ + USER_INFO_1 ui; + USER_INFO_1008 ui2; + NET_API_STATUS nStatus; + wchar_t wszName[MAX_NAME_LENGTH], wszDesc[MAX_NAME_LENGTH]; + DWORD dwErr; + LSA_HANDLE hPolicy; + PSID pSID; + + if (! GNNetUserAdd) + return 1; + mbstowcs(wszName, pszName, strlen(pszName) + 1); + mbstowcs(wszDesc, pszDesc, strlen(pszDesc) + 1); + + memset(&ui, 0, sizeof(ui)); + ui.usri1_name = wszName; + ui.usri1_password = wszName; /* account is locked anyway */ + ui.usri1_priv = USER_PRIV_USER; + ui.usri1_comment = wszDesc; + ui.usri1_flags = UF_SCRIPT; + + nStatus = GNNetUserAdd(NULL, 1, (LPBYTE)&ui, NULL); + + if (nStatus != NERR_Success && nStatus != NERR_UserExists) + return 2; + + ui2.usri1008_flags = UF_PASSWD_CANT_CHANGE | UF_DONT_EXPIRE_PASSWD; + GNNetUserSetInfo(NULL, wszName, 1008, (LPBYTE)&ui2, NULL); + + if (_OpenPolicy(NULL, POLICY_ALL_ACCESS, &hPolicy) != + STATUS_SUCCESS) + return 3; + + _GetAccountSid(NULL, (LPCTSTR) pszName, &pSID); + + if (_SetPrivilegeOnAccount(hPolicy, pSID, (LPWSTR) L"SeServiceLogonRight", TRUE) != STATUS_SUCCESS) + return 4; + + _SetPrivilegeOnAccount(hPolicy, pSID, (LPWSTR) L"SeDenyInteractiveLogonRight", TRUE); + _SetPrivilegeOnAccount(hPolicy, pSID, (LPWSTR) L"SeDenyBatchLogonRight", TRUE); + _SetPrivilegeOnAccount(hPolicy, pSID, (LPWSTR) L"SeDenyNetworkLogonRight", TRUE); + + GNLsaClose(hPolicy); + + return 0; +} + +/** + * @brief Grant permission to a file + * @param lpszFileName the name of the file or directory + * @param lpszAccountName the user account + * @param dwAccessMask the desired access (e.g. GENERIC_ALL) + * @return TRUE on success + * @remark based on http://support.microsoft.com/default.aspx?scid=KB;EN-US;Q102102& + */ +BOOL AddPathAccessRights(char *lpszFileName, char *lpszAccountName, + DWORD dwAccessMask) +{ + /* SID variables. */ + SID_NAME_USE snuType; + TCHAR * szDomain = NULL; + DWORD cbDomain = 0; + LPVOID pUserSID = NULL; + DWORD cbUserSID = 0; + + /* File SD variables. */ + PSECURITY_DESCRIPTOR pFileSD = NULL; + DWORD cbFileSD = 0; + + /* New SD variables. */ + SECURITY_DESCRIPTOR newSD; + + /* ACL variables. */ + PACL pACL = NULL; + BOOL fDaclPresent; + BOOL fDaclDefaulted; + ACL_SIZE_INFORMATION AclInfo; + + /* New ACL variables. */ + PACL pNewACL = NULL; + DWORD cbNewACL = 0; + + /* Temporary ACE. */ + LPVOID pTempAce = NULL; + UINT CurrentAceIndex = 0; + + UINT newAceIndex = 0; + + /* Assume function will fail. */ + BOOL fResult = FALSE; + BOOL fAPISuccess; + + SECURITY_INFORMATION secInfo = DACL_SECURITY_INFORMATION; + + /** + * STEP 1: Get SID of the account name specified. + */ + fAPISuccess = GNLookupAccountName(NULL, (LPCTSTR) lpszAccountName, + pUserSID, &cbUserSID, (LPTSTR) szDomain, &cbDomain, &snuType); + + /* API should have failed with insufficient buffer. */ + if (fAPISuccess) + goto end; + else if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { + goto end; + } + + pUserSID = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbUserSID); + if (!pUserSID) { + goto end; + } + + szDomain = (TCHAR *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbDomain * sizeof(TCHAR)); + if (!szDomain) { + goto end; + } + + fAPISuccess = GNLookupAccountName(NULL, (LPCTSTR) lpszAccountName, + pUserSID, &cbUserSID, (LPTSTR) szDomain, &cbDomain, &snuType); + if (!fAPISuccess) { + goto end; + } + + /** + * STEP 2: Get security descriptor (SD) of the file specified. + */ + fAPISuccess = GNGetFileSecurity((LPCTSTR) lpszFileName, + secInfo, pFileSD, 0, &cbFileSD); + + /* API should have failed with insufficient buffer. */ + if (fAPISuccess) + goto end; + else if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { + goto end; + } + + pFileSD = (PSECURITY_DESCRIPTOR) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + cbFileSD); + if (!pFileSD) { + goto end; + } + + fAPISuccess = GNGetFileSecurity((LPCTSTR) lpszFileName, + secInfo, pFileSD, cbFileSD, &cbFileSD); + if (!fAPISuccess) { + goto end; + } + + /** + * STEP 3: Initialize new SD. + */ + if (!GNInitializeSecurityDescriptor(&newSD, + SECURITY_DESCRIPTOR_REVISION)) { + goto end; + } + + /** + * STEP 4: Get DACL from the old SD. + */ + if (!GNGetSecurityDescriptorDacl(pFileSD, &fDaclPresent, &pACL, + &fDaclDefaulted)) { + goto end; + } + + /** + * STEP 5: Get size information for DACL. + */ + AclInfo.AceCount = 0; // Assume NULL DACL. + AclInfo.AclBytesFree = 0; + AclInfo.AclBytesInUse = sizeof(ACL); + + if (pACL == NULL) + fDaclPresent = FALSE; + + /* If not NULL DACL, gather size information from DACL. */ + if (fDaclPresent) { + + if (!GNGetAclInformation(pACL, &AclInfo, + sizeof(ACL_SIZE_INFORMATION), AclSizeInformation)) { + goto end; + } + } + + /** + * STEP 6: Compute size needed for the new ACL. + */ + cbNewACL = AclInfo.AclBytesInUse + sizeof(ACCESS_ALLOWED_ACE) + + GetLengthSid(pUserSID) - sizeof(DWORD); + + /** + * STEP 7: Allocate memory for new ACL. + */ + pNewACL = (PACL) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbNewACL); + if (!pNewACL) { + goto end; + } + + /** + * STEP 8: Initialize the new ACL. + */ + if (!GNInitializeAcl(pNewACL, cbNewACL, ACL_REVISION2)) { + goto end; + } + + /** + * STEP 9 If DACL is present, copy all the ACEs from the old DACL + * to the new DACL. + * + * The following code assumes that the old DACL is + * already in Windows 2000 preferred order. To conform + * to the new Windows 2000 preferred order, first we will + * copy all non-inherited ACEs from the old DACL to the + * new DACL, irrespective of the ACE type. + */ + + newAceIndex = 0; + + if (fDaclPresent && AclInfo.AceCount) { + + for (CurrentAceIndex = 0; + CurrentAceIndex < AclInfo.AceCount; + CurrentAceIndex++) { + + /** + * TEP 10: Get an ACE. + */ + if (!GNGetAce(pACL, CurrentAceIndex, &pTempAce)) { + goto end; + } + + /** + * STEP 11: Check if it is a non-inherited ACE. + * If it is an inherited ACE, break from the loop so + * that the new access allowed non-inherited ACE can + * be added in the correct position, immediately after + * all non-inherited ACEs. + */ + if (((ACCESS_ALLOWED_ACE *)pTempAce)->Header.AceFlags + & INHERITED_ACE) + break; + + /** + * STEP 12: Skip adding the ACE, if the SID matches + * with the account specified, as we are going to + * add an access allowed ACE with a different access + * mask. + */ + if (GNEqualSid(pUserSID, + &(((ACCESS_ALLOWED_ACE *)pTempAce)->SidStart))) + continue; + + /** + * STEP 13: Add the ACE to the new ACL. + */ + if (!GNAddAce(pNewACL, ACL_REVISION, MAXDWORD, pTempAce, + ((PACE_HEADER) pTempAce)->AceSize)) { + goto end; + } + + newAceIndex++; + } + } + + /** + * STEP 14: Add the access-allowed ACE to the new DACL. + * The new ACE added here will be in the correct position, + * immediately after all existing non-inherited ACEs. + */ + if (!GNAddAccessAllowedAce(pNewACL, ACL_REVISION2, dwAccessMask, + pUserSID)) { + goto end; + } + + /** + * STEP 14.5: Make new ACE inheritable + */ + if (!GetAce(pNewACL, newAceIndex, &pTempAce)) + goto end; + ((ACCESS_ALLOWED_ACE *)pTempAce)->Header.AceFlags |= + (CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE); + + /** + * STEP 15: To conform to the new Windows 2000 preferred order, + * we will now copy the rest of inherited ACEs from the + * old DACL to the new DACL. + */ + if (fDaclPresent && AclInfo.AceCount) { + + for (; + CurrentAceIndex < AclInfo.AceCount; + CurrentAceIndex++) { + + /** + * STEP 16: Get an ACE. + */ + if (!GNGetAce(pACL, CurrentAceIndex, &pTempAce)) { + goto end; + } + + /** + * STEP 17: Add the ACE to the new ACL. + */ + if (!GNAddAce(pNewACL, ACL_REVISION, MAXDWORD, pTempAce, + ((PACE_HEADER) pTempAce)->AceSize)) { + goto end; + } + } + } + + /** + * STEP 18: Set permissions + */ + if (GNSetNamedSecurityInfo((LPTSTR) lpszFileName, SE_FILE_OBJECT, + DACL_SECURITY_INFORMATION, NULL, NULL, pNewACL, NULL) != ERROR_SUCCESS) { + goto end; + } + + fResult = TRUE; + +end: + + /** + * STEP 19: Free allocated memory + */ + if (pUserSID) + HeapFree(GetProcessHeap(), 0, pUserSID); + + if (szDomain) + HeapFree(GetProcessHeap(), 0, szDomain); + + if (pFileSD) + HeapFree(GetProcessHeap(), 0, pFileSD); + + if (pNewACL) + HeapFree(GetProcessHeap(), 0, pNewACL); + + return fResult; +} + +char *winErrorStr(const char *prefix, int dwErr) +{ + char *err, *ret; + int mem; + + if (! FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, (DWORD) dwErr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &err, + 0, NULL )) + { + err = (char *) LocalAlloc (LMEM_FIXED | LMEM_ZEROINIT, 1); + } + + mem = strlen(err) + strlen(prefix) + 20; + ret = (char *) malloc(mem); + + snprintf(ret, mem, "%s: %s (#%u)", prefix, err, dwErr); + + LocalFree(err); + + return ret; +} + +/** + * Terminate a process by creating a remote thread within it, + * which proceeds to call ExitProcess() inside that process. + * Safer than TerminateProcess (). + * + * Code is from From http://private-storm.de/2009/08/11/case-terminateprocess/ + * + * @param hProcess handle of a process to terminate + * @param uExitCode exit code to use for ExitProcess() + * @param dwTimeout number of ms to wait for the process to terminate + * @return TRUE on success, FALSE on failure (check last error for the code) + */ +BOOL +SafeTerminateProcess (HANDLE hProcess, UINT uExitCode, DWORD dwTimeout) +{ + DWORD dwTID, dwCode, dwErr = 0; + HANDLE hProcessDup = INVALID_HANDLE_VALUE; + HANDLE hRT = NULL; + HINSTANCE hKernel = GetModuleHandle ("Kernel32"); + BOOL bSuccess = FALSE; + + BOOL bDup = DuplicateHandle (GetCurrentProcess (), hProcess, + GetCurrentProcess (), &hProcessDup, PROCESS_ALL_ACCESS, + FALSE, 0); + + /* Detect the special case where the process is + * already dead... + */ + if (GetExitCodeProcess (bDup ? hProcessDup : hProcess, &dwCode) && + (STILL_ACTIVE == dwCode)) + { + FARPROC pfnExitProc; + + pfnExitProc = GetProcAddress (hKernel, "ExitProcess"); + + hRT = CreateRemoteThread ((bDup) ? hProcessDup : hProcess, NULL, 0, + (LPTHREAD_START_ROUTINE) pfnExitProc, (PVOID) uExitCode, 0, &dwTID); + + dwErr = GetLastError (); + } + else + { + dwErr = ERROR_PROCESS_ABORTED; + } + + if (hRT) + { + /* Must wait process to terminate to + * guarantee that it has exited... + */ + DWORD dwWaitResult = WaitForSingleObject ((bDup) ? hProcessDup : hProcess, + dwTimeout); + if (dwWaitResult == WAIT_TIMEOUT) + dwErr = WAIT_TIMEOUT; + else + dwErr = GetLastError (); + + CloseHandle (hRT); + bSuccess = dwErr == NO_ERROR; + } + + if (bDup) + CloseHandle (hProcessDup); + + SetLastError (dwErr); + + return bSuccess; +} + +#endif |