aboutsummaryrefslogtreecommitdiff
path: root/src/util
diff options
context:
space:
mode:
Diffstat (limited to 'src/util')
-rw-r--r--src/util/Makefile.am66
-rw-r--r--src/util/Makefile.in606
-rw-r--r--src/util/bandwidth.c7
-rw-r--r--src/util/client.c106
-rw-r--r--src/util/common_allocation.c58
-rw-r--r--src/util/common_logging.c437
-rw-r--r--src/util/configuration.c468
-rw-r--r--src/util/connection.c32
-rw-r--r--src/util/container_bloomfilter.c32
-rw-r--r--src/util/container_heap.c2
-rw-r--r--src/util/container_meta_data.c299
-rw-r--r--src/util/container_multihashmap.c529
-rw-r--r--src/util/crypto_crc.c3
-rw-r--r--src/util/crypto_ecc.c1082
-rw-r--r--src/util/crypto_hash.c72
-rw-r--r--src/util/crypto_ksk.c30
-rw-r--r--src/util/crypto_random.c51
-rw-r--r--src/util/crypto_rsa.c651
-rw-r--r--src/util/disk.c340
-rw-r--r--src/util/getopt.c110
-rw-r--r--src/util/getopt_helpers.c42
-rw-r--r--src/util/gnunet-config.c184
-rw-r--r--src/util/gnunet-ecc.c249
-rw-r--r--src/util/gnunet-resolver.c15
-rw-r--r--src/util/gnunet-rsa.c142
-rw-r--r--src/util/gnunet-service-resolver.c15
-rw-r--r--src/util/gnunet-uri.c184
-rw-r--r--src/util/helper.c119
-rw-r--r--src/util/network.c677
-rw-r--r--src/util/os_installation.c423
-rw-r--r--src/util/os_priority.c891
-rw-r--r--src/util/peer.c100
-rw-r--r--src/util/perf_crypto_hash.c10
-rw-r--r--src/util/perf_malloc.c66
-rw-r--r--src/util/program.c28
-rw-r--r--src/util/pseudonym.c61
-rw-r--r--src/util/resolver.conf.in1
-rw-r--r--src/util/resolver_api.c2
-rw-r--r--src/util/scheduler.c18
-rw-r--r--src/util/server.c136
-rw-r--r--src/util/service.c106
-rw-r--r--src/util/speedup.c5
-rw-r--r--src/util/strings.c294
-rw-r--r--src/util/test_client.c29
-rw-r--r--src/util/test_common_logging_runtime_loglevels.c62
-rw-r--r--src/util/test_configuration.c3
-rw-r--r--src/util/test_connection.c54
-rw-r--r--src/util/test_connection_addressing.c28
-rw-r--r--src/util/test_connection_receive_cancel.c2
-rw-r--r--src/util/test_connection_timeout.c34
-rw-r--r--src/util/test_connection_timeout_no_connect.c32
-rw-r--r--src/util/test_connection_transmit_cancel.c32
-rw-r--r--src/util/test_container_bloomfilter.c8
-rw-r--r--src/util/test_container_multihashmap.c6
-rw-r--r--src/util/test_crypto_ecc.c241
-rw-r--r--src/util/test_crypto_hash.c20
-rw-r--r--src/util/test_crypto_ksk.c23
-rw-r--r--src/util/test_crypto_rsa.c105
-rw-r--r--src/util/test_disk.c2
-rw-r--r--src/util/test_getopt.c13
-rw-r--r--src/util/test_os_network.c32
-rw-r--r--src/util/test_os_priority.c1
-rw-r--r--src/util/test_os_start_process.c61
-rw-r--r--src/util/test_peer.c9
-rw-r--r--src/util/test_plugin.c21
-rw-r--r--src/util/test_pseudonym.c28
-rw-r--r--src/util/test_resolver_api.c76
-rw-r--r--src/util/test_resolver_api_data.conf1
-rw-r--r--src/util/test_scheduler.c13
-rw-r--r--src/util/test_scheduler_delay.c19
-rw-r--r--src/util/test_server.c2
-rw-r--r--src/util/test_server_disconnect.c1
-rw-r--r--src/util/test_server_mst_interrupt.c37
-rw-r--r--src/util/test_server_with_client.c28
-rw-r--r--src/util/test_server_with_client_unix.c30
-rw-r--r--src/util/test_service.c32
-rw-r--r--src/util/test_strings.c59
-rw-r--r--src/util/test_time.c16
-rw-r--r--src/util/time.c24
-rw-r--r--src/util/util.conf3
-rw-r--r--src/util/w32cat.c108
-rw-r--r--src/util/win.c (renamed from src/util/win.cc)2595
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, &section },
+ { '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