[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] r3024 - in GNUnet: . src/applications src/applications/stat
From: |
grothoff |
Subject: |
[GNUnet-SVN] r3024 - in GNUnet: . src/applications src/applications/state src/include src/util src/util/crypto src/util/disk src/util/getopt src/util/loggers src/util/network src/util/os src/util/string src/util/threads |
Date: |
Thu, 22 Jun 2006 10:51:11 -0700 (PDT) |
Author: grothoff
Date: 2006-06-22 10:50:56 -0700 (Thu, 22 Jun 2006)
New Revision: 3024
Added:
GNUnet/src/applications/state/
GNUnet/src/applications/state/Makefile.am
GNUnet/src/applications/state/state.c
GNUnet/src/applications/state/statetest.c
GNUnet/src/util/disk/
GNUnet/src/util/disk/Makefile.am
GNUnet/src/util/disk/storage.c
GNUnet/src/util/disk/storagetest.c
GNUnet/src/util/network/
GNUnet/src/util/network/Makefile.am
GNUnet/src/util/network/endian.c
GNUnet/src/util/network/io.c
GNUnet/src/util/network/ipcheck.c
GNUnet/src/util/network/port.c
GNUnet/src/util/network/tcp_return.c
GNUnet/src/util/network/tcpio.c
GNUnet/src/util/network/tcpiotest.c
GNUnet/src/util/os/
GNUnet/src/util/os/Makefile.am
GNUnet/src/util/os/daemon.c
GNUnet/src/util/os/daemontest.c
GNUnet/src/util/os/dso.c
GNUnet/src/util/os/osconfig.c
GNUnet/src/util/os/statuscalls.c
GNUnet/src/util/os/statuscallstest.c
GNUnet/src/util/threads/
GNUnet/src/util/threads/Makefile.am
GNUnet/src/util/threads/mutex.c
GNUnet/src/util/threads/pthread.c
GNUnet/src/util/threads/semaphore.c
GNUnet/src/util/threads/semaphoretest.c
GNUnet/src/util/threads/shutdown.c
GNUnet/src/util/threads/shutdowntest.c
GNUnet/src/util/threads/timertest.c
GNUnet/src/util/time.c
Removed:
GNUnet/src/util/cron.c
GNUnet/src/util/crontest.c
GNUnet/src/util/daemon.c
GNUnet/src/util/daemontest.c
GNUnet/src/util/dso.c
GNUnet/src/util/endian.c
GNUnet/src/util/io.c
GNUnet/src/util/ipcheck.c
GNUnet/src/util/osconfig.c
GNUnet/src/util/port.c
GNUnet/src/util/printhelp.c
GNUnet/src/util/semaphore.c
GNUnet/src/util/semaphoretest.c
GNUnet/src/util/shutdown.c
GNUnet/src/util/shutdowntest.c
GNUnet/src/util/state.c
GNUnet/src/util/statetest.c
GNUnet/src/util/statuscalls.c
GNUnet/src/util/statuscallstest.c
GNUnet/src/util/storage.c
GNUnet/src/util/storagetest.c
GNUnet/src/util/tcp_return.c
GNUnet/src/util/tcpio.c
GNUnet/src/util/tcpiotest.c
GNUnet/src/util/timer.c
GNUnet/src/util/timertest.c
Modified:
GNUnet/configure.ac
GNUnet/src/applications/Makefile.am
GNUnet/src/include/Makefile.am
GNUnet/src/include/gnunet_util.h
GNUnet/src/include/gnunet_util_crypto.h
GNUnet/src/include/gnunet_util_error.h
GNUnet/src/include/gnunet_util_error_loggers.h
GNUnet/src/util/Makefile.am
GNUnet/src/util/README
GNUnet/src/util/crypto/locking_gcrypt.c
GNUnet/src/util/getopt/Makefile
GNUnet/src/util/getopt/Makefile.in
GNUnet/src/util/getopt/getopt.c
GNUnet/src/util/getopt/printhelp.c
GNUnet/src/util/getopt/setoption.c
GNUnet/src/util/loggers/file.c
GNUnet/src/util/string/string.c
GNUnet/todo
Log:
Denver
Modified: GNUnet/configure.ac
===================================================================
--- GNUnet/configure.ac 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/configure.ac 2006-06-22 17:50:56 UTC (rev 3024)
@@ -539,6 +539,7 @@
src/applications/session/Makefile
src/applications/sqstore_mysql/Makefile
src/applications/sqstore_sqlite/Makefile
+src/applications/state/Makefile
src/applications/stats/Makefile
src/applications/tbench/Makefile
src/applications/testbed/Makefile
@@ -556,9 +557,16 @@
src/util/config/Makefile
src/util/config_impl/Makefile
src/util/containers/Makefile
+src/util/cron/Makefile
src/util/crypto/Makefile
+src/util/disk/Makefile
src/util/error/Makefile
+src/util/getopt/Makefile
src/util/loggers/Makefile
+src/util/network/Makefile
+src/util/os/Makefile
+src/util/string/Makefile
+src/util/threads/Makefile
src/util/win/Makefile
])
AC_OUTPUT
Modified: GNUnet/src/applications/Makefile.am
===================================================================
--- GNUnet/src/applications/Makefile.am 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/applications/Makefile.am 2006-06-22 17:50:56 UTC (rev 3024)
@@ -21,6 +21,7 @@
fragmentation \
getoption \
fs \
+ state \
stats \
gap \
identity \
Added: GNUnet/src/applications/state/Makefile.am
===================================================================
--- GNUnet/src/applications/state/Makefile.am 2006-06-22 17:39:19 UTC (rev
3023)
+++ GNUnet/src/applications/state/Makefile.am 2006-06-22 17:50:56 UTC (rev
3024)
@@ -0,0 +1,33 @@
+INCLUDES = -I$(top_srcdir)/src/include
+
+LDADD = \
+ $(top_builddir)/src/util/libgnunetutil.la
+
+plugindir = $(libdir)/GNUnet
+
+plugin_LTLIBRARIES = \
+ libgnunetmodule_state.la
+
+lib_LTLIBRARIES = \
+ libgnunetstate_api.la
+
+bin_PROGRAMS = \
+ gnunet-stats
+
+libgnunetmodule_state_la_SOURCES = \
+ state.c
+libgnunetmodule_state_la_LIBADD = \
+ $(top_builddir)/src/util/libgnunetutil.la
+libgnunetmodule_state_la_LDFLAGS = \
+ -export-dynamic -avoid-version -module
+
+check_PROGRAMS = \
+ statetest
+
+TESTS = $(check_PROGRAMS)
+
+statetest_SOURCES = \
+ statetest.c
+statetest_LDADD = \
+ $(top_builddir)/src/util/libgnunetutil.la
+
Added: GNUnet/src/applications/state/state.c
===================================================================
--- GNUnet/src/applications/state/state.c 2006-06-22 17:39:19 UTC (rev
3023)
+++ GNUnet/src/applications/state/state.c 2006-06-22 17:50:56 UTC (rev
3024)
@@ -0,0 +1,271 @@
+/*
+ This file is part of GNUnet.
+ (C) 2002, 2003, 2004, 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/disk/state.c
+ * @brief tiny, stateful database too keep track of internal state
+ *
+ * Directory based implementation of a tiny, stateful database
+ * to keep track of GNUnet _internal_ configuration parameters
+ * that users are not supposed to see (e.g. *previous* quota,
+ * previous database type for AFS, etc.)
+ *
+ *
+ * @author Christian Grothoff
+ */
+
+#include "gnunet_util_disk.h"
+#include "platform.h"
+
+#include <sys/stat.h>
+
+#define STATE_DEBUG NO
+
+#define DIR_EXT "state.sdb"
+
+static char * handle = NULL;
+
+/**
+ * Initialize the Directory module, expand filename
+ * @param dir the directory where content is configured to be stored (e.g.
~/.gnunet/data/content).
+ */
+static char * getDirectory(char * dir) {
+ char * result;
+ char * tmp;
+ size_t n;
+
+#if STATE_DEBUG
+ LOG(LOG_DEBUG,
+ "Database (state): %s\n",
+ dir);
+#endif
+ n = strlen(dir) + strlen(DIR_EXT) + 5;
+ tmp = MALLOC(n);
+ SNPRINTF(tmp, n, "%s/%s/", dir, DIR_EXT);
+ result = expandFileName(tmp);
+ FREE(tmp);
+ return result;
+}
+
+void initState() {
+ char * dbh;
+ char * dir;
+ char * base;
+ char * baseSect;
+
+ if (testConfigurationString("GNUNETD",
+ "_MAGIC_",
+ "YES")) {
+ base = "GNUNETD_HOME";
+ baseSect = "GNUNETD";
+ }
+ else {
+ base = "GNUNET_HOME";
+ baseSect = "GNUNET";
+ }
+ dir = getFileName(baseSect,
+ base,
+ _("Configuration file must specify a directory"
+ " for GNUnet to store per-peer data under %s\\%s.\n"));
+ dbh = getDirectory(dir);
+ FREE(dir);
+ GNUNET_ASSERT(dbh != NULL);
+ mkdirp(dbh);
+ handle = dbh;
+}
+
+/**
+ * Clean shutdown of the storage module (not used at the moment)
+ */
+void doneState() {
+ if (handle == NULL)
+ return; /* bogus call! */
+ FREE(handle);
+ handle = NULL;
+}
+
+/**
+ * Read the contents of a bucket to a buffer.
+ *
+ * @param name the hashcode representing the entry
+ * @param result the buffer to write the result to
+ * (*result should be NULL, sufficient space is allocated)
+ * @return the number of bytes read on success, -1 on failure
+ */
+int stateReadContent(const char * name,
+ void ** result) {
+ /* open file, must exist, open read only */
+ char * dbh = handle;
+ int fd;
+ int size;
+ char * fil;
+ unsigned long long fsize;
+ size_t n;
+
+ GNUNET_ASSERT(handle != NULL);
+ if (result == NULL)
+ return -1;
+ n = strlen(dbh) + strlen(name) + 2;
+ fil = MALLOC(n);
+ SNPRINTF(fil,
+ n,
+ "%s/%s",
+ dbh,
+ name);
+ if (OK != getFileSize(fil,
+ &fsize)) {
+ FREE(fil);
+ return -1;
+ }
+ fd = fileopen(fil,
+ O_RDONLY,
+ S_IRUSR);
+ if (fd == -1) {
+ FREE(fil);
+ return -1;
+ }
+ FREE(fil);
+ if (fsize == 0) { /* also invalid! */
+ closefile(fd);
+ return -1;
+ }
+
+ *result = xmalloc_unchecked_(fsize, __FILE__, __LINE__);
+ size = READ(fd,
+ *result,
+ fsize);
+ closefile(fd);
+ if (size == -1) {
+ FREE(*result);
+ *result = NULL;
+ }
+ return size;
+}
+
+
+/**
+ * Append content to file.
+ *
+ * @param name the key for the entry
+ * @param len the number of bytes in block
+ * @param block the data to store
+ * @return SYSERR on error, OK if ok.
+ */
+int stateAppendContent(const char * name,
+ int len,
+ const void * block) {
+ char * dbh = handle;
+ char * fil;
+ int fd;
+ size_t n;
+
+ GNUNET_ASSERT(handle != NULL);
+ n = strlen(dbh) + strlen(name) + 2;
+ fil = MALLOC(n);
+ SNPRINTF(fil,
+ n,
+ "%s/%s",
+ dbh,
+ name);
+ fd = fileopen(fil,
+ O_RDWR|O_CREAT,
+ S_IRUSR|S_IWUSR);
+ if (fd == -1) {
+ LOG_FILE_STRERROR(LOG_WARNING, "open", fil);
+ FREE(fil);
+ return SYSERR; /* failed! */
+ }
+ FREE(fil);
+ lseek(fd,
+ 0,
+ SEEK_END);
+ WRITE(fd,
+ block,
+ len);
+ closefile(fd);
+ return OK;
+}
+
+/**
+ * Write content to a file.
+ *
+ * @param name the key for the entry
+ * @param len the number of bytes in block
+ * @param block the data to store
+ * @return SYSERR on error, OK if ok.
+ */
+int stateWriteContent(const char * name,
+ int len,
+ const void * block) {
+ char * dbh = handle;
+ char * fil;
+ int fd;
+ size_t n;
+
+ GNUNET_ASSERT(handle != NULL);
+ n = strlen(dbh) + strlen(name) + 2;
+ fil = MALLOC(n);
+ SNPRINTF(fil,
+ n,
+ "%s/%s",
+ dbh,
+ name);
+ fd = fileopen(fil,
+ O_RDWR|O_CREAT,
+ S_IRUSR|S_IWUSR);
+ if (fd == -1) {
+ LOG_FILE_STRERROR(LOG_WARNING, "open", fil);
+ FREE(fil);
+ return SYSERR; /* failed! */
+ }
+ WRITE(fd,
+ block,
+ len);
+ if (0 != ftruncate(fd, len))
+ LOG_FILE_STRERROR(LOG_WARNING, "ftruncate", fil);
+ closefile(fd);
+ FREE(fil);
+ return OK;
+}
+
+/**
+ * Free space in the database by removing one file
+ * @param name the hashcode representing the name of the file
+ * (without directory)
+ */
+int stateUnlinkFromDB(const char * name) {
+ char * dbh = handle;
+ char * fil;
+ size_t n;
+
+ GNUNET_ASSERT(handle != NULL);
+ n = strlen(dbh) + strlen(name) + 2;
+ fil = MALLOC(n);
+ SNPRINTF(fil,
+ n,
+ "%s/%s",
+ dbh,
+ name);
+ UNLINK(fil);
+ FREE(fil);
+ return OK;
+}
+
+/* end of state.c */
Added: GNUnet/src/applications/state/statetest.c
===================================================================
--- GNUnet/src/applications/state/statetest.c 2006-06-22 17:39:19 UTC (rev
3023)
+++ GNUnet/src/applications/state/statetest.c 2006-06-22 17:50:56 UTC (rev
3024)
@@ -0,0 +1,81 @@
+/**
+ * @file test/storagetest.c
+ * @brief testcase for the state module
+ * @author Christian Grothoff
+ */
+
+#include "gnunet_util.h"
+#include "platform.h"
+
+/**
+ * Perform option parsing from the command line.
+ */
+static int parseCommandLine(int argc,
+ char * argv[]) {
+ char c;
+
+ while (1) {
+ int option_index = 0;
+ static struct GNoption long_options[] = {
+ { "config", 1, 0, 'c' },
+ { 0,0,0,0 }
+ };
+
+ c = GNgetopt_long(argc,
+ argv,
+ "c:",
+ long_options,
+ &option_index);
+
+ if (c == -1)
+ break; /* No more flags to process */
+
+ switch(c) {
+ case 'c':
+ FREENONNULL(setConfigurationString("FILES",
+ "gnunet.conf",
+ GNoptarg));
+ break;
+ } /* end of parsing commandline */
+ }
+ FREENONNULL(setConfigurationString("GNUNETD",
+ "LOGLEVEL",
+ "NOTHING"));
+ return OK;
+}
+
+#define TH "TestHandle"
+
+int testState() {
+ char * testString = "Hello World";
+ char * ret;
+
+ stateUnlinkFromDB(TH); /* go to defined state */
+ if (SYSERR == stateWriteContent(TH,
+ 5,
+ testString))
+ return 1;
+ if (SYSERR == stateAppendContent(TH,
+ 6,
+ &testString[5]))
+ return 2;
+ ret = NULL;
+ if (SYSERR == stateReadContent(TH,
+ (void**)&ret))
+ return 3;
+ if (0 != strncmp(ret, testString, 11))
+ return 4;
+ FREE(ret);
+ if (OK != stateUnlinkFromDB(TH))
+ return 5;
+ return 0;
+}
+
+int main(int argc, char * argv[]) {
+ int ret = 0;
+ initUtil(argc, argv, &parseCommandLine);
+ ret = testState();
+
+ doneUtil();
+ return ret;
+} /* end of main */
Modified: GNUnet/src/include/Makefile.am
===================================================================
--- GNUnet/src/include/Makefile.am 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/include/Makefile.am 2006-06-22 17:50:56 UTC (rev 3024)
@@ -44,7 +44,13 @@
gnunet_util_config.h \
gnunet_util_config_impl.h \
gnunet_util_containers.h \
+ gnunet_util_cron.h \
gnunet_util_crypto.h \
+ gnunet_util_disk.h \
gnunet_util_error.h \
- gnunet_util_error.h \
gnunet_util_error_loggers.h
+ gnunet_util_getopt.h \
+ gnunet_util_network.h \
+ gnunet_util_os.h \
+ gnunet_util_string.h \
+ gnunet_util_threads.h
Modified: GNUnet/src/include/gnunet_util.h
===================================================================
--- GNUnet/src/include/gnunet_util.h 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/include/gnunet_util.h 2006-06-22 17:50:56 UTC (rev 3024)
@@ -56,8 +56,15 @@
unconditionally available... */
#include <stdlib.h>
-/* add error and config prototypes */
+/* add prototypes of sublibraries */
+#include "gnunet_util_error.h"
#include "gnunet_util_config.h"
+#include "gnunet_util_string.h"
+#include "gnunet_util_disk.h"
+#include "gnunet_util_threads.h"
+#include "gnunet_util_getopt.h"
+#include "gnunet_util_network.h"
+#include "gnunet_util_os.h"
#ifdef __cplusplus
extern "C" {
@@ -67,12 +74,18 @@
#endif
-/* **************** constants ****************** */
+#define DEFAULT_CLIENT_CONFIG_FILE "~/.gnunet/gnunet.conf"
+#define DEFAULT_DAEMON_DIR "/etc"
+#define DEFAULT_DAEMON_CONFIG_FILE DEFAULT_DAEMON_DIR"/gnunetd.conf"
+#define VAR_DIRECTORY "/var/lib"
+#define VAR_DAEMON_DIRECTORY VAR_DIRECTORY"/gnunet"
+#define VAR_DAEMON_CONFIG_FILE VAR_DAEMON_DIRECTORY"/gnunetd.conf"
+#define GNUNET_HOME_DIRECTORY "~/.gnunet"
+#define HOME_DAEMON_CONFIG_FILE GNUNET_HOME_DIRECTORY"/gnunetd.conf"
-/* do not turn this on unless you know what you
- are doing, you'll get a ton of output... */
-#define DEBUG_LOCKING 0
+/* **************** constants ****************** */
+
/**
* Just the version number of GNUnet-util implementation.
* Encoded as
@@ -87,743 +100,18 @@
*/
#define GNUNET_UTIL_VERSION 0x00070004
-/**
- * We use an unsigned short in the protocol header, thus:
- */
-#define MAX_BUFFER_SIZE 65536
+/* CHRISTIAN: move this to gnunet_core.h or _protocols.h ? */
/**
* Highest legal priority or trust value
*/
#define MAX_PRIO 0x7FFFFFFF
-/**
- * Named constants for return values. The following
- * invariants hold: "NO == 0" (to allow "if (NO)")
- * "OK != SYSERR", "OK != NO", "NO != SYSERR"
- * and finally "YES != NO".
- */
-#define OK 1
-#define SYSERR -1
-#define YES 1
-#define NO 0
-#define STRONG YES
-#define WEAK NO
+/* NILS: I would love to see the
+ next two methods in PLIBC */
/**
- * @brief constants to specify time
- */
-#define cronMILLIS ((cron_t)1)
-#define cronSECONDS ((cron_t)(1000 * cronMILLIS))
-#define cronMINUTES ((cron_t) (60 * cronSECONDS))
-#define cronHOURS ((cron_t)(60 * cronMINUTES))
-#define cronDAYS ((cron_t)(24 * cronHOURS))
-#define cronWEEKS ((cron_t)(7 * cronDAYS))
-#define cronMONTHS ((cron_t)(30 * cronDAYS))
-#define cronYEARS ((cron_t)(365 * cronDAYS))
-
-/**
- * @brief Default names of the configuration files.
- */
-#define DEFAULT_CLIENT_CONFIG_FILE "~/.gnunet/gnunet.conf"
-#define DEFAULT_DAEMON_DIR "/etc"
-#define DEFAULT_DAEMON_CONFIG_FILE "/etc/gnunetd.conf"
-#define VAR_DIRECTORY "/var/lib"
-#define VAR_DAEMON_DIRECTORY "/var/lib/GNUnet"
-#define VAR_DAEMON_CONFIG_FILE "/var/lib/GNUnet/gnunetd.conf"
-#define HOME_DAEMON_CONFIG_FILE "~/.gnunet/gnunetd.conf"
-#define GNUNET_HOME_DIRECTORY "~/.gnunet/"
-
-#define HELP_HELP \
- { 'h', "help", NULL, \
- gettext_noop("print this help") }
-#define HELP_LOGLEVEL \
- { 'L', "loglevel", "LEVEL", \
- gettext_noop("set verbosity to LEVEL") }
-#define HELP_CONFIG \
- { 'c', "config", "FILENAME", \
- gettext_noop("use configuration file FILENAME") }
-#define HELP_HOSTNAME \
- { 'H', "host", "HOSTNAME", \
- gettext_noop("specify host on which gnunetd is running") }
-#define HELP_VERSION \
- { 'v', "version", NULL, \
- gettext_noop("print the version number") }
-#define HELP_VERBOSE \
- { 'V', "verbose", NULL, \
- gettext_noop("be verbose") }
-#define HELP_END \
- { 0, NULL, NULL, NULL, }
-
-/**
- * Default "long" version of the options, use
- * "vhdc:L:H:" in the short option argument
- * to getopt_long for now.
- */
-#define LONG_DEFAULT_OPTIONS \
- { "config", 1, 0, 'c' }, \
- { "version", 0, 0, 'v' }, \
- { "help", 0, 0, 'h' }, \
- { "debug", 0, 0, 'd' }, \
- { "loglevel", 1, 0, 'L' }, \
- { "host", 1, 0, 'H' }
-
-/* **************** structs ****************** */
-
-/**
- * @brief 512-bit hashcode
- */
-typedef struct {
- unsigned int bits[512 / 8 / sizeof(unsigned int)]; /* = 16 */
-} HashCode512;
-
-/**
- * Header for all Client-Server communications.
- */
-typedef struct {
- /**
- * The length of the struct (in bytes, including the length field itself)
- */
- unsigned short size;
-
- /**
- * The type of the message (XX_CS_PROTO_XXXX)
- */
- unsigned short type;
-
-} CS_MESSAGE_HEADER;
-
-/**
- * CS communication: simple return value
- */
-typedef struct {
- /**
- * The CS header (values: sizeof(CS_returnvalue_MESSAGE),
CS_PROTO_RETURN_VALUE)
- */
- CS_MESSAGE_HEADER header;
-
- /**
- * The return value (network byte order)
- */
- int return_value;
-} CS_returnvalue_MESSAGE;
-
-/**
- * p2p message part header
- */
-typedef struct {
- /**
- * size of this MESSAGE_PART (network byte order)
- */
- unsigned short size;
-
- /**
- * type of the request, XX_p2p_PROTO_XXX (network byte order)
- */
- unsigned short type;
-} P2P_MESSAGE_HEADER;
-
-typedef void (*NotifyConfigurationUpdateCallback)(void);
-
-/**
- * Type of a cron-job method.
- */
-typedef void (*CronJob)(void *);
-
-/**
- * Time for absolute times used by cron (64 bit)
- */
-typedef unsigned long long cron_t;
-
-/**
- * 32-bit timer value.
- */
-typedef unsigned int TIME_T;
-
-/* Describe the long-named options requested by the application.
- The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
- of `struct GNoption' terminated by an element containing a name which is
- zero.
-
- The field `has_arg' is:
- no_argument (or 0) if the option does not take an argument,
- required_argument (or 1) if the option requires an argument,
- optional_argument (or 2) if the option takes an optional argument.
-
- If the field `flag' is not NULL, it points to a variable that is set
- to the value given in the field `val' when the option is found, but
- left unchanged if the option is not found.
-
- To have a long-named option do something other than set an `int' to
- a compiled-in constant, such as set a value from `GNoptarg', set the
- option's `flag' field to zero and its `val' field to a nonzero
- value (the equivalent single-letter option character, if there is
- one). For long options that have a zero `flag' field, `getopt'
- returns the contents of the `val' field. */
-
-struct GNoption {
- const char *name;
- /* has_arg can't be an enum because some compilers complain about
- type mismatches in all the code that assumes it is an int. */
- int has_arg;
- int *flag;
- int val;
-};
-
-/**
- * @brief an IPv4 address
- */
-typedef struct {
- unsigned int addr; /* struct in_addr */
-} IPaddr;
-
-/**
- * @brief IPV4 network in CIDR notation.
- */
-struct CIDRNetwork;
-
-/**
- * @brief an IPV6 address.
- */
-typedef struct {
- unsigned int addr[4]; /* struct in6_addr addr; */
-} IP6addr;
-
-/**
- * @brief IPV6 network in CIDR notation.
- */
-struct CIDR6Network;
-
-/**
- * Main method of a thread.
- */
-typedef void * (*PThreadMain)(void*);
-
-/**
- * Encapsulation of a pthread handle.
- */
-typedef struct PTHREAD_T {
- void * internal;
-} PTHREAD_T;
-
-/**
- * The identity of the host (basically the SHA-512 hashcode of
- * it's public key).
- */
-typedef struct {
- HashCode512 hashPubKey;
-} PeerIdentity;
-
-/**
- * @brief Structure for MUTual EXclusion (Mutex).
- *
- * Essentially a wrapper around pthread_mutex_t.
- */
-typedef struct Mutex {
- void * internal;
-} Mutex;
-
-/**
- * @brief Semaphore abstraction implemented with pthreads
- */
-typedef struct Semaphore {
- int v;
- Mutex mutex;
- /**
- * Wrapper for pthread condition variable.
- */
- void * cond;
-} Semaphore;
-
-/**
- * @brief Inter-process semaphore.
- */
-typedef struct IPC_Semaphore{
- void * platform;
-} IPC_Semaphore;
-
-/**
- * Struct to refer to a GNUnet TCP connection.
- * This is more than just a socket because if the server
- * drops the connection, the client automatically tries
- * to reconnect (and for that needs connection information).
- */
-typedef struct GNUNET_TCP_SOCKET {
-
- /**
- * the socket handle, -1 if invalid / not life
- */
- int socket;
-
- /**
- * the following is the IP for the remote host for client-sockets,
- * as returned by gethostbyname("hostname"); server sockets should
- * use 0.
- */
- IPaddr ip;
-
- /**
- * the port number, in host byte order
- */
- unsigned short port;
-
- /**
- * Write buffer length for non-blocking writes.
- */
- unsigned int outBufLen;
-
- /**
- * Write buffer for non-blocking writes.
- */
- void * outBufPending;
-
- Mutex readlock;
- Mutex writelock;
-
-} GNUNET_TCP_SOCKET;
-
-/**
- * Method to parse the command line. The results
- * are to be stored in the configuration module.
- * @param argc the number of arguments
- * @param argv the command line arguments
- * @return OK on success, SYSERR if we should abort the
- * initialization sequence and exit the program
- */
-typedef int (*CommandLineParser)(int argc, char * argv[]);
-
-/**
- * Function called on each file in a directory.
- * @return OK to continue to iterate,
- * SYSERR to abort iteration with error!
- */
-typedef int (*DirectoryEntryCallback)(const char * filename,
- const char * dirName,
- void * data);
-
-/**
- * @brief description of a command line option (helptext)
- */
-typedef struct {
- char shortArg;
- char * longArg;
- char * mandatoryArg;
- char * description;
-} Help;
-
-
-/* **************** Functions and Macros ************* */
-
-/**
- * Convert a long-long to host-byte-order.
- * @param n the value in network byte order
- * @return the same value in host byte order
- */
-unsigned long long ntohll(unsigned long long n);
-
-/**
- * Convert a long long to network-byte-order.
- * @param n the value in host byte order
- * @return the same value in network byte order
- */
-unsigned long long htonll(unsigned long long n);
-
-/**
- * Convert the len characters long character sequence
- * given in input that is in the given charset
- * to UTF-8.
- * @return the converted string (0-terminated)
- */
-char * convertToUtf8(const char * input,
- size_t len,
- const char * charset);
-
-/**
- * Expand an expression of the form
- * "$FOO/BAR" to "DIRECTORY/BAR" where
- * either in the current section or
- * globally FOO is set to DIRECTORY.
- */
-char * expandDollar(const char * section,
- char * orig);
-
-/**
- * Start the cron jobs.
- */
-void startCron(void);
-
-/**
- * Stop the cron service.
- */
-void stopCron(void);
-
-/**
- * Stop running cron-jobs for a short time. This method may only be
- * called by a thread that is not holding any locks. It will cause
- * a deadlock if this method is called from within a cron-job.
- * Use with caution.
- */
-void suspendCron(void);
-
-/**
- * Resume running cron-jobs.
- */
-void resumeCron(void);
-
-/**
- * Is the cron-thread currently running?
- */
-int isCronRunning(void);
-
-/**
- * Like suspendCron, but does nothing if called from
- * within a cron-job.
- */
-void suspendIfNotCron(void);
-
-/**
- * Like resumeCron, but does nothing if called from
- * within a cron-job.
- */
-void resumeIfNotCron(void);
-
-/**
- * Get the current time (works just as "time", just
- * that we use the unit of time that the cron-jobs use).
- * @param setme will set the current time if non-null
- * @return the current time
- */
-cron_t cronTime(cron_t * setme);
-
-/**
- * Add a cron-job to the delta list.
- * @param method which method should we run
- * @param delta how many milliseconds until we run the method
- * @param deltaRepeat if this is a periodic, the time between
- * the runs, otherwise 0.
- * @param data argument to pass to the method
- */
-void addCronJob(CronJob method,
- unsigned int delta,
- unsigned int deltaRepeat,
- void * data);
-
-/**
- * If the specified cron-job exists in th delta-list, move it to the
- * head of the list. If it is running, do nothing. If it is does not
- * exist and is not running, add it to the list to run it next.
- *
- * @param method which method should we run
- * @param deltaRepeat if this is a periodic, the time between
- * the runs, otherwise 0.
- * @param data extra argument to calls to method, freed if
- * non-null and cron is shutdown before the job is
- * run and/or delCronJob is called
- */
-void advanceCronJob(CronJob method,
- unsigned int deltaRepeat,
- void * data);
-/**
- * Remove all matching cron-jobs from the list. This method should
- * only be called while cron is suspended or stopped, or from a cron
- * job that deletes another cron job. If cron is not suspended or
- * stopped, it may be running the method that is to be deleted, which
- * could be bad (in this case, the deletion will not affect the
- * running job and may return before the running job has terminated).
- *
- * @param method which method is listed?
- * @param repeat which repeat factor was chosen?
- * @param data what was the data given to the method
- * @return the number of jobs removed
- */
-int delCronJob(CronJob method,
- unsigned int repeat,
- void * data);
-
-/**
- * Sleep for the specified time interval.
- * A signal interrupts the sleep. Caller
- * is responsible to check that the sleep was
- * long enough.
- *
- * @return 0 if there was no interrupt, 1 if there was, -1 on error.
- */
-int gnunet_util_sleep(cron_t delay);
-
-/**
- * Load dynamic library
- */
-void * loadDynamicLibrary(const char * libprefix,
- const char * dsoname);
-
-void * bindDynamicMethod(void * libhandle,
- const char * methodprefix,
- const char * dsoname);
-
-void * trybindDynamicMethod(void * libhandle,
- const char * methodprefix,
- const char * dsoname);
-
-void unloadDynamicLibrary(void * libhandle);
-
-/* For communication from `getopt' to the caller.
- When `getopt' finds an option that takes an argument,
- the argument value is returned here.
- Also, when `ordering' is RETURN_IN_ORDER,
- each non-option ARGV-element is returned here. */
-
-extern char *GNoptarg;
-
-/* Index in ARGV of the next element to be scanned.
- This is used for communication to and from the caller
- and for communication between successive calls to `getopt'.
-
- On entry to `getopt', zero means this is the first call; initialize.
-
- When `getopt' returns -1, this is the index of the first of the
- non-option elements that the caller should itself scan.
-
- Otherwise, `GNoptind' communicates from one call to the next
- how much of ARGV has been scanned so far. */
-
-extern int GNoptind;
-
-/* Callers store zero here to inhibit the error message `getopt' prints
- for unrecognized options. */
-
-extern int GNopterr;
-
-/* Set to an option character which was unrecognized. */
-
-extern int GNoptopt;
-
-
-int GNgetopt_long (int argc,
- char *const *argv,
- const char *shortopts,
- const struct GNoption *longopts,
- int *longind);
-
-
-/**
- * Parse a network specification. The argument specifies
- * a list of networks. The format is
- * <tt>[network/netmask;]*</tt> (no whitespace, must be terminated
- * with a semicolon). The network must be given in dotted-decimal
- * notation. The netmask can be given in CIDR notation (/16) or
- * in dotted-decimal (/255.255.0.0).
- * <p>
- * @param routeList a string specifying the forbidden networks
- * @return the converted list, NULL if the synatx is flawed
- */
-struct CIDRNetwork * parseRoutes(const char * routeList);
-
-
-/**
- * Check if the given IP address is in the list of
- * IP addresses.
- * @param list a list of networks
- * @param ip the IP to check (in network byte order)
- * @return NO if the IP is not in the list, YES if it it is
- */
-int checkIPListed(const struct CIDRNetwork * list,
- IPaddr ip);
-
-/**
- * Check if the given IP address is in the list of
- * IP addresses.
- * @param list a list of networks
- * @param ip the IP to check (in network byte order)
- * @return NO if the IP is not in the list, YES if it it is
- */
-int checkIP6Listed(const struct CIDR6Network * list,
- const IP6addr * ip);
-
-/**
- * Parse a network specification. The argument specifies
- * a list of networks. The format is
- * <tt>[network/netmask;]*</tt> (no whitespace, must be terminated
- * with a semicolon). The network must be given in dotted-decimal
- * notation. The netmask can be given in CIDR notation (/16) or
- * in dotted-decimal (/255.255.0.0).
- * <p>
- * @param routeList a string specifying the forbidden networks
- * @return the converted list, NULL if the synatx is flawed
- */
-struct CIDR6Network * parseRoutes6(const char * routeList);
-
-#define PRIP(ip) (unsigned int)(((unsigned int)(ip))>>24), (unsigned
int)((((unsigned)(ip)))>>16 & 255), (unsigned int)((((unsigned int)(ip)))>>8 &
255), (unsigned int)((((unsigned int)(ip))) & 255)
-
-/**
- * Allocate memory. Checks the return value, aborts if no more
- * memory is available. Don't use xmalloc_ directly. Use the
- * MALLOC macro.
- */
-void * xmalloc_(size_t size,
- const char * filename,
- const int linenumber);
-
-/**
- * Allocate memory. This function does not check if the
- * allocation request is within reasonable bounds, allowing
- * allocations larger than 40 MB. If you don't expect the
- * possibility of very large allocations, use MALLOC instead.
- */
-void * xmalloc_unchecked_(size_t size,
- const char * filename,
- const int linenumber);
-
-/**
- * Wrapper around malloc. Allocates size bytes of memory.
- * @param size the number of bytes to allocate
- * @return pointer to size bytes of memory
- */
-#define MALLOC(size) xmalloc_(size, __FILE__,__LINE__)
-
-/**
- * Reallocate memory. Checks the return value, aborts if no more
- * memory is available.
- */
-void * xrealloc_(void * ptr,
- const size_t n,
- const char * filename,
- const int linenumber);
-
-/**
- * Wrapper around realloc. Rellocates size bytes of memory.
- * @param ptr the pointer to reallocate
- * @param size the number of bytes to reallocate
- * @return pointer to size bytes of memory
- */
-#define REALLOC(ptr, size) xrealloc_(ptr, size, __FILE__,__LINE__)
-
-/**
- * Free memory. Merely a wrapper for the case that we
- * want to keep track of allocations. Don't use xfree_
- * directly. Use the FREE macro.
- */
-void xfree_(void * ptr,
- const char * filename,
- const int linenumber);
-
-/**
- * Wrapper around free. Frees the memory referred to by ptr.
- * Note that is is generally better to free memory that was
- * allocated with GROW using GROW(mem, size, 0) instead of FREE.
- *
- * @param ptr location where to free the memory. ptr must have
- * been returned by STRDUP, MALLOC or GROW earlier.
- */
-#define FREE(ptr) xfree_(ptr, __FILE__, __LINE__)
-
-/**
- * Free the memory pointed to by ptr if ptr is not NULL.
- * Equivalent to if (ptr!=null)FREE(ptr).
- * @param ptr the location in memory to free
- */
-#define FREENONNULL(ptr) do { void * __x__ = ptr; if (__x__ != NULL) {
FREE(__x__); } } while(0)
-
-/**
- * Dup a string. Don't call xstrdup_ directly. Use the STRDUP macro.
- */
-char * xstrdup_(const char * str,
- const char * filename,
- const int linenumber);
-
-/**
- * Wrapper around STRDUP. Makes a copy of the zero-terminated string
- * pointed to by a.
- * @param a pointer to a zero-terminated string
- * @return a copy of the string including zero-termination
- */
-#define STRDUP(a) xstrdup_(a,__FILE__,__LINE__)
-
-/**
- * Dup a string. Don't call xstrdup_ directly. Use the STRDUP macro.
- *
- * @param str the string to dup
- * @param n the maximum number of characters to copy (+1 for 0-termination)
- * @param filename where in the code was the call to GROW
- * @param linenumber where in the code was the call to GROW
- * @return strdup(str)
- */
-char * xstrndup_(const char * str,
- const size_t n,
- const char * filename,
- const int linenumber);
-
-/**
- * Wrapper around STRNDUP. Makes a copy of the zero-terminated string
- * pointed to by a.
- * @param a pointer to a zero-terminated string
- * @param n the maximum number of characters to copy (+1 for 0-termination)
- * @return a copy of the string including zero-termination
- */
-#define STRNDUP(a,n) xstrndup_(a,n,__FILE__,__LINE__)
-
-/**
- * Grow an array, the new elements are zeroed out.
- * Grows old by (*oldCount-newCount)*elementSize
- * bytes and sets *oldCount to newCount.
- *
- * Don't call xgrow_ directly. Use the GROW macro.
- *
- * @param old address of the pointer to the array
- * *old may be NULL
- * @param elementSize the size of the elements of the array
- * @param oldCount address of the number of elements in the *old array
- * @param newCount number of elements in the new array, may be 0 (then *old
will be NULL afterwards)
- */
-void xgrow_(void ** old,
- size_t elementSize,
- unsigned int * oldCount,
- unsigned int newCount,
- const char * filename,
- const int linenumber);
-
-/**
- * Grow a well-typed (!) array. This is a convenience
- * method to grow a vector <tt>arr</tt> of size <tt>size</tt>
- * to the new (target) size <tt>tsize</tt>.
- * <p>
- *
- * Example (simple, well-typed stack):
- *
- * <pre>
- * static struct foo * myVector = NULL;
- * static int myVecLen = 0;
- *
- * static void push(struct foo * elem) {
- * GROW(myVector, myVecLen, myVecLen+1);
- * memcpy(&myVector[myVecLen-1], elem, sizeof(struct foo));
- * }
- *
- * static void pop(struct foo * elem) {
- * if (myVecLen == 0) die();
- * memcpy(elem, myVector[myVecLen-1], sizeof(struct foo));
- * GROW(myVector, myVecLen, myVecLen-1);
- * }
- * </pre>
- *
- * @param arr base-pointer of the vector, may be NULL if size is 0;
- * will be updated to reflect the new address. The TYPE of
- * arr is important since size is the number of elements and
- * not the size in bytes
- * @param size the number of elements in the existing vector (number
- * of elements to copy over)
- * @param tsize the target size for the resulting vector, use 0 to
- * free the vector (then, arr will be NULL afterwards).
- */
-#define GROW(arr,size,tsize) xgrow_((void**)&arr, sizeof(arr[0]), &size,
tsize, __FILE__, __LINE__)
-
-/**
- * Append an element to a list (growing the
- * list by one).
- */
-#define APPEND(arr,size,element) GROW(arr,size,size+1); arr[size-1] = (element)
-
-/**
* TIME prototype. "man time".
*/
TIME_T TIME(TIME_T * t);
@@ -835,171 +123,17 @@
*/
char * GN_CTIME(const TIME_T * t);
-/**
- * Get the IP address of the given host.
- * @return OK on success, SYSERR on error
- */
-int GN_getHostByName(const char * hostname,
- IPaddr * ip);
+/** NILS: the next one should be removed from gnunetutil --
+ we should not have anything win32 specific in here! */
/**
- * Give relative time in human-readable fancy format.
+ * @brief Format a Windows specific error code
*/
-char * timeIntervalToFancyString(cron_t delta);
+char *winErrorStr(const char *prefix,
+ int dwErr);
-/**
- * Convert a given filesize into a fancy human-readable format.
- */
-char * fileSizeToFancyString(unsigned long long size);
-#define SEMAPHORE_NEW(value) semaphore_new_(value, __FILE__, __LINE__)
-#define SEMAPHORE_FREE(s) semaphore_free_(s, __FILE__, __LINE__)
-#define SEMAPHORE_DOWN(s) semaphore_down_(s, __FILE__, __LINE__)
-#define SEMAPHORE_DOWN_NONBLOCKING(s) semaphore_down_nonblocking_(s, __FILE__,
__LINE__)
-#define SEMAPHORE_UP(s) semaphore_up_(s, __FILE__, __LINE__)
-
-#if DEBUG_LOCKING
-#define MUTEX_CREATE(a) do { \
- fprintf(stderr, \
- "Creating mutex %x at line %d in file %s\n", \
- (int) a, __LINE__, __FILE__); \
- create_mutex_(a); \
-}\
-while(0)
-#define MUTEX_CREATE_RECURSIVE(a) do { \
- fprintf(stderr, \
- "Creating recursive mutex %x at line %d in file %s\n", \
- (int) a, __LINE__, __FILE__); \
- create_recursive_mutex_(a); \
-}\
-while(0)
-#define MUTEX_DESTROY(a) do { \
- fprintf(stderr, \
- "Destroying mutex %x at line %d in file %s\n", \
- (int) a, __LINE__, __FILE__); \
- destroy_mutex_(a); \
-}\
-while(0)
-#define MUTEX_LOCK(a) do { \
- fprintf(stderr, \
- "Aquireing lock %x at %s:%d\n", \
- (int)a, __FILE__, __LINE__); \
- mutex_lock_(a, __FILE__, __LINE__); \
-}\
-while (0)
-#define MUTEX_UNLOCK(a) do { \
- fprintf(stderr, \
- "Releasing lock %x at %s:%d\n", \
- (int)a, __FILE__, __LINE__); \
- mutex_unlock_(a, __FILE__, __LINE__); \
-}\
-while (0)
-#else
-#define MUTEX_LOCK(a) mutex_lock_(a, __FILE__, __LINE__)
-#define MUTEX_UNLOCK(a) mutex_unlock_(a, __FILE__, __LINE__)
-#define MUTEX_CREATE(a) create_mutex_(a)
-#define MUTEX_CREATE_RECURSIVE(a) create_recursive_mutex_(a)
-#define MUTEX_DESTROY(a) destroy_mutex_(a)
-#endif
-
/**
- * Returns YES if pt is the handle for THIS thread.
- */
-int PTHREAD_SELF_TEST(PTHREAD_T * pt);
-
-/**
- * Get the handle for THIS thread.
- */
-void PTHREAD_GET_SELF(PTHREAD_T * pt);
-
-/**
- * Release handle for a thread (should have been
- * obtained using PTHREAD_GET_SELF).
- */
-void PTHREAD_REL_SELF(PTHREAD_T * pt);
-
-/**
- * Create a thread. Use this method instead of pthread_create since
- * BSD may only give a 1k stack otherwise.
- *
- * @param handle handle to the pthread (for detaching, join)
- * @param main the main method of the thread
- * @param arg the argument to main
- * @param stackSize the size of the stack of the thread in bytes.
- * Note that if the stack overflows, some OSes (seen under BSD)
- * will just segfault and gdb will give a messed-up stacktrace.
- * @return see pthread_create
- */
-int PTHREAD_CREATE(PTHREAD_T * handle,
- PThreadMain main,
- void * arg,
- size_t stackSize);
-
-void PTHREAD_JOIN(PTHREAD_T * handle,
- void ** ret);
-
-void PTHREAD_KILL(PTHREAD_T * handle,
- int signal);
-
-void PTHREAD_DETACH(PTHREAD_T * handle);
-
-#define IPC_SEMAPHORE_NEW(name,value) ipc_semaphore_new_(name, value,
__FILE__, __LINE__)
-#define IPC_SEMAPHORE_FREE(s) ipc_semaphore_free_(s, __FILE__, __LINE__)
-#define IPC_SEMAPHORE_DOWN(s) ipc_semaphore_down_(s, __FILE__, __LINE__)
-#define IPC_SEMAPHORE_UP(s) ipc_semaphore_up_(s, __FILE__, __LINE__)
-
-IPC_Semaphore * ipc_semaphore_new_(const char * basename,
- const unsigned int initialValue,
- const char * filename,
- const int linenumber);
-
-void ipc_semaphore_up_(IPC_Semaphore * sem,
- const char * filename,
- const int linenumber);
-
-void ipc_semaphore_down_(IPC_Semaphore * sem,
- const char * filename,
- const int linenumber);
-
-
-void ipc_semaphore_free_(IPC_Semaphore * sem,
- const char * filename,
- const int linenumber);
-
-/**
- * While we must define these globally to make the
- * compiler happy, always use the macros in the sources
- * instead!
- */
-void create_mutex_(Mutex * mutex);
-void create_recursive_mutex_(Mutex * mutex);
-void create_fast_mutex_(Mutex * mutex);
-void destroy_mutex_(Mutex * mutex);
-void mutex_lock_(Mutex * mutex,
- const char * filename,
- const int linenumber);
-void mutex_unlock_(Mutex * mutex,
- const char * filename,
- const int linenumber);
-Semaphore * semaphore_new_(int value,
- const char * filename,
- const int linenumber);
-void semaphore_free_(Semaphore * s,
- const char * filename,
- const int linenumber);
-int semaphore_down_(Semaphore * s,
- const char * filename,
- const int linenumber);
-int semaphore_down_nonblocking_(Semaphore * s,
- const char * filename,
- const int linenumber);
-int semaphore_up_(Semaphore * s,
- const char * filename,
- const int linenumber);
-
-
-
-/**
* Initialize the util module.
* @param argc the number of arguments
* @param argv the command line arguments
@@ -1023,609 +157,6 @@
*/
void doneUtil(void);
-/**
- * Configuration: get the GNUnet port for the client to
- * connect to (via TCP).
- */
-unsigned short getGNUnetPort(void);
-
-/**
- * Get a GNUnet TCP socket that is connected to gnunetd.
- */
-GNUNET_TCP_SOCKET * getClientSocket(void);
-
-/**
- * Free a Client socket.
- */
-void releaseClientSocket(GNUNET_TCP_SOCKET * sock);
-
-/**
- * Read the contents of a bucket to a buffer.
- *
- * @param fn the hashcode representing the entry
- * @param result the buffer to write the result to
- * (*result should be NULL, sufficient space is allocated)
- * @return the number of bytes read on success, -1 on failure
- */
-int stateReadContent(const char * name,
- void ** result);
-
-/**
- * Append content to file.
- *
- * @param fn the key for the entry
- * @param len the number of bytes in block
- * @param block the data to store
- * @return SYSERR on error, OK if ok.
- */
-int stateAppendContent(const char * name,
- int len,
- const void * block);
-
-/**
- * Write content to a file.
- *
- * @param fn the key for the entry
- * @param len the number of bytes in block
- * @param block the data to store
- * @return SYSERR on error, OK if ok.
- */
-int stateWriteContent(const char * name,
- int len,
- const void * block);
-
-/**
- * Free space in the database by removing one file
- * @param name the hashcode representing the name of the file
- * (without directory)
- */
-int stateUnlinkFromDB(const char * name);
-
-/**
- * Initialize a GNUnet client socket.
- *
- * @param port the portnumber in host byte order
- * @param hostname the name of the host to connect to
- * @param result the SOCKET (filled in)
- * @return OK if successful, SYSERR on failure
- */
-int initGNUnetClientSocket(unsigned short port,
- const char * hostname,
- GNUNET_TCP_SOCKET * result);
-
-/**
- * Initialize a GNUnet client socket.
- *
- * @param port the portnumber in host byte order
- * @param ip IP of the host to connect to
- * @param result the SOCKET (filled in)
- * @return OK if successful, SYSERR on failure
- */
-int initGNUnetClientSocketIP(unsigned short port,
- IPaddr ip,
- GNUNET_TCP_SOCKET * result);
-
-/**
- * Initialize a GNUnet server socket.
- * @param sock the open socket
- * @param result the SOCKET (filled in)
- * @return OK (always successful)
- */
-int initGNUnetServerSocket(int socket,
- GNUNET_TCP_SOCKET * result);
-
-/**
- * Check if a socket is open. Will ALWAYS return 'true'
- * for a valid client socket (even if the connection is
- * closed), but will return false for a closed server socket.
- * @return 1 if open, 0 if closed
- */
-int isOpenConnection(GNUNET_TCP_SOCKET * sock);
-
-/**
- * Check a socket, open and connect if it is closed and it is a
- * client-socket.
- */
-int checkSocket(GNUNET_TCP_SOCKET * sock);
-
-/**
- * Read from a GNUnet TCP socket.
- * @param sock the socket
- * @param buffer the buffer to write data to;
- * if NULL == *buffer, *buffer is allocated (caller frees)
- * @return OK if the read was successful, SYSERR if the socket
- * was closed by the other side (if the socket is a
- * client socket and is used again, tcpio will attempt
- * to re-establish the connection [temporary error]).
- */
-int readFromSocket(GNUNET_TCP_SOCKET * sock,
- CS_MESSAGE_HEADER ** buffer);
-
-/**
- * Write to a GNUnet TCP socket.
- * @param sock the socket to write to
- * @param buffer the buffer to write
- * @return OK if the write was sucessful, otherwise SYSERR.
- */
-int writeToSocket(GNUNET_TCP_SOCKET * sock,
- const CS_MESSAGE_HEADER * buffer);
-
-/**
- * Write to a GNUnet TCP socket non-blocking.
- * @param sock the socket to write to
- * @param buffer the buffer to write
- * @return OK if the write was sucessful, NO if it would have blocked and was
not performed,
- * otherwise SYSERR.
- */
-int writeToSocketNonBlocking(GNUNET_TCP_SOCKET * sock,
- const CS_MESSAGE_HEADER * buffer);
-
-/**
- * Close a GNUnet TCP socket for now (use to temporarily close
- * a TCP connection that will probably not be used for a long
- * time; the socket will still be auto-reopened by the
- * readFromSocket/writeToSocket methods if it is a client-socket).
- */
-void closeSocketTemporarily(GNUNET_TCP_SOCKET * sock);
-
-/**
- * Destroy a socket for good. If you use this socket afterwards,
- * you must first invoke initializeSocket, otherwise the operation
- * will fail.
- */
-void destroySocket(GNUNET_TCP_SOCKET * sock);
-
-
-/**
- * Obtain a return value from a remote call from
- * TCP.
- * @param sock the TCP socket
- * @param ret the return value from TCP
- * @return SYSERR on error, OK if the return value was
- * read successfully
- */
-int readTCPResult(GNUNET_TCP_SOCKET * sock,
- int * ret);
-
-/**
- * Send a return value to the caller of a remote call via
- * TCP.
- * @param sock the TCP socket
- * @param ret the return value to send via TCP
- * @return SYSERR on error, OK if the return value was
- * send successfully
- */
-int sendTCPResult(GNUNET_TCP_SOCKET * sock,
- int ret);
-
-/**
- * Get the load of the CPU relative to what is allowed.
- *
- * @return the CPU load as a percentage of allowed
- * (100 is equivalent to full load)
- */
-int getCPULoad(void);
-
-/**
- * Get the load of the network relative to what is allowed.
- * The only difference to networkUsageUp is that
- * this function averages the values over time.
- *
- * @return the network load as a percentage of allowed
- * (100 is equivalent to full load)
- */
-int getNetworkLoadUp(void);
-
-/**
- * Get the load of the network relative to what is allowed.
- * The only difference to networkUsageDown is that
- * this function averages the values over time.
- *
- * @return the network load as a percentage of allowed
- * (100 is equivalent to full load)
- */
-int getNetworkLoadDown(void);
-
-/**
- * Tell statuscalls to increment the number of bytes sent
- */
-void incrementBytesSent(unsigned long long delta);
-
-/**
- * Tell statuscalls to increment the number of bytes received
- */
-void incrementBytesReceived(unsigned long long delta);
-
-/**
- * Get the size of the file (or directory)
- * of the given file (in bytes).
- *
- * @return OK on success, SYSERR on error
- */
-int getFileSize(const char * filename,
- unsigned long long * size);
-
-/**
- * Get the size of the file (or directory) without
- * counting symlinks.
- *
- * @return OK on success, SYSERR on error
- */
-int getFileSizeWithoutSymlinks(const char * filename,
- unsigned long long * size);
-
-/**
- * Get the number of blocks that are left on the partition that
- * contains the given file (for normal users).
- *
- * @param part a file on the partition to check
- * @return -1 on errors, otherwise the number of free blocks
- */
-long getBlocksLeftOnDrive(const char * part);
-
-/**
- * Assert that fil corresponds to a filename
- * (of a file that exists and that is not a directory).
- * @returns 1 if yes, 0 if not (will print an error
- * message in that case, too).
- */
-int assertIsFile(const char * fil);
-
-/**
- * Complete filename (a la shell) from abbrevition.
- * @param fil the name of the file, may contain ~/ or
- * be relative to the current directory
- * @returns the full file name,
- * NULL is returned on error
- */
-char * expandFileName(const char * fil);
-
-/**
- * Implementation of "mkdir -p"
- * @param dir the directory to create
- * @returns SYSERR on failure, OK otherwise
- */
-int mkdirp(const char * dir);
-
-/**
- * Read the contents of a binary file into a buffer.
- * @param fileName the name of the file, not freed,
- * must already be expanded!
- * @param len the maximum number of bytes to read
- * @param result the buffer to write the result to
- * @return the number of bytes read on success, -1 on failure
- */
-int readFile(const char * fileName,
- int len,
- void * result);
-
-/**
- * Write a buffer to a file.
- * @param fileName the name of the file, NOT freed!
- * @param buffer the data to write
- * @param n number of bytes to write
- * @param mode the mode for file permissions
- * @return OK on success, SYSERR on error
- */
-int writeFile(const char * fileName,
- const void * buffer,
- unsigned int n,
- const char * mode);
-
-/**
- * Copy a file.
- * @return OK on success, SYSERR on error
- */
-int copyFile(const char * src,
- const char * dst);
-
-/**
- * Scan a directory for files. The name of the directory
- * must be expanded first (!).
- * @param dirName the name of the directory
- * @param callback the method to call for each file
- * @param data argument to pass to callback
- * @return the number of files found, -1 on error
- */
-int scanDirectory(const char * dirName,
- DirectoryEntryCallback callback,
- void * data);
-
-/**
- * Test if fil is a directory.
- * @returns YES if yes, NO if not
- */
-int isDirectory(const char * fil);
-
-/**
- * Remove all files in a directory (rm -rf). Call with
- * caution.
- *
- *
- * @param fileName the file to remove
- * @return OK on success, SYSERR on error
- */
-int rm_minus_rf(const char * fileName);
-
-/**
- * Stop the application.
- * @param signum is ignored
- */
-void run_shutdown(int signum);
-
-/**
- * Test if the shutdown has been initiated.
- * @return YES if we are shutting down, NO otherwise
- */
-int testShutdown(void);
-
-/**
- * Initialize the signal handlers, etc.
- */
-void initializeShutdownHandlers(void);
-
-/**
- * Wait until the shutdown has been initiated.
- */
-void wait_for_shutdown(void);
-
-void doneShutdownHandlers(void);
-
-/**
- * Print output of --help in GNU format.
- */
-void formatHelp(const char * general,
- const char * description,
- const Help * opt);
-
-/**
- * Parse the default set of options and set
- * options in the configuration accordingly.
- * This does not include --help or --version.
- * @return YES if the option was a default option
- * that was successfully processed
- */
-int parseDefaultOptions(char c,
- char * optarg);
-
-/**
- * Depending on doBlock, enable or disable the nonblocking mode
- * of socket s.
- *
- * @return Upon successful completion, it returns zero.
- * @return Otherwise -1 is returned.
- */
-int setBlocking(int s, int doBlock);
-
-/**
- * Check whether the socket is blocking
- * @param s the socket
- * @return YES if blocking, NO non-blocking
- */
-int isSocketBlocking(int s);
-
-/**
- * Do a NONBLOCKING read on the given socket. Note that in order to
- * avoid blocking, the caller MUST have done a select call before
- * calling this function. Though the caller must be prepared to the
- * fact that this function may fail with EWOULDBLOCK in any case (Win32).
- *
- * @brief Reads at most max bytes to buf. Interrupts are IGNORED.
- * @param s socket
- * @param buf buffer
- * @param max maximum number of bytes to read
- * @param read number of bytes actually read.
- * 0 is returned if no more bytes can be read
- * @return SYSERR on error, YES on success or NO if the operation
- * would have blocked
- */
-int RECV_NONBLOCKING(int s,
- void * buf,
- size_t max,
- size_t *read);
-
-
-/**
- * Do a BLOCKING read on the given socket. Read len bytes (if needed
- * try multiple reads). Interrupts are ignored.
- *
- * @return SYSERR if len bytes could not be read,
- * otherwise the number of bytes read (must be len)
- */
-int RECV_BLOCKING_ALL(int s,
- void * buf,
- size_t len);
-
-
-/**
- * Do a NONBLOCKING write on the given socket.
- * Write at most max bytes from buf.
- * Interrupts are ignored (cause a re-try).
- *
- * The caller must be prepared to the fact that this function
- * may fail with EWOULDBLOCK in any case (Win32).
- *
- * @param s socket
- * @param buf buffer to send
- * @param max maximum number of bytes to send
- * @param sent number of bytes actually sent
- * @return SYSERR on error, YES on success or
- * NO if the operation would have blocked.
- */
-int SEND_NONBLOCKING(int s,
- const void * buf,
- size_t max,
- size_t *sent);
-
-
-/**
- * Do a BLOCKING write on the given socket. Write len bytes (if
- * needed do multiple write). Interrupts are ignored (cause a
- * re-try).
- *
- * @return SYSERR if len bytes could not be send,
- * otherwise the number of bytes transmitted (must be len)
- */
-int SEND_BLOCKING_ALL(int s,
- const void * buf,
- size_t len);
-
-/**
- * Check if socket is valid
- * @return 1 if valid, 0 otherwise
- */
-int isSocketValid(int s);
-
-/**
- * Like snprintf, just aborts if the buffer is of insufficient size.
- */
-int SNPRINTF(char * buf,
- size_t size,
- const char * format,
- ...);
-
-/**
- * open() a file
- */
-int fileopen(const char *filename, int oflag, ...);
-
-/**
- * String functions
- */
-#if !HAVE_STRLCPY
-size_t strlcpy(char *dest, const char *src, size_t size);
-#endif
-#if !HAVE_STRLCAT
-size_t strlcat(char *dest, const char *src, size_t count);
-#endif
-
-/**
- * @brief Get human-readable filesizes from byte numbers
- * @param size_n the size in bytes
- */
-char * getHumanSize (unsigned long long int size_n);
-
-/**
- * @brief Enumerate all network interfaces
- * @param callback the callback function
- */
-void enumNetworkIfs(void (*callback) (const char *, int, void *), void * cls);
-
-/**
- * @brief Checks if we can start GNUnet automatically
- * @return 1 if yes, 0 otherwise
- */
-int isOSAutostartCapable(void);
-
-/**
- * @brief Make GNUnet start automatically
- * @param doAutoStart true to enable autostart, false to disable it
- * @param username name of the user account to use
- * @param groupname name of the group to use
- * @return 0 on success
- */
-int autostartService(int doAutoStart,
- const char *username,
- const char *groupname);
-
-/**
- * @brief Checks if we can add an user for the GNUnet service
- * @return 1 if yes, 0 otherwise
- * @todo support for useradd(8)
- */
-int isOSUserAddCapable(void);
-
-/**
- * @brief Checks if we can add a group for the GNUnet service
- * @return 1 if yes, 0 otherwise
- * @todo support for groupadd(8)
- */
-int isOSGroupAddCapable(void);
-
-/**
- * @brief Add a service account for GNUnet
- * @param group the group of the new user
- * @param name the name of the new user
- * @return 0 on success
- */
-int createGroupUser(const char *group_name,
- const char *user_name);
-
-/**
- * @brief Format a Windows specific error code
- */
-char *winErrorStr(const char *prefix, int dwErr);
-
-/**
- * Checks if gnunetd is running
- *
- * Uses CS_PROTO_traffic_COUNT query to determine if gnunetd is
- * running.
- *
- * @return OK if gnunetd is running, SYSERR if not
- */
-int checkGNUnetDaemonRunning(void);
-
-/**
- * Start gnunetd process
- *
- * @param daemonize YES if gnunetd should be daemonized
- * @return pid_t of gnunetd if NOT daemonized, 0 if
- * daemonized sucessfully, -1 on error
- */
-int startGNUnetDaemon(int daemonize);
-
-
-/**
- * Stop gnunetd
- *
- * Note that returning an error does NOT mean that
- * gnunetd will continue to run (it may have been
- * shutdown by something else in the meantime or
- * crashed). Call checkDaemonRunning() frequently
- * to check the status of gnunetd.
- *
- * Furthermore, note that this WILL potentially kill
- * gnunetd processes on remote machines that cannot
- * be restarted with startGNUnetDaemon!
- *
- * This function does NOT need the PID and will also
- * kill daemonized gnunetd's.
- *
- * @return OK successfully stopped, SYSERR: error
- */
-int stopGNUnetDaemon(void);
-
-
-/**
- * Wait until the gnunet daemon is
- * running.
- *
- * @param timeout how long to wait at most
- * @return OK if gnunetd is now running
- */
-int waitForGNUnetDaemonRunning(cron_t timeout);
-
-
-/**
- * Wait until the gnunet daemon (or any other CHILD process for that
- * matter) with the given PID has terminated. Assumes that
- * the daemon was started with startGNUnetDaemon in no-daemonize mode.
- * On arbitrary PIDs, this function may fail unexpectedly.
- *
- * @return YES if gnunetd shutdown with
- * return value 0, SYSERR if waitpid
- * failed, NO if gnunetd shutdown with
- * some error
- */
-int waitForGNUnetDaemonTermination(int pid);
-
-/**
- * @brief Terminate a process
- * @return YES on success, NO otherwise
- */
-int termProcess(int pid);
-
#if 0 /* keep Emacsens' auto-indent happy */
{
#endif
Modified: GNUnet/src/include/gnunet_util_crypto.h
===================================================================
--- GNUnet/src/include/gnunet_util_crypto.h 2006-06-22 17:39:19 UTC (rev
3023)
+++ GNUnet/src/include/gnunet_util_crypto.h 2006-06-22 17:50:56 UTC (rev
3024)
@@ -41,6 +41,9 @@
#endif
#endif
+#define STRONG YES
+#define WEAK NO
+
/**
* @brief length of the sessionkey in bytes (256 BIT sessionkey)
*/
Modified: GNUnet/src/include/gnunet_util_error.h
===================================================================
--- GNUnet/src/include/gnunet_util_error.h 2006-06-22 17:39:19 UTC (rev
3023)
+++ GNUnet/src/include/gnunet_util_error.h 2006-06-22 17:50:56 UTC (rev
3024)
@@ -38,6 +38,19 @@
#endif
/**
+ * Named constants for return values. The following
+ * invariants hold: "NO == 0" (to allow "if (NO)")
+ * "OK != SYSERR", "OK != NO", "NO != SYSERR"
+ * and finally "YES != NO".
+ */
+#define OK 1
+#define SYSERR -1
+#define YES 1
+#define NO 0
+
+
+
+/**
* Context required to log messages.
*/
struct GE_Context;
@@ -49,10 +62,11 @@
GE_NOTHING = 0x00000000,
/* type of event */
GE_DEBUG = 0x00000001, /* DEBUG/CRON/EVERYTHING */
- GE_STATUS = 0x00000002, /* INFO/MESSAGE */
- GE_WARNING = 0x00000004,
- GE_ERROR = 0x00000008,
- GE_FATAL = 0x00000010, /* FATAL/FAILURE/NOTHING */
+ GE_STATUS = 0x00000002, /* status message */
+ GE_INFO = 0x00000004, /* normal program response */
+ GE_WARNING = 0x00000008,
+ GE_ERROR = 0x00000010,
+ GE_FATAL = 0x00000020, /* FATAL/FAILURE/NOTHING */
GE_EVENTKIND = 0x000000FF, /* bitmask */
/* who should see the message? */
@@ -112,8 +126,10 @@
/**
* Does the given event match the mask?
+ *
* @param have the event type
* @param mask the filter mask
+ * @return YES or NO
*/
int GE_applies(GE_KIND have,
GE_KIND mask);
@@ -121,8 +137,10 @@
/**
* Would an event of this kind be possibly
* processed by the logger?
+ *
* @param ctx the logger
* @param have the kind of event
+ * @return YES or NO
*/
int GE_isLogged(struct GE_Context * ctx,
GE_KIND kind);
@@ -155,7 +173,7 @@
#define GE_ASSERT(ctx, cond) do { if (! (cond)) { GE_LOG(ctx, GE_DEVELOPER |
GE_USER | GE_FATAL | GE_IMMEDIATE, _("Assertion failed at %s:%d in %s.\n"),
__FILE__, __LINE__, __FUNCTION__); abort(); } } while(0);
-#define GE_ASSERT_FLF(ctx, cond, file, line, function) do { if (! (cond)) {
GE_LOG(_(ctx, GE_DEVELOPER | GE_USER | GE_FATAL | GE_IMMEDIATE, "Assertion
failed at %s:%d in %s.\n"), file, line, function); abort(); } } while(0);
+#define GE_ASSERT_FLF(ctx, cond, file, line, function) do { if (! (cond)) {
GE_LOG(ctx, GE_DEVELOPER | GE_USER | GE_FATAL | GE_IMMEDIATE, _("Assertion
failed at %s:%d in %s.\n"), file, line, function); abort(); } } while(0);
#define GE_BREAK(ctx, cond) do { if (! (cond)) { GE_LOG(ctx, GE_DEVELOPER |
GE_USER | GE_FATAL | GE_IMMEDIATE, _("Assertion failed at %s:%d in %s.\n"),
__FILE__, __LINE__, __FUNCTION__); } } while(0);
@@ -180,6 +198,13 @@
* a failure of the command 'cmd' with the message given
* by strerror(errno).
*/
+#define GE_DIE_STRERROR_FLF(ctx, level, cmd, file, line, function) do {
GE_LOG(ctx, level, _("`%s' failed at %s:%d in %s with error: %s\n"), cmd, file,
line, function, STRERROR(errno)); abort(); } while(0);
+
+/**
+ * Log an error message at log-level 'level' that indicates
+ * a failure of the command 'cmd' with the message given
+ * by strerror(errno).
+ */
#define GE_LOG_STRERROR_FLF(ctx, level, cmd, file, line, function) do {
GE_LOG(ctx, level, _("`%s' failed at %s:%d in %s with error: %s\n"), cmd, file,
line, function, STRERROR(errno)); } while(0);
/**
@@ -190,8 +215,6 @@
#define GE_LOG_STRERROR_FILE(ctx, level, cmd, filename) do { GE_LOG(ctx,
level, _("`%s' failed on file `%s' at %s:%d in %s with error: %s\n"), cmd,
filename,__FILE__, __LINE__, __FUNCTION__, STRERROR(errno)); } while(0);
-
-
#if 0 /* keep Emacsens' auto-indent happy */
{
#endif
Modified: GNUnet/src/include/gnunet_util_error_loggers.h
===================================================================
--- GNUnet/src/include/gnunet_util_error_loggers.h 2006-06-22 17:39:19 UTC
(rev 3023)
+++ GNUnet/src/include/gnunet_util_error_loggers.h 2006-06-22 17:50:56 UTC
(rev 3024)
@@ -69,6 +69,15 @@
GE_KIND mask);
/**
+ * Create a logger that writes events to stderr
+ *
+ * @param mask which events should be logged?
+ */
+struct GE_Context *
+GE_create_context_stdout(int logDate,
+ GE_KIND mask);
+
+/**
* Create a logger that keeps events in memory (to be
* queried later in bulk).
*/
Modified: GNUnet/src/util/Makefile.am
===================================================================
--- GNUnet/src/util/Makefile.am 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/Makefile.am 2006-06-22 17:50:56 UTC (rev 3024)
@@ -1,4 +1,9 @@
-SUBDIRS = $(WINSUBDIRS) $(CYGSUBDIRS) error string config getopt . config_impl
loggers crypto containers
+SUBDIRS = $(WINSUBDIRS) $(CYGSUBDIRS) \
+ error string config \
+ getopt disk threads \
+ os network . \
+ config_impl loggers \
+ crypto cron containers
INCLUDES = -I$(top_srcdir)/src/include
@@ -34,11 +39,16 @@
lib_LTLIBRARIES = libgnunetutil.la
libgnunetutil_la_LIBADD = $(GCLIBADD) $(CYGLIBADD) $(WINLIBADD) \
- error/liberror.la \
config/libconfig.la \
+ disk/libdisk.la \
+ error/liberror.la \
+ getopt/libgetopt.la \
string/libstring.la \
- getopt/libgetopt.la
+ network/libnetwork.la \
+ os/libos.la \
+ threads/libthreads.la
+
EXTRA_DIST = \
testconfig.conf \
check.conf
@@ -48,86 +58,5 @@
-version-info 1:0:0
libgnunetutil_la_SOURCES = \
- cron.c \
- daemon.c \
- dso.c \
- endian.c \
- getopt.c \
- initialize.c \
- io.c \
- ipcheck.c \
- osconfig.c \
- printhelp.c \
- port.c \
- semaphore.c \
- shutdown.c \
- state.c \
- statuscalls.c \
- storage.c \
- tcp_return.c \
- tcpio.c \
- timer.c
+ initialize.c time.c
-################################
-# TESTCASES
-################################
-
-check_PROGRAMS = \
- crontest \
- daemontest \
- semaphoretest \
- shutdowntest \
- statetest \
- statuscallstest \
- storagetest \
- tcpiotest \
- timertest
-
-TESTS = $(check_PROGRAMS)
-
-daemontest_SOURCES = \
- daemontest.c
-daemontest_LDADD = \
- $(top_builddir)/src/util/libgnunetutil.la
-
-statetest_SOURCES = \
- statetest.c
-statetest_LDADD = \
- $(top_builddir)/src/util/libgnunetutil.la
-
-shutdowntest_SOURCES = \
- shutdowntest.c
-shutdowntest_LDADD = \
- $(top_builddir)/src/util/libgnunetutil.la
-
-timertest_SOURCES = \
- timertest.c
-timertest_LDADD = \
- $(top_builddir)/src/util/libgnunetutil.la
-
-tcpiotest_SOURCES = \
- tcpiotest.c
-tcpiotest_LDADD = \
- $(top_builddir)/src/util/libgnunetutil.la
-
-crontest_SOURCES = \
- crontest.c
-crontest_LDADD = \
- $(top_builddir)/src/util/libgnunetutil.la
-
-storagetest_SOURCES = \
- storagetest.c
-storagetest_LDADD = \
- $(top_builddir)/src/util/libgnunetutil.la
-
-statuscallstest_SOURCES = \
- statuscallstest.c
-statuscallstest_LDADD = \
- $(top_builddir)/src/util/libgnunetutil.la
-
-semaphoretest_SOURCES = \
- semaphoretest.c
-semaphoretest_LDADD = \
- $(top_builddir)/src/util/libgnunetutil.la
-
-
Modified: GNUnet/src/util/README
===================================================================
--- GNUnet/src/util/README 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/README 2006-06-22 17:50:56 UTC (rev 3024)
@@ -1,12 +1,22 @@
-Util is now structured as follows:
+util/ is now structured as follows:
util/error: basic error handling functions (lowest layer)
util/win: win32 portability (lowest layer)
-util/string: string and memory abstraction (depends on error)
-util/config: configuration handling (depends on error)
-util/getopt: command line parsing (depends on config)
-util: main utility library (depends on error/, win/ and config/, string/ and
getopt/)
- => these are linked into gnunetutil.so
+ util/string: string and memory abstraction (depends on error)
+ util/disk : disk IO abstractions (depends on string)
+ util/config: configuration handling (depends on error)
+ util/getopt: command line parsing (depends on config)
+ util/threads: pthread abstractions (depends on error)
+
+-------- TODO ----------
+ util/network: network IO abstractions (depends on threads, config)
+ util/os : process and system abstractions (depends on threads, config)
+
+util: main utility library (depends on all of the above)
+ => these are all statically linked into gnunetutil.so
+
+util/cron: periodic job execution (depends on gnunetutil.so)
+ => linked to gnunetutil_cron.so
util/loggers: specific logging implementations (depends on gnunetutil.so)
=> linked to gnunetutil_logging.so
util/config_impl: implementation of config API (depends on gnunetutil.so)
Deleted: GNUnet/src/util/cron.c
===================================================================
--- GNUnet/src/util/cron.c 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/cron.c 2006-06-22 17:50:56 UTC (rev 3024)
@@ -1,708 +0,0 @@
-/*
- 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/cron.c
- * @author Christian Grothoff
- *
- * @brief Module for periodic background (cron) jobs.
- *
- * The module only uses one thread, thus every cron-job must be
- * short-lived, should never block for an indefinite amount of
- * time. Specified deadlines are only a guide-line, the 10ms
- * timer-resolution is only an upper-bound on the possible precision,
- * in practice it will be worse (depending on the other cron-jobs).
- *
- * If you need to schedule a long-running or blocking cron-job,
- * run a function that will start another thread that will
- * then run the actual job.
- */
-
-#include "gnunet_util.h"
-#include "platform.h"
-
-#define DEBUG_CRON NO
-
-#if DEBUG_CRON
-#define HAVE_PRINT_CRON_TAB 1
-#else
-#define HAVE_PRINT_CRON_TAB 0
-#endif
-
-/**
- * The initial size of the cron-job table
- */
-#define INIT_CRON_JOBS 16
-
-/**
- * how long do we sleep at most? In some systems, the
- * signal-interrupted sleep does not work nicely, so to ensure
- * progress, we should rather wake up periodically. (But we don't want
- * to burn too much CPU time doing busy waiting; every 2s strikes a
- * good balance)
- */
-#define MAXSLEEP 2000
-
-#define CHECK_ASSERTS 1
-
-/**
- * The Delta-list for the cron jobs.
- */
-typedef struct {
- /** The start-time for this event (in milliseconds). */
- cron_t delta;
- /** The method to call at that point. */
- CronJob method;
- /** for cron-jobs: when this should be repeated
- automatically, 0 if this was a once-only job */
- unsigned int deltaRepeat;
- /** The index of the next entry in the delta list
- after this one */
- int next;
- /** data ptr (argument to the method) */
- void * data;
-} UTIL_cron_DeltaListEntry;
-
-/**
- * The delta-list of waiting tasks.
- */
-static UTIL_cron_DeltaListEntry * deltaList_;
-
-/**
- * The current size of the DeltaList.
- */
-static unsigned int deltaListSize_;
-
-/**
- * The lock for the delta-list.
- */
-static Mutex deltaListLock_;
-
-/**
- * The currently running job.
- */
-static CronJob runningJob_;
-static unsigned int runningRepeat_;
-static void * runningData_;
-
-/**
- * The first empty slot in the delta-list.
- */
-static int firstFree_;
-
-/**
- * The first empty slot in the delta-list.
- */
-static int firstUsed_;
-
-/**
- * The cron thread.
- */
-static int cron_shutdown = YES;
-static Semaphore * cron_signal = NULL;
-static Semaphore * cron_signal_up = NULL;
-
-static PTHREAD_T cron_handle;
-
-
-/* don't do anything, we use SIGALRM to abort
- the nanosleep */
-#ifndef WINDOWS
-static void sigalrmHandler(int sig) {
-}
-#endif
-
-static Mutex inBlockLock_;
-
-
-/**
- * Initialize the cron service.
- */
-void initCron() {
- unsigned int i;
-#ifndef MINGW
- static struct sigaction sig;
- static struct sigaction old;
-#endif
-
- deltaListSize_ = INIT_CRON_JOBS;
- deltaList_
- = MALLOC(sizeof(UTIL_cron_DeltaListEntry) * deltaListSize_);
- for (i=0;i<deltaListSize_;i++)
- deltaList_[i].next = i-1;
- firstFree_ = deltaListSize_-1;
- MUTEX_CREATE_RECURSIVE(&deltaListLock_);
- MUTEX_CREATE(&inBlockLock_);
- runningJob_ = NULL;
- firstUsed_ = -1;
- /* SA_NODEFER == SA_NOMASK but is available on linux */
-
-#ifndef WINDOWS /* We don't use signals under Windows */
- memset(&sig, 0, sizeof(struct sigaction));
- memset(&old, 0, sizeof(struct sigaction));
- sig.sa_flags = SA_NODEFER;
- sig.sa_handler = &sigalrmHandler;
- sigaction(SIGALRM, &sig, &old);
-#endif
- cron_signal_up = SEMAPHORE_NEW(0);
-}
-
-static void noJob(void * unused) {
-#if DEBUG_CRON
- GE_LOG(NULL,
- GE_STATUS | GE_DEVELOPER | GE_BULK,
- "In noJob.\n");
-#endif
-}
-
-/**
- * Stop the cron service.
- */
-void stopCron() {
- void * unused;
-
-#if DEBUG_CRON
- GE_LOG(NULL,
- GE_STATUS | GE_DEVELOPER | GE_BULK,
- "Stopping cron\n");
-#endif
- cron_shutdown = YES;
- addCronJob(&noJob, 0, 0, NULL);
- SEMAPHORE_DOWN(cron_signal);
- SEMAPHORE_FREE(cron_signal);
- cron_signal = NULL;
- PTHREAD_JOIN(&cron_handle, &unused);
-#if DEBUG_CRON
- GE_LOG(NULL,
- GE_STATUS | GE_DEVELOPER | GE_BULK,
- "Cron stopped\n");
-#endif
-}
-
-static int inBlock = 0;
-
-/**
- * CronJob to suspend the cron thread
- * until it is resumed.
- */
-static void block(void * sem) {
- Semaphore * sig = sem;
- int ok = SYSERR;
-
- if (sig != NULL)
- SEMAPHORE_UP(sig);
- while (ok == SYSERR) {
- SEMAPHORE_DOWN(cron_signal_up);
- MUTEX_LOCK(&inBlockLock_);
- inBlock--;
- if (inBlock == 0)
- ok = OK;
- MUTEX_UNLOCK(&inBlockLock_);
- }
-}
-
-/**
- * Stop running cron-jobs for a short time. This method may only be
- * called by a thread that is not holding any locks (otherwise
- * there is the danger of a deadlock).
- */
-void suspendCron() {
- Semaphore * blockSignal;
-
- GE_ASSERT(NULL, cron_shutdown == NO);
- GE_ASSERT(NULL, NO == PTHREAD_SELF_TEST(&cron_handle));
- MUTEX_LOCK(&inBlockLock_);
- inBlock++;
- if (inBlock == 1) {
- blockSignal = SEMAPHORE_NEW(0);
- addCronJob(&block,
- 0,
- 0,
- blockSignal);
- SEMAPHORE_DOWN(blockSignal);
- SEMAPHORE_FREE(blockSignal);
- }
- MUTEX_UNLOCK(&inBlockLock_);
-}
-
-int isCronRunning() {
- if ( (NO == cron_shutdown) || (inBlock > 0) )
- return YES;
- else
- return NO;
-}
-
-/**
- * Resume running cron-jobs.
- */
-void resumeCron() {
- GE_ASSERT(NULL, inBlock > 0);
- SEMAPHORE_UP(cron_signal_up);
-}
-
-void suspendIfNotCron() {
- if (NO == PTHREAD_SELF_TEST(&cron_handle))
- suspendCron();
-}
-
-void resumeIfNotCron() {
- if (NO == PTHREAD_SELF_TEST(&cron_handle))
- resumeCron();
-}
-
-static void abortSleep() {
- if (cron_signal == NULL)
- return; /* cron_handle not valid */
- PTHREAD_KILL(&cron_handle, SIGALRM);
-}
-
-
-#if HAVE_PRINT_CRON_TAB
-/**
- * Print the cron-tab.
- */
-void printCronTab() {
- int jobId;
- UTIL_cron_DeltaListEntry * tab;
- cron_t now;
-
- cronTime(&now);
- MUTEX_LOCK(&deltaListLock_);
-
- jobId = firstUsed_;
- while (jobId != -1) {
- tab = &deltaList_[jobId];
- GE_LOG(NULL,
- GE_STATUS | GE_DEVELOPER | GE_BULK,
- "%3u: delta %8lld CU --- method %p --- repeat %8u CU\n",
- jobId,
- tab->delta - now,
- (int)tab->method,
- tab->deltaRepeat);
- jobId = tab->next;
- }
- MUTEX_UNLOCK(&deltaListLock_);
-}
-#endif
-
-
-/**
- * If the specified cron-job exists in th delta-list, move it to the
- * head of the list. If it is running, do nothing. If it is does not
- * exist and is not running, add it to the list to run it next.
- *
- * @param method which method should we run
- * @param deltaRepeat if this is a periodic, the time between
- * the runs, otherwise 0.
- * @param data extra argument to calls to method, freed if
- * non-null and cron is shutdown before the job is
- * run and/or delCronJob is called
- */
-void advanceCronJob(CronJob method,
- unsigned int deltaRepeat,
- void * data) {
- UTIL_cron_DeltaListEntry * job;
- UTIL_cron_DeltaListEntry * last;
- int jobId;
-
-#if DEBUG_CRON
- GE_LOG(NULL,
- GE_STATUS | GE_DEVELOPER | GE_BULK,
- "Advancing job %p-%p\n",
- method,
- data);
-#endif
- MUTEX_LOCK(&deltaListLock_);
- jobId = firstUsed_;
- if (jobId == -1) {
- /* not in queue; add if not running */
- if ( (method != runningJob_) ||
- (data != runningData_) ||
- (deltaRepeat != runningRepeat_) ) {
- GE_LOG(NULL,
- GE_ERROR | GE_USER | GE_DEVELOPER | GE_BULK,
- _("`%s' called with cron job not in queue, adding. This may not
be what you want.\n"),
- __FUNCTION__);
- addCronJob(method,
- 0,
- deltaRepeat,
- data);
- }
- MUTEX_UNLOCK(&deltaListLock_);
- return;
- }
- last = NULL;
- job = &deltaList_[jobId];
- while ( (job->method != method) ||
- (job->data != data) ||
- (job->deltaRepeat != deltaRepeat) ) {
- last = job;
- if (job->next == -1) {
- /* not in queue; add if not running */
- if ( (method != runningJob_) ||
- (data != runningData_) ||
- (deltaRepeat != runningRepeat_) ) {
- addCronJob(method,
- 0,
- deltaRepeat,
- data);
- }
- MUTEX_UNLOCK(&deltaListLock_);
- return;
- }
- jobId = job->next;
- job = &deltaList_[jobId];
- }
- /* ok, found it; remove, re-add with time 0 */
- delCronJob(method,
- deltaRepeat,
- data);
- addCronJob(method,
- 0,
- deltaRepeat,
- data);
- MUTEX_UNLOCK(&deltaListLock_);
-}
-
-/**
- * Add a cron-job to the delta list.
- *
- * @param method which method should we run
- * @param delta how many milliseconds until we run the method
- * @param deltaRepeat if this is a periodic, the time between
- * the runs, otherwise 0.
- * @param data extra argument to calls to method, freed if
- * non-null and cron is shutdown before the job is
- * run and/or delCronJob is called
- */
-void addCronJob(CronJob method,
- unsigned int delta,
- unsigned int deltaRepeat,
- void * data) {
- UTIL_cron_DeltaListEntry * entry;
- UTIL_cron_DeltaListEntry * pos;
- int last;
- int current;
-
-#if DEBUG_CRON
- GE_LOG(NULL,
- GE_STATUS | GE_DEVELOPER | GE_BULK,
- "Adding job %p-%p to fire in %d CU\n",
- method,
- data,
- delta);
-#endif
-
- MUTEX_LOCK(&deltaListLock_);
- if (firstFree_ == -1) { /* need to grow */
- unsigned int i;
-
- GROW(deltaList_,
- deltaListSize_,
- deltaListSize_ * 2);
- for (i=deltaListSize_/2;i<deltaListSize_;i++)
- deltaList_[i].next = i-1;
- deltaList_[deltaListSize_/2].next = -1;
- firstFree_ = deltaListSize_-1;
- }
- entry = &deltaList_[firstFree_];
- entry->method = method;
- entry->data = data;
- entry->deltaRepeat = deltaRepeat;
- entry->delta = cronTime(NULL) + delta;
- if (firstUsed_ == -1) {
- firstUsed_
- = firstFree_;
- firstFree_
- = entry->next;
- entry->next = -1; /* end of list */
- MUTEX_UNLOCK(&deltaListLock_);
- /* interrupt sleeping cron-thread! */
- abortSleep();
- return;
- }
- /* no, there are jobs waiting */
- last = -1;
- current = firstUsed_;
- pos = &deltaList_[current];
-
- while (entry->delta > pos->delta) {
- if (pos->next != -1) {
- last = current;
- current = pos->next;
- pos = &deltaList_[current];
- } else { /* append */
- pos->next = firstFree_;
- firstFree_
- = entry->next;
- entry->next = -1;
- MUTEX_UNLOCK(&deltaListLock_);
-#if HAVE_PRINT_CRON_TAB
- printCronTab();
-#endif
- return;
- }
- }
- /* insert before pos */
- if (last == -1) {
- firstUsed_ = firstFree_;
- abortSleep();
- } else {
- deltaList_[last].next = firstFree_;
-#if HAVE_PRINT_CRON_TAB
- printCronTab();
-#endif
- }
- firstFree_
- = entry->next;
- entry->next = current;
- MUTEX_UNLOCK(&deltaListLock_);
-}
-
-/**
- * Process the cron-job at the beginning of the waiting queue, that
- * is, remove, invoke, and re-insert if it is a periodical job. Make
- * sure the cron job is held when calling this method, but
- * note that it will be released briefly for the time
- * where the job is running (the job to run may add other
- * jobs!)
- */
-static void runJob() {
- UTIL_cron_DeltaListEntry * job;
- int jobId;
- CronJob method;
- void * data;
- unsigned int repeat;
-
- jobId = firstUsed_;
- if (jobId == -1)
- return; /* no job to be done */
- job = &deltaList_[jobId];
- method = job->method;
- runningJob_ = method;
- data = job->data;
- runningData_ = data;
- repeat = job->deltaRepeat;
- runningRepeat_ = repeat;
- /* remove from queue */
- firstUsed_
- = job->next;
- job->next
- = firstFree_;
- firstFree_ = jobId;
- MUTEX_UNLOCK(&deltaListLock_);
- /* re-insert */
- if (repeat > 0) {
-#if DEBUG_CRON
- GE_LOG(NULL,
- GE_STATUS | GE_DEVELOPER | GE_BULK,
- "adding periodic job %p-%p to run again in %u\n",
- method,
- data,
- repeat);
-#endif
- addCronJob(method, repeat, repeat, data);
- }
- /* run */
-#if DEBUG_CRON
- GE_LOG(NULL,
- GE_STATUS | GE_DEVELOPER | GE_BULK,
- "running job %p-%p\n",
- method,
- data);
-#endif
- method(data);
- MUTEX_LOCK(&deltaListLock_);
- runningJob_ = NULL;
-#if DEBUG_CRON
- GE_LOG(NULL,
- GE_STATUS | GE_DEVELOPER | GE_BULK,
- "job %p-%p done\n",
- method,
- data);
-#endif
-}
-
-/**
- * The main-method of cron.
- */
-static void * cron(void * unused) {
- cron_t now;
- cron_t next;
-
- while (cron_shutdown == NO) {
-#if HAVE_PRINT_CRON_TAB
- printCronTab();
-#endif
- cronTime(&now);
- next = now + 0xFFFFFFFF;
- MUTEX_LOCK(&deltaListLock_);
- while (firstUsed_ != -1) {
- cronTime(&now);
- next = deltaList_[firstUsed_].delta;
- if (next <= now) {
-#if DEBUG_CRON
- LOG(LOG_CRON,
- "running cron job, table is\n");
- printCronTab();
-#endif
- runJob();
-#if DEBUG_CRON
- GE_LOG(NULL,
- GE_STATUS | GE_DEVELOPER | GE_BULK,
- "job run, new table is\n");
- printCronTab();
-#endif
- } else
- break;
- }
- MUTEX_UNLOCK(&deltaListLock_);
- next = next - now; /* how long to sleep */
-#if DEBUG_CRON
- GE_LOG(NULL,
- GE_STATUS | GE_DEVELOPER | GE_BULK,
- "Sleeping at %llu for %llu CU (%llu s, %llu CU)\n",
- now,
- next,
- next / cronSECONDS,
- next);
-#endif
- if (next > MAXSLEEP)
- next = MAXSLEEP;
- if (cron_shutdown == NO)
- gnunet_util_sleep(next);
-#if DEBUG_CRON
- GE_LOG(NULL,
- GE_STATUS | GE_DEVELOPER | GE_BULK,
- "woke up at %llu - %lld CS late\n",
- cronTime(NULL),
- cronTime(NULL)-(now+next));
-#endif
- }
- SEMAPHORE_UP(cron_signal);
-#if DEBUG_CRON
- GE_LOG(NULL,
- GE_STATUS | GE_DEVELOPER | GE_BULK,
- "Cron thread exits.\n");
- printCronTab();
-#endif
- return NULL;
-}
-
-
-/**
- * Make sure to call stopCron before calling this method!
- */
-void doneCron() {
- int i;
-
- i = firstUsed_;
- while (i != -1) {
- FREENONNULL(deltaList_[i].data);
- i = deltaList_[i].next;
- }
- MUTEX_DESTROY(&deltaListLock_);
- MUTEX_DESTROY(&inBlockLock_);
- FREE(deltaList_);
- SEMAPHORE_FREE(cron_signal_up);
- deltaList_ = NULL;
-}
-
-/**
- * Start the cron jobs.
- */
-void startCron() {
- GE_ASSERT(NULL, cron_signal == NULL);
- cron_shutdown = NO;
- cron_signal = SEMAPHORE_NEW(0);
- /* large stack, we don't know for sure
- what the cron jobs may be doing */
- if (0 != PTHREAD_CREATE(&cron_handle,
- &cron,
- NULL,
- 256 * 1024))
- GE_DIE_STRERROR(NULL,
- GE_FATAL | GE_ADMIN | GE_USER | GE_BULK,
- "pthread_create");
-}
-
-
-/**
- * Remove all matching cron-jobs from the list. This method should
- * only be called while cron is suspended or stopped, or from a cron
- * job that deletes another cron job. If cron is not suspended or
- * stopped, it may be running the method that is to be deleted, which
- * could be bad (in this case, the deletion will not affect the
- * running job and may return before the running job has terminated).
- *
- * @param method which method is listed?
- * @param repeat which repeat factor was chosen?
- * @param data what was the data given to the method
- * @return the number of jobs removed
- */
-int delCronJob(CronJob method,
- unsigned int repeat,
- void * data) {
- UTIL_cron_DeltaListEntry * job;
- UTIL_cron_DeltaListEntry * last;
- int jobId;
-
-#if DEBUG_CRON
- GE_LOG(NULL,
- GE_STATUS | GE_DEVELOPER | GE_BULK,
- "deleting job %p-%p\n",
- method,
- data);
-#endif
- MUTEX_LOCK(&deltaListLock_);
- jobId = firstUsed_;
- if (jobId == -1) {
- MUTEX_UNLOCK(&deltaListLock_);
- return 0;
- }
- last = NULL;
- job = &deltaList_[jobId];
- while ( (job->method != method) ||
- (job->data != data) ||
- (job->deltaRepeat != repeat) ) {
- last = job;
- if (job->next == -1) {
- MUTEX_UNLOCK(&deltaListLock_);
- return 0;
- }
- jobId = job->next;
- job = &deltaList_[jobId];
- }
- if (last != NULL)
- last->next = job->next;
- else
- firstUsed_ = job->next;
- job->next
- = firstFree_;
- firstFree_ = jobId;
- job->method = NULL;
- job->data = NULL;
- job->deltaRepeat = 0;
- MUTEX_UNLOCK(&deltaListLock_);
- /* ok, there may be more matches, go again! */
- return 1 + delCronJob(method, repeat, data);
-}
-
-/* end of cron.c */
Deleted: GNUnet/src/util/crontest.c
===================================================================
--- GNUnet/src/util/crontest.c 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/crontest.c 2006-06-22 17:50:56 UTC (rev 3024)
@@ -1,105 +0,0 @@
-/**
- * @file test/crontest.c
- * @brief Testcase for cron.
- * @author Christian Grothoff
- */
-
-#include "gnunet_util.h"
-#include "platform.h"
-
-static int global;
-static int global2;
-static int global3;
-
-/**
- * Initialize controlThread.
- */
-void initCron();
-
-/**
- * Make sure to call stopCron before calling this method!
- */
-void doneCron();
-
-/**
- * Process the cron-job at the beginning of the waiting
- * queue, that is, remove, invoke, and re-insert if
- * it is a periodical job. Make sure the sync is down
- * while the job is running (it may add other jobs!)
- */
-void runJob();
-
-static void cronJob(void * unused) {
- global++;
-}
-static void cronJob2(void * unused) {
- global2++;
-}
-static void cronJob3(void * unused) {
- global3++;
-}
-
-int testCron() {
- int i;
-
- global = -1;
- global2 = -1;
- global3 = -1;
- addCronJob(&cronJob, cronSECONDS*1, cronSECONDS*1, NULL);
- addCronJob(&cronJob2, cronSECONDS*4, cronSECONDS*4, NULL);
- addCronJob(&cronJob3, cronSECONDS*16, cronSECONDS*16, NULL);
- for (i=0;i<10;i++) {
- /* fprintf(stderr,"."); */
- sleep(1);
- if (((global-i) * (global-i)) > 9) {
- fprintf(stderr,"1: Expected %d got %d\n", i, global);
- return 1;
- }
- if (((global2-(i>>2)) * (global2-(i>>2))) > 9) {
- fprintf(stderr,"2: Expected %d got %d\n", i>>2, global2);
- return 1;
- }
- if (((global3-(i>>4)) * (global3-(i>>4))) > 9) {
- fprintf(stderr,"3: Expected %d got %d\n", i>>4, global3);
- return 1;
- }
- }
- delCronJob(&cronJob, cronSECONDS*1, NULL);
- delCronJob(&cronJob2, cronSECONDS*4, NULL);
- delCronJob(&cronJob3, cronSECONDS*16, NULL);
- return 0;
-}
-
-static void delJob() {
- delCronJob(&cronJob, 42, NULL);
-}
-
-static int testDelCron() {
- global = 0;
- addCronJob(&cronJob, cronSECONDS*1, 42, NULL);
- addCronJob(&delJob, 500 * cronMILLIS, 0, NULL);
- sleep(1);
- if (global != 0) {
- fprintf(stderr,
- "cron job was supposed to be deleted, but ran anyway!\n");
- return 1;
- } else
- return 0;
-}
-
-int main(int argc, char * argv[]) {
- int failureCount = 0;
-
- initCron();
- startCron();
- failureCount += testCron();
- failureCount += testDelCron();
- stopCron();
- doneCron();
- if (failureCount == 0)
- return 0;
- else {
- printf("\n\n%d TESTS FAILED!\n\n",failureCount);
- return -1;
- }
-} /* end of main */
Modified: GNUnet/src/util/crypto/locking_gcrypt.c
===================================================================
--- GNUnet/src/util/crypto/locking_gcrypt.c 2006-06-22 17:39:19 UTC (rev
3023)
+++ GNUnet/src/util/crypto/locking_gcrypt.c 2006-06-22 17:50:56 UTC (rev
3024)
@@ -39,7 +39,7 @@
MUTEX_UNLOCK(&gcrypt_shared_lock);
}
-void __attribute__ ((constructor)) gnunet_crypto_ltdl_init(void) {
+void __attribute__ ((constructor)) gnunet_crypto_ltdl_init() {
MUTEX_CREATE_RECURSIVE(&gcrypt_shared_lock);
gcry_control(GCRYCTL_DISABLE_SECMEM, 0);
if (! gcry_check_version(GCRYPT_VERSION)) {
@@ -56,6 +56,6 @@
#endif
}
-void __attribute__ ((destructor)) gnunet_crypto_ltdl_fini(void) {
+void __attribute__ ((destructor)) gnunet_crypto_ltdl_fini() {
MUTEX_DESTROY(&gcrypt_shared_lock);
}
Deleted: GNUnet/src/util/daemon.c
===================================================================
--- GNUnet/src/util/daemon.c 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/daemon.c 2006-06-22 17:50:56 UTC (rev 3024)
@@ -1,336 +0,0 @@
-/*
- This file is part of GNUnet.
- (C) 2005 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 src/util/daemon.c
- * @brief code for client-gnunetd interaction (start, stop, waitpid, check
running)
- * @author Christian Grothoff
- */
-
-#include "platform.h"
-#include "gnunet_util.h"
-#include "gnunet_protocols.h"
-
-
-/**
- * Checks if gnunetd is running
- *
- * Uses CS_PROTO_traffic_COUNT query to determine if gnunetd is
- * running.
- *
- * @return OK if gnunetd is running, SYSERR if not
- */
-int checkGNUnetDaemonRunning(struct GE_Context * ectx) {
- GNUNET_TCP_SOCKET * sock;
- CS_MESSAGE_HEADER csHdr;
- int ret;
-
- sock = getClientSocket(ectx);
- if (sock == NULL)
- return SYSERR;
-
- csHdr.size
- = htons(sizeof(CS_MESSAGE_HEADER));
- csHdr.type
- = htons(CS_PROTO_traffic_COUNT);
- if (SYSERR == writeToSocket(sock,
- &csHdr)) {
- releaseClientSocket(sock);
- return SYSERR;
- }
- if (SYSERR == readTCPResult(sock,
- &ret)) {
- releaseClientSocket(sock);
- return SYSERR;
- }
- releaseClientSocket(sock);
- return OK;
-}
-
-
-#if LINUX || OSX || SOLARIS || SOMEBSD
-/**
- * Fork a gnunetd process
- *
- * @param daemonize YES if gnunetd should be daemonized
- * @return pid_t of gnunetd if NOT daemonized, 0 if
- * daemonized sucessfully, -1 on error
- */
-static pid_t launchWithExec(int daemonize) {
- pid_t pid;
-
- pid = fork();
- if (pid == 0) {
- char * args[5];
- char * path;
- char * cp;
-
- path = NULL;
- cp = getConfigurationString("MAIN",
- "ARGV[0]");
- if (cp != NULL) {
- int i = strlen(cp);
- while ( (i >= 0) &&
- (cp[i] != DIR_SEPARATOR) )
- i--;
- if ( i != -1 ) {
- cp[i+1] = '\0';
- path = MALLOC(i+2+strlen("gnunetd"));
- strcpy(path, cp);
- strcat(path, "gnunetd");
- if (ACCESS(path, X_OK) == 0) {
- args[0] = path;
- } else {
- FREE(path);
- path = NULL;
- args[0] = "gnunetd";
- }
- FREE(cp);
- } else {
- args[0] = "gnunetd";
- }
- }
- cp = getConfigurationString("GNUNET",
- "GNUNETD-CONFIG");
- if (cp != NULL) {
- args[1] = "-c";
- args[2] = cp;
- if (NO == daemonize) {
- args[3] = "-d";
- args[4] = NULL;
- } else
- args[3] = NULL;
- } else {
- if (NO == daemonize) {
- args[1] = "-d";
- args[2] = NULL;
- } else
- args[1] = NULL;
- }
- errno = 0;
- nice(10); /* return value is not well-defined */
- if (errno != 0)
- LOG_STRERROR(LOG_WARNING, "nice");
- if (path != NULL)
- execv(path,
- args);
- else
- execvp("gnunetd",
- args);
- LOG_STRERROR(LOG_FAILURE, "exec");
- LOG(LOG_FAILURE,
- _("Attempted path to `%s' was `%s'.\n"),
- "gnunetd",
- (path == NULL) ? "gnunetd" : path);
- FREENONNULL(path); /* yeah, right, like we're likely to get
- here... */
- _exit(-1);
- } else if (daemonize) {
- pid_t ret;
- int status;
-
- ret = waitpid(pid, &status, 0);
- if (ret == -1) {
- LOG_STRERROR(LOG_ERROR, "waitpid");
- return SYSERR;
- }
- if ( (WIFEXITED(status) &&
- (0 != WEXITSTATUS(status)) ) ) {
- return SYSERR;
- }
-#ifdef WCOREDUMP
- if (WCOREDUMP(status)) {
- return SYSERR;
- }
-#endif
- if (WIFSIGNALED(status) ||
- WTERMSIG(status) ) {
- return SYSERR;
- }
- return 0;
- }
- return pid;
-}
-#endif
-
-/**
- * Start gnunetd process
- *
- * @param daemonize YES if gnunetd should be daemonized
- * @return pid_t of gnunetd if NOT daemonized, 0 if
- * daemonized sucessfully, -1 on error
- */
-int startGNUnetDaemon(int daemonize) {
-#if LINUX || OSX || SOLARIS || SOMEBSD
- return launchWithExec(daemonize);
-#elif MINGW
- char szCall[_MAX_PATH + 1], szWd[_MAX_PATH + 1], szCWd[_MAX_PATH + 1];
- char *args[1], *cp = NULL;
- int pid;
- int idx = 0;
-
- plibc_conv_to_win_path("/bin/gnunetd.exe", szCall);
- plibc_conv_to_win_path("/bin", szWd);
- _getcwd(szCWd, _MAX_PATH);
-
- chdir(szWd);
-
- if (daemonize == NO) {
- args[0] = "-d";
- idx = 1;
-
- cp = getConfigurationString("GNUNET",
- "GNUNETD-CONFIG");
- if (cp) {
- args[1] = "-c";
- args[2] = cp;
- idx=3;
- }
- }
-
- args[idx] = NULL;
- pid = spawnvp(_P_NOWAIT, szCall, (const char *const *) args);
- chdir(szCWd);
-
- FREENONNULL(cp);
-
- return (daemonize == NO) ? pid : 0;
-#else
- /* any system out there that does not support THIS!? */
- system("gnunetd"); /* we may not have nice,
- so let's be minimalistic here. */
- return 0;
-#endif
-}
-
-
-/**
- * Stop gnunetd
- *
- * Note that returning an error does NOT mean that
- * gnunetd will continue to run (it may have been
- * shutdown by something else in the meantime or
- * crashed). Call checkDaemonRunning() frequently
- * to check the status of gnunetd.
- *
- * Furthermore, note that this WILL potentially kill
- * gnunetd processes on remote machines that cannot
- * be restarted with startGNUnetDaemon!
- *
- * This function does NOT need the PID and will also
- * kill daemonized gnunetd's.
- *
- * @return OK successfully stopped, SYSERR: error
- */
-int stopGNUnetDaemon() {
- GNUNET_TCP_SOCKET * sock;
- CS_MESSAGE_HEADER csHdr;
- int ret;
-
- sock = getClientSocket();
- if (sock == NULL)
- return SYSERR;
- csHdr.size
- = htons(sizeof(CS_MESSAGE_HEADER));
- csHdr.type
- = htons(CS_PROTO_SHUTDOWN_REQUEST);
- if (SYSERR == writeToSocket(sock,
- &csHdr)) {
- releaseClientSocket(sock);
- return SYSERR;
- }
- if (SYSERR == readTCPResult(sock,
- &ret)) {
- releaseClientSocket(sock);
- return SYSERR;
- }
- releaseClientSocket(sock);
- return ret;
-}
-
-/**
- * Wait until the gnunet daemon is
- * running.
- *
- * @param timeout how long to wait at most
- * @return OK if gnunetd is now running
- */
-int waitForGNUnetDaemonRunning(cron_t timeout) {
- timeout += cronTime(NULL);
- while (OK != checkGNUnetDaemonRunning()) {
- gnunet_util_sleep(100 * cronMILLIS);
- if (timeout < cronTime(NULL))
- return checkGNUnetDaemonRunning();
- }
- return OK;
-}
-
-/**
- * Wait until the gnunet daemon (or any other CHILD process for that
- * matter) with the given PID has terminated. Assumes that
- * the daemon was started with startGNUnetDaemon in no-daemonize mode.
- * On arbitrary PIDs, this function may fail unexpectedly.
- *
- * @return YES if gnunetd shutdown with
- * return value 0, SYSERR if waitpid
- * failed, NO if gnunetd shutdown with
- * some error
- */
-int waitForGNUnetDaemonTermination(int pid) {
- pid_t p;
- int status;
-
- p = pid;
- if (p != WAITPID(p, &status, 0)) {
- LOG_STRERROR(LOG_ERROR, "waitpid");
- return SYSERR;
- }
- if (WEXITSTATUS(status) == 0)
- return YES;
- else
- return NO;
-}
-
-int termProcess(int pid) {
-#ifndef MINGW
- return kill(pid, SIGTERM) == 0;
-#else
- int ret;
- DWORD dwExitCode = 0;
-
- HANDLE hProc = OpenProcess(1, 0, pid);
- GenerateConsoleCtrlEvent(CTRL_C_EVENT, pid);
-
- WaitForSingleObject(hProc, 3000);
-
- GetExitCodeProcess(hProc, &dwExitCode);
- if(dwExitCode == STILL_ACTIVE) {
- ret = TerminateProcess(hProc, 0);
- }
- else
- ret = 1;
-
- CloseHandle(hProc);
-
- return ret;
-#endif
-}
-
-/* end of daemon.c */
Deleted: GNUnet/src/util/daemontest.c
===================================================================
--- GNUnet/src/util/daemontest.c 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/daemontest.c 2006-06-22 17:50:56 UTC (rev 3024)
@@ -1,61 +0,0 @@
-/*
- This file is part of GNUnet.
- (C) 2005 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 test/daemontest.c
- * @brief Testcase for the daemon functions
- * @author Christian Grothoff
- */
-
-#include "gnunet_util.h"
-#include "platform.h"
-static int parseCommandLine(int argc,
- char * argv[]) {
- FREENONNULL(setConfigurationString("GNUNETD",
- "_MAGIC_",
- "NO"));
- FREENONNULL(setConfigurationString("GNUNETD",
- "LOGFILE",
- NULL));
- FREENONNULL(setConfigurationString("GNUNET",
- "LOGLEVEL",
- "NOTHING"));
- FREENONNULL(setConfigurationString("GNUNET",
- "GNUNETD-CONFIG",
- "check.conf"));
- return OK;
-}
-
-int main(int argc, char *argv[]) {
- int daemon;
-
- if (OK != initUtil(argc,
- argv,
- &parseCommandLine))
- return -1;
- daemon = startGNUnetDaemon(NO);
- GNUNET_ASSERT(daemon > 0);
- GNUNET_ASSERT(OK == waitForGNUnetDaemonRunning(30 * cronSECONDS));
- GNUNET_ASSERT(OK == stopGNUnetDaemon());
- GNUNET_ASSERT(OK == waitForGNUnetDaemonTermination(daemon));
- doneUtil();
- return 0;
-}
-
-/* end of deamontest.c */
Added: GNUnet/src/util/disk/Makefile.am
===================================================================
--- GNUnet/src/util/disk/Makefile.am 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/disk/Makefile.am 2006-06-22 17:50:56 UTC (rev 3024)
@@ -0,0 +1,18 @@
+INCLUDES = -I$(top_srcdir)/src/include
+
+SUBDIRS = .
+
+noinst_LTLIBRARIES = \
+ libdisk.la
+
+libdisk_la_SOURCES = \
+ storage.c
+
+check_PROGRAMS = \
+ storagetest
+
+storagetest_SOURCES = \
+ storagetest.c
+storagetest_LDADD = \
+ $(top_builddir)/src/util/libgnunetutil.la
+
Added: GNUnet/src/util/disk/storage.c
===================================================================
--- GNUnet/src/util/disk/storage.c 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/disk/storage.c 2006-06-22 17:50:56 UTC (rev 3024)
@@ -0,0 +1,695 @@
+/*
+ This file is part of GNUnet.
+ (C) 2001, 2002, 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/disk/storage.c
+ * @brief disk IO convenience methods
+ * @author Christian Grothoff
+ */
+
+#include "platform.h"
+#include "gnunet_util_string.h"
+#include "gnunet_util_disk.h"
+
+
+
+#if LINUX || CYGWIN
+#include <sys/vfs.h>
+#else
+#ifdef SOMEBSD
+#include <sys/param.h>
+#include <sys/mount.h>
+#else
+#ifdef OSX
+#include <sys/param.h>
+#include <sys/mount.h>
+#else
+#ifdef SOLARIS
+#include <sys/types.h>
+#include <sys/statvfs.h>
+#else
+#ifdef MINGW
+#define _IFMT 0170000 /* type of file */
+#define _IFLNK 0120000 /* symbolic link */
+#define S_ISLNK(m) (((m)&_IFMT) == _IFLNK)
+#else
+#error PORT-ME: need to port statfs (how much space is left on the drive?)
+#endif
+#endif
+#endif
+#endif
+#endif
+
+#ifndef SOMEBSD
+ #ifndef WINDOWS
+ #ifndef OSX
+ #include <wordexp.h>
+ #endif
+ #endif
+#endif
+
+typedef struct {
+ struct GE_Context * ectx;
+ unsigned long long total;
+ int include_sym_links;
+} GetFileSizeData;
+
+static int getSizeRec(const char * filename,
+ const char * dirname,
+ void * ptr) {
+ GetFileSizeData * gfsd = ptr;
+#ifdef HAVE_STAT64
+ struct stat64 buf;
+#else
+ struct stat buf;
+#endif
+ char * fn;
+
+ GE_ASSERT(gfsd->ectx, filename != NULL);
+ if ( (dirname != NULL) &&
+ (strlen(dirname) > 0) ) {
+ fn = MALLOC(strlen(filename) + strlen(dirname) + 3);
+ if (strlen(dirname) > 0) {
+ strcpy(fn, dirname);
+ if (dirname[strlen(dirname)-1] != DIR_SEPARATOR)
+ strcat(fn, DIR_SEPARATOR_STR); /* add tailing / if needed */
+ }
+ /* Windows paths don't start with / */
+#ifndef MINGW
+ else
+ strcpy(fn, DIR_SEPARATOR_STR);
+#endif
+ if (filename[0] == DIR_SEPARATOR)
+ /* if filename starts with a "/", don't copy it */
+ strcat(fn, &filename[1]);
+ else
+ strcat(fn, filename);
+ } else
+ fn = STRDUP(filename);
+
+#ifdef HAVE_STAT64
+ if (0 != STAT64(fn, &buf)) {
+#else
+ if (0 != STAT(fn, &buf)) {
+#endif
+ GE_LOG_STRERROR_FILE(gfsd->ectx,
+ GE_WARNING | GE_USER | GE_REQUEST,
+ "stat",
+ fn);
+ FREE(fn);
+ return SYSERR;
+ }
+ if ( (! S_ISLNK(buf.st_mode)) ||
+ (gfsd->include_sym_links == YES) )
+ gfsd->total += buf.st_size;
+ if ( (S_ISDIR(buf.st_mode)) &&
+ ( (!S_ISLNK(buf.st_mode)) ||
+ (gfsd->include_sym_links == YES) ) ) {
+ if (SYSERR ==
+ disk_directory_scan(gfsd->ectx,
+ fn,
+ &getSizeRec,
+ gfsd)) {
+ FREE(fn);
+ return SYSERR;
+ }
+ }
+ FREE(fn);
+ return OK;
+}
+
+/**
+ * Get the size of the file (or directory)
+ * of the given file (in bytes).
+ *
+ * @return SYSERR on error, OK on success
+ */
+int disk_file_size(struct GE_Context * ectx,
+ const char * filename,
+ unsigned long long * size,
+ int includeSymLinks) {
+ GetFileSizeData gfsd;
+ int ret;
+
+ GE_ASSERT(ectx, size != NULL);
+ gfsd.ectx = ectx;
+ gfsd.total = 0;
+ gfsd.include_sym_links = includeSymLinks;
+ ret = getSizeRec(filename, "", &gfsd);
+ *size = gfsd.total;
+ return ret;
+}
+
+/**
+ * Get the number of blocks that are left on the partition that
+ * contains the given file (for normal users).
+ *
+ * @param part a file on the partition to check
+ * @return -1 on errors, otherwise the number of free blocks
+ */
+long disk_get_blocks_available(struct GE_Context * ectx,
+ const char * part) {
+#ifdef SOLARIS
+ struct statvfs buf;
+
+ if (0 != statvfs(part, &buf)) {
+ GE_LOG_STRERROR_FILE(ectx,
+ GE_WARNING | GE_USER | GE_ADMIN | GE_BULK,
+ "statfs",
+ part);
+ return -1;
+ }
+ return buf.f_bavail;
+#elif MINGW
+ DWORD dwDummy;
+ DWORD dwBlocks;
+ char szDrive[4];
+
+ memcpy(szDrive, part, 3);
+ szDrive[3] = 0;
+ if (!GetDiskFreeSpace(szDrive,
+ &dwDummy,
+ &dwDummy,
+ &dwBlocks,
+ &dwDummy)) {
+ GE_LOG(ectx,
+ GE_WARNING | GE_USER | GE_ADMIN | GE_BULK,
+ _("`%s' failed for drive `%s': %u\n"),
+ "GetDiskFreeSpace",
+ szDrive,
+ GetLastError());
+
+ return -1;
+ }
+ return dwBlocks;
+#else
+ struct statfs s;
+ if (0 != statfs(part, &s)) {
+ GE_LOG_STRERROR_FILE(ectx,
+ GE_WARNING | GE_USER | GE_ADMIN | GE_BULK,
+ "statfs",
+ part);
+ return -1;
+ }
+ return s.f_bavail;
+#endif
+}
+
+/**
+ * Test if fil is a directory.
+ *
+ * @return YES if yes, NO if not, SYSERR if it
+ * does not exist
+ */
+int disk_directory_test(struct GE_Context * ectx,
+ const char * fil) {
+ struct stat filestat;
+ int ret;
+
+ ret = STAT(fil, &filestat);
+ if (ret != 0) {
+ if (errno != ENOENT) {
+ GE_LOG_STRERROR_FILE(ectx,
+ GE_WARNING | GE_USER | GE_ADMIN | GE_REQUEST,
+ "stat",
+ fil);
+ return SYSERR;
+ }
+ return NO;
+ }
+ if (!S_ISDIR(filestat.st_mode)) {
+ GE_LOG(ectx,
+ GE_WARNING | GE_USER | GE_ADMIN | GE_REQUEST,
+ _("Expected `%s' to be a directory\n"),
+ fil);
+ return SYSERR;
+ }
+ if (ACCESS(fil, R_OK | X_OK) < 0 ) {
+ GE_LOG_STRERROR_FILE(ectx,
+ GE_WARNING | GE_USER | GE_ADMIN | GE_REQUEST,
+ "access",
+ fil);
+ return SYSERR;
+ }
+ return YES;
+}
+
+/**
+ * Assert that fil corresponds to a filename
+ * (of a file that exists and that is not a directory).
+ * @returns 1 if yes, 0 if not (will print an error
+ * message in that case, too).
+ */
+int disk_file_test(struct GE_Context * ectx,
+ const char * fil) {
+ struct stat filestat;
+ int ret;
+
+ ret = STAT(fil, &filestat);
+ if (ret != 0) {
+ if (errno != ENOENT) {
+ GE_LOG_STRERROR_FILE(ectx,
+ GE_WARNING | GE_USER | GE_ADMIN | GE_REQUEST,
+ "stat",
+ fil);
+ return SYSERR;
+ }
+ return NO;
+ }
+ if (!S_ISREG(filestat.st_mode)) {
+ GE_LOG(ectx,
+ GE_WARNING | GE_USER | GE_ADMIN | GE_REQUEST,
+ _("Expected `%s' to be a regular file\n"),
+ fil);
+ return SYSERR;
+ }
+ if (ACCESS(fil, R_OK) < 0 ) {
+ GE_LOG_STRERROR_FILE(ectx,
+ GE_WARNING | GE_USER | GE_ADMIN | GE_REQUEST,
+ "access",
+ fil);
+ return SYSERR;
+ }
+ return YES;
+}
+
+/**
+ * Implementation of "mkdir -p"
+ * @param dir the directory to create
+ * @returns OK on success, SYSERR on failure
+ */
+int disk_directory_create(struct GE_Context * ectx,
+ const char * dir) {
+ char * rdir;
+ int len;
+ int pos;
+ int ret = OK;
+
+ rdir = string_expandFileName(ectx,
+ dir);
+ if (rdir == NULL)
+ return SYSERR;
+ len = strlen(rdir);
+#ifndef MINGW
+ pos = 1; /* skip heading '/' */
+#else
+ /* Local or Network path? */
+ if (strncmp(rdir, "\\\\", 2) == 0) {
+ pos = 2;
+ while (rdir[pos]) {
+ if (rdir[pos] == '\\') {
+ pos++;
+ break;
+ }
+ pos++;
+ }
+ } else {
+ pos = 3; /* strlen("C:\\") */
+ }
+#endif
+ while (pos <= len) {
+ if ( (rdir[pos] == DIR_SEPARATOR) ||
+ (pos == len) ) {
+ rdir[pos] = '\0';
+ ret = disk_directory_test(ectx, rdir);
+ if (ret == SYSERR) {
+ FREE(rdir);
+ return SYSERR;
+ }
+ if (ret == NO) {
+#ifndef MINGW
+ ret = mkdir(rdir,
+ S_IRUSR | S_IWUSR |
+ S_IXUSR | S_IRGRP |
+ S_IXGRP | S_IROTH |
+ S_IXOTH); /* 755 */
+#else
+ ret = mkdir(rdir);
+#endif
+ if ( (ret != 0) &&
+ (errno != EEXIST) ) {
+ GE_LOG_STRERROR_FILE(ectx,
+ GE_ERROR | GE_USER | GE_BULK,
+ "mkdir",
+ rdir);
+ FREE(rdir);
+ return SYSERR;
+ }
+ rdir[pos] = DIR_SEPARATOR;
+ }
+ }
+ pos++;
+ }
+ FREE(rdir);
+ return ret;
+}
+
+/**
+ * Read the contents of a binary file into a buffer.
+ * @param fileName the name of the file, not freed,
+ * must already be expanded!
+ * @param len the maximum number of bytes to read
+ * @param result the buffer to write the result to
+ * @return the number of bytes read on success, -1 on failure
+ */
+int disk_file_read(struct GE_Context * ectx,
+ const char * fileName,
+ int len,
+ void * result) {
+ /* open file, must exist, open read only */
+ int handle;
+ int size;
+
+ GE_ASSERT(ectx, fileName != NULL);
+ if (len == 0)
+ return 0;
+ GE_ASSERT(ectx, result != NULL);
+ handle = disk_file_open(ectx,
+ fileName,
+ O_RDONLY,
+ S_IRUSR);
+ if (handle < 0)
+ return -1;
+ size = READ(handle, result, len);
+ disk_file_close(ectx, fileName, handle);
+ return size;
+}
+
+
+/**
+ * Convert string to value ('755' for chmod-call)
+ */
+static int atoo(const char *s) {
+ int n = 0;
+
+ while ( ('0' <= *s) && (*s < '8') ) {
+ n <<= 3;
+ n += *s++ - '0';
+ }
+ return n;
+}
+
+/**
+ * Write a buffer to a file.
+ * @param fileName the name of the file, NOT freed!
+ * @param buffer the data to write
+ * @param n number of bytes to write
+ * @param mode permissions to set on the file
+ * @return OK on success, SYSERR on error
+ */
+int disk_file_write(struct GE_Context * ectx,
+ const char * fileName,
+ const void * buffer,
+ unsigned int n,
+ const char * mode) {
+ int handle;
+
+ /* open file, open with 600, create if not
+ present, otherwise overwrite */
+ GE_ASSERT(ectx, fileName != NULL);
+
+ handle = disk_file_open(ectx,
+ fileName,
+ O_CREAT | O_WRONLY,
+ S_IRUSR | S_IWUSR);
+ if (handle == -1)
+ return SYSERR;
+ GE_ASSERT(ectx,
+ (n == 0) || (buffer != NULL));
+ /* write the buffer take length from the beginning */
+ if (n != WRITE(handle, buffer, n)) {
+ GE_LOG_STRERROR_FILE(ectx,
+ GE_WARNING | GE_USER | GE_IMMEDIATE,
+ "write",
+ fileName);
+ disk_file_close(ectx, fileName, handle);
+ return SYSERR;
+ }
+ disk_file_close(ectx, fileName, handle);
+ if (0 != CHMOD(fileName,
+ atoo(mode))) {
+ GE_LOG_STRERROR_FILE(ectx,
+ GE_WARNING | GE_USER | GE_BULK,
+ "chmod",
+ fileName);
+ }
+ return OK;
+}
+
+/**
+ * Scan a directory for files. The name of the directory
+ * must be expanded first (!).
+ * @param dirName the name of the directory
+ * @param callback the method to call for each file,
+ * can be NULL, in that case, we only count
+ * @param data argument to pass to callback
+ * @return the number of files found, SYSERR on error or
+ * ieration aborted by callback returning SYSERR
+ */
+int disk_directory_scan(struct GE_Context * ectx,
+ const char * dirName,
+ DirectoryEntryCallback callback,
+ void * data) {
+ DIR * dinfo;
+ struct dirent *finfo;
+ struct stat istat;
+ int count = 0;
+
+ GE_ASSERT(ectx, dirName != NULL);
+ if (0 != STAT(dirName, &istat)) {
+ GE_LOG_STRERROR_FILE(ectx,
+ GE_WARNING | GE_USER | GE_BULK,
+ "stat",
+ dirName);
+ return SYSERR;
+ }
+ if (!S_ISDIR(istat.st_mode)) {
+ GE_LOG(ectx,
+ GE_WARNING | GE_USER | GE_BULK,
+ _("expected `%s' to be a directory!\n"),
+ dirName);
+ return SYSERR;
+ }
+ errno = 0;
+ dinfo = OPENDIR(dirName);
+ if ( (errno == EACCES) || (dinfo == NULL)) {
+ GE_LOG_STRERROR_FILE(ectx,
+ GE_WARNING | GE_USER | GE_BULK,
+ "opendir",
+ dirName);
+ return SYSERR;
+ }
+ while ((finfo = readdir(dinfo)) != NULL) {
+ if (finfo->d_name[0] == '.')
+ continue;
+ if (callback != NULL) {
+ if (OK != callback(finfo->d_name,
+ dirName,
+ data)) {
+ closedir(dinfo);
+ return SYSERR;
+ }
+ }
+ count++;
+ }
+ closedir(dinfo);
+ return count;
+}
+
+/**
+ * Callback for disk_directory_remove
+ */
+static int rmHelper(const char * fil,
+ const char * dir,
+ void * ctx) {
+ struct GE_Context * ectx = ctx;
+ char * fn;
+ size_t n;
+
+ n = strlen(dir) + strlen(fil) + 2;
+ fn = MALLOC(n);
+ SNPRINTF(fn,
+ n,
+ "%s/%s",
+ dir,
+ fil);
+ if (SYSERR == disk_directory_remove(ectx,
+ fn)) {
+ FREE(fn);
+ return SYSERR;
+ }
+ FREE(fn);
+ return OK;
+}
+
+/**
+ * Remove all files in a directory (rm -rf). Call with
+ * caution.
+ *
+ *
+ * @param fileName the file to remove
+ * @return OK on success, SYSERR on error
+ */
+int disk_directory_remove(struct GE_Context * ectx,
+ const char * fileName) {
+ if (UNLINK(fileName) == 0)
+ return 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" */
+ (YES != disk_directory_test(ectx, fileName)) ) {
+ GE_LOG_STRERROR_FILE(ectx,
+ GE_WARNING | GE_USER | GE_ADMIN | GE_BULK,
+ "rmdir",
+ fileName);
+ return SYSERR;
+ }
+ if (SYSERR == disk_directory_scan(ectx,
+ fileName,
+ &rmHelper,
+ ectx))
+ return SYSERR;
+ if (0 != RMDIR(fileName)) {
+ GE_LOG_STRERROR_FILE(ectx,
+ GE_WARNING | GE_USER | GE_ADMIN | GE_BULK,
+ "rmdir",
+ fileName);
+ return SYSERR;
+ }
+ return OK;
+}
+
+void disk_file_close(struct GE_Context * ectx,
+ const char * filename,
+ int fd) {
+ if (0 != CLOSE(fd))
+ GE_LOG_STRERROR_FILE(ectx,
+ GE_WARNING | GE_USER | GE_BULK,
+ "close",
+ filename);
+}
+
+int disk_file_open(struct GE_Context * ectx,
+ const char * filename,
+ int oflag,
+ ...) {
+ const char * fn;
+ int mode;
+ int ret;
+#ifdef MINGW
+ char szFile[_MAX_PATH + 1];
+ long lRet;
+
+ if ((lRet = plibc_conv_to_win_path(filename,
+ szFile)) != ERROR_SUCCESS) {
+ errno = ENOENT;
+ SetLastError(lRet);
+ GE_LOG_STRERROR_FILE(ectx,
+ GE_WARNING | GE_USER | GE_DEVELOPER | GE_ADMIN |
GE_BULK,
+ "plibc_conv_to_win_path",
+ filename);
+ return -1;
+ }
+ fn = szFile;
+#else
+ fn = filename;
+#endif
+ if (oflag & O_CREAT) {
+ va_list arg;
+ va_start(arg, oflag);
+ mode = va_arg(arg, int);
+ va_end(arg);
+ } else {
+ mode = 0;
+ }
+#ifdef MINGW
+ /* set binary mode */
+ oflag |= O_BINARY;
+#endif
+ ret = open(fn, oflag, mode);
+ if (ret == -1)
+ GE_LOG_STRERROR_FILE(ectx,
+ GE_WARNING | GE_USER | GE_BULK,
+ "open",
+ filename);
+ return ret;
+}
+
+#define COPY_BLK_SIZE 65536
+
+/**
+ * Copy a file.
+ * @return OK on success, SYSERR on error
+ */
+int disk_file_copy(struct GE_Context * ectx,
+ const char * src,
+ const char * dst) {
+ char * buf;
+ unsigned long long pos;
+ unsigned long long size;
+ unsigned long long len;
+ int in;
+ int out;
+
+ if (OK != disk_file_size(ectx,
+ src,
+ &size,
+ YES))
+ return SYSERR;
+ pos = 0;
+ in = disk_file_open(ectx,
+ src,
+ O_RDONLY | O_LARGEFILE);
+ if (in == -1)
+ return SYSERR;
+ out = disk_file_open(ectx,
+ dst,
+ O_LARGEFILE | O_WRONLY | O_CREAT | O_EXCL,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
+ if (out == -1) {
+ disk_file_close(ectx,
+ src,
+ in);
+ return SYSERR;
+ }
+ buf = MALLOC(COPY_BLK_SIZE);
+ while (pos < size) {
+ len = COPY_BLK_SIZE;
+ if (len > size - pos)
+ len = size - pos;
+ if (len != READ(in, buf, len))
+ goto FAIL;
+ if (len != WRITE(out, buf, len))
+ goto FAIL;
+ pos += len;
+ }
+ FREE(buf);
+ disk_file_close(ectx, src, in);
+ disk_file_close(ectx, dst, out);
+ return OK;
+ FAIL:
+ FREE(buf);
+ disk_file_close(ectx, src, in);
+ disk_file_close(ectx, dst, out);
+ return SYSERR;
+}
+
+/* end of storage.c */
Added: GNUnet/src/util/disk/storagetest.c
===================================================================
--- GNUnet/src/util/disk/storagetest.c 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/disk/storagetest.c 2006-06-22 17:50:56 UTC (rev 3024)
@@ -0,0 +1,54 @@
+/**
+ * @file test/storagetest.c
+ * @brief testcase for the storage module
+ * @author Christian Grothoff
+ */
+
+#include "gnunet_util.h"
+#include "platform.h"
+
+#define TESTSTRING "Hello World\0"
+
+/**
+ * Perform option parsing from the command line.
+ */
+static int parseCommandLine(int argc,
+ char * argv[]) {
+ return OK;
+}
+
+static int testReadWrite() {
+ HashCode512 ha;
+ EncName filename;
+ char tmp[100];
+
+ hash(TESTSTRING,
+ strlen(TESTSTRING),
+ &ha);
+ hash2enc(&ha, &filename);
+ writeFile((char*)&filename, TESTSTRING, strlen(TESTSTRING), "644");
+ tmp[readFile((char*)&filename, 100, tmp)] = '\0';
+ if (memcmp(tmp,TESTSTRING,strlen(TESTSTRING)+1) == 0)
+ return 0;
+ else {
+ fprintf(stderr,
+ "Error in testReadWrite: *%s* != *%s* for file %s\n",
+ tmp,TESTSTRING,(char*)&filename);
+ return 1;
+ }
+}
+
+int main(int argc, char * argv[]) {
+ int failureCount = 0;
+
+ initUtil(argc, argv, &parseCommandLine);
+ failureCount += testReadWrite();
+ doneUtil();
+ if (failureCount == 0)
+ return 0;
+ else {
+ fprintf(stderr,
+ "\n\n%d TESTS FAILED!\n\n",failureCount);
+ return -1;
+ }
+} /* end of main */
Deleted: GNUnet/src/util/dso.c
===================================================================
--- GNUnet/src/util/dso.c 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/dso.c 2006-06-22 17:50:56 UTC (rev 3024)
@@ -1,160 +0,0 @@
-/*
- This file is part of GNUnet
- (C) 2002, 2003, 2004, 2005 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/dso.c
- * @brief Methods to access dynamic shared objects (DSOs).
- * @author Christian Grothoff
- */
-
-#include "platform.h"
-#include "gnunet_util.h"
-
-static int using_valgrind;
-
-static char * old_dlsearchpath = NULL;
-
-/* using libtool, needs init! */
-void __attribute__ ((constructor)) gnc_ltdl_init(void) {
- int err;
-
- err = lt_dlinit ();
- if (err > 0)
- {
-#if DEBUG
- fprintf(stderr,
- _("Initialization of plugin mechanism failed: %s!\n"),
- lt_dlerror());
-#endif
- return;
- }
- if (lt_dlgetsearchpath() != NULL)
- old_dlsearchpath = strdup(lt_dlgetsearchpath());
- if (lt_dlgetsearchpath () == NULL)
- lt_dladdsearchdir ("/usr/lib/GNUnet");
- else if (strstr (lt_dlgetsearchpath (), "/usr/lib/GNUnet") == NULL)
- lt_dladdsearchdir ("/usr/lib/GNUnet");
- if (strstr (lt_dlgetsearchpath (), "/usr/local/lib/GNUnet") == NULL)
- lt_dladdsearchdir ("/usr/local/lib/GNUnet");
-#ifdef PLUGIN_PATH
- if (strstr (lt_dlgetsearchpath (), PLUGIN_PATH) == NULL)
- lt_dladdsearchdir (PLUGIN_PATH);
-#endif
-}
-
-void __attribute__ ((destructor)) gnc_ltdl_fini(void) {
- lt_dlsetsearchpath(old_dlsearchpath);
- if (old_dlsearchpath != NULL) {
- free(old_dlsearchpath);
- old_dlsearchpath = NULL;
- }
- if (0 != using_valgrind)
- lt_dlexit ();
-}
-
-
-static char * buildLibName(const char * prefix,
- const char * dso) {
- char * libname;
-
- libname = MALLOC(strlen(dso) +
- strlen(prefix) + 1);
- libname[0] = '\0';
- strcat(libname, prefix);
- strcat(libname, dso);
- return libname;
-}
-
-void * loadDynamicLibrary(const char * libprefix,
- const char * dsoname) {
- void * libhandle;
- char * libname;
-
- if (0 != lt_dlinit())
- DIE_STRERROR("lt_dlinit");
- /* finally, load the library */
- libname = buildLibName(libprefix,
- dsoname);
- libhandle = lt_dlopenext(libname);
- if (libhandle == NULL) {
- LOG(LOG_ERROR,
- _("`%s' failed for library `%s' at %s:%d with error: %s\n"),
- "lt_dlopenext",
- libname,
- __FILE__, __LINE__,
- lt_dlerror());
- }
- FREE(libname);
- return libhandle;
-}
-
-void unloadDynamicLibrary(void * libhandle) {
- /* when valgrinding, comment out these lines
- to get decent traces for memory leaks on exit */
- if (0 != getConfigurationInt("GNUNETD",
- "VALGRIND")) {
- lt_dlclose(libhandle);
- if (0 != lt_dlexit())
- LOG_STRERROR(LOG_WARNING, "lt_dlexit");
- } else
- using_valgrind = 1;
-}
-
-void * trybindDynamicMethod(void * libhandle,
- const char * methodprefix,
- const char * dsoname) {
- char * initName;
- void * mptr;
-
- initName = MALLOC(strlen(dsoname) +
- strlen(methodprefix) + 2);
- initName[0] = '\0';
- strcat(initName, "_");
- strcat(initName, methodprefix);
- strcat(initName, dsoname);
- mptr = lt_dlsym(libhandle, &initName[1]);
- if (mptr == NULL) {
- /* try again with "_" prefix; some systems use that
- variant. */
- mptr = lt_dlsym(libhandle, initName);
- }
- FREE(initName);
- return mptr;
-}
-
-void * bindDynamicMethod(void * libhandle,
- const char * methodprefix,
- const char * dsoname) {
- void * mptr;
-
- mptr = trybindDynamicMethod(libhandle,
- methodprefix,
- dsoname);
- if (mptr == NULL)
- LOG(LOG_ERROR,
- _("`%s' failed to resolve method '%s%s' at %s:%d with error: %s\n"),
- "lt_dlsym",
- methodprefix, dsoname,
- __FILE__, __LINE__,
- lt_dlerror());
- return mptr;
-}
-
-/* end of dso.c */
Deleted: GNUnet/src/util/endian.c
===================================================================
--- GNUnet/src/util/endian.c 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/endian.c 2006-06-22 17:50:56 UTC (rev 3024)
@@ -1,48 +0,0 @@
-/*
- This file is part of GNUnet.
- (C) 2001, 2002, 2003, 2004, 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/endian.c
- * @brief endian conversion helpers
- * @author Christian Grothoff
- */
-
-#include "platform.h"
-#include "gnunet_util.h"
-
-unsigned long long ntohll(unsigned long long n) {
-#if __BYTE_ORDER == __BIG_ENDIAN
- return n;
-#else
- return (((unsigned long long)ntohl(n)) << 32) + ntohl(n >> 32);
-#endif
-}
-
-unsigned long long htonll(unsigned long long n) {
-#if __BYTE_ORDER == __BIG_ENDIAN
- return n;
-#else
- return (((unsigned long long)htonl(n)) << 32) + htonl(n >> 32);
-#endif
-}
-
-
-
-/* end of endian.c */
Modified: GNUnet/src/util/getopt/Makefile
===================================================================
--- GNUnet/src/util/getopt/Makefile 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/getopt/Makefile 2006-06-22 17:50:56 UTC (rev 3024)
@@ -14,7 +14,7 @@
-SOURCES = $(liberror_la_SOURCES)
+SOURCES = $(libgetopt_la_SOURCES)
srcdir = .
top_srcdir = ../../..
@@ -54,13 +54,17 @@
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
LTLIBRARIES = $(noinst_LTLIBRARIES)
-liberror_la_LIBADD =
-am_liberror_la_OBJECTS = error.lo
-liberror_la_OBJECTS = $(am_liberror_la_OBJECTS)
+libgetopt_la_LIBADD =
+am_libgetopt_la_OBJECTS = getopt.lo setoption.lo printhelp.lo \
+ printversion.lo
+libgetopt_la_OBJECTS = $(am_libgetopt_la_OBJECTS)
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
-DEP_FILES = ./$(DEPDIR)/error.Plo
+DEP_FILES = ./$(DEPDIR)/getopt.Plo \
+ ./$(DEPDIR)/printhelp.Plo \
+ ./$(DEPDIR)/printversion.Plo \
+ ./$(DEPDIR)/setoption.Plo
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) \
@@ -69,8 +73,8 @@
CCLD = $(CC)
LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(AM_LDFLAGS) $(LDFLAGS) -o $@
-SOURCES = $(liberror_la_SOURCES)
-DIST_SOURCES = $(liberror_la_SOURCES)
+SOURCES = $(libgetopt_la_SOURCES)
+DIST_SOURCES = $(libgetopt_la_SOURCES)
RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
html-recursive info-recursive install-data-recursive \
install-exec-recursive install-info-recursive \
@@ -248,10 +252,13 @@
INCLUDES = -I$(top_srcdir)/src/include
SUBDIRS = .
noinst_LTLIBRARIES = \
- liberror.la
+ libgetopt.la
-liberror_la_SOURCES = \
- error.c
+libgetopt_la_SOURCES = \
+ getopt.c \
+ setoption.c \
+ printhelp.c \
+ printversion.c
all: all-recursive
@@ -295,8 +302,8 @@
echo "rm -f \"$${dir}/so_locations\""; \
rm -f "$${dir}/so_locations"; \
done
-liberror.la: $(liberror_la_OBJECTS) $(liberror_la_DEPENDENCIES)
- $(LINK) $(liberror_la_LDFLAGS) $(liberror_la_OBJECTS)
$(liberror_la_LIBADD) $(LIBS)
+libgetopt.la: $(libgetopt_la_OBJECTS) $(libgetopt_la_DEPENDENCIES)
+ $(LINK) $(libgetopt_la_LDFLAGS) $(libgetopt_la_OBJECTS)
$(libgetopt_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
@@ -304,7 +311,10 @@
distclean-compile:
-rm -f *.tab.c
-include ./$(DEPDIR)/error.Plo
+include ./$(DEPDIR)/getopt.Plo
+include ./$(DEPDIR)/printhelp.Plo
+include ./$(DEPDIR)/printversion.Plo
+include ./$(DEPDIR)/setoption.Plo
.c.o:
if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
Modified: GNUnet/src/util/getopt/Makefile.in
===================================================================
--- GNUnet/src/util/getopt/Makefile.in 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/getopt/Makefile.in 2006-06-22 17:50:56 UTC (rev 3024)
@@ -14,7 +14,7 @@
@SET_MAKE@
-SOURCES = $(liberror_la_SOURCES)
+SOURCES = $(libgetopt_la_SOURCES)
srcdir = @srcdir@
top_srcdir = @top_srcdir@
@@ -54,13 +54,17 @@
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
LTLIBRARIES = $(noinst_LTLIBRARIES)
-liberror_la_LIBADD =
-am_liberror_la_OBJECTS = error.lo
-liberror_la_OBJECTS = $(am_liberror_la_OBJECTS)
+libgetopt_la_LIBADD =
+am_libgetopt_la_OBJECTS = getopt.lo setoption.lo printhelp.lo \
+ printversion.lo
+libgetopt_la_OBJECTS = $(am_libgetopt_la_OBJECTS)
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
address@hidden@DEP_FILES = ./$(DEPDIR)/error.Plo
address@hidden@DEP_FILES = ./$(DEPDIR)/getopt.Plo \
address@hidden@ ./$(DEPDIR)/printhelp.Plo \
address@hidden@ ./$(DEPDIR)/printversion.Plo \
address@hidden@ ./$(DEPDIR)/setoption.Plo
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) \
@@ -69,8 +73,8 @@
CCLD = $(CC)
LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(AM_LDFLAGS) $(LDFLAGS) -o $@
-SOURCES = $(liberror_la_SOURCES)
-DIST_SOURCES = $(liberror_la_SOURCES)
+SOURCES = $(libgetopt_la_SOURCES)
+DIST_SOURCES = $(libgetopt_la_SOURCES)
RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
html-recursive info-recursive install-data-recursive \
install-exec-recursive install-info-recursive \
@@ -248,10 +252,13 @@
INCLUDES = -I$(top_srcdir)/src/include
SUBDIRS = .
noinst_LTLIBRARIES = \
- liberror.la
+ libgetopt.la
-liberror_la_SOURCES = \
- error.c
+libgetopt_la_SOURCES = \
+ getopt.c \
+ setoption.c \
+ printhelp.c \
+ printversion.c
all: all-recursive
@@ -295,8 +302,8 @@
echo "rm -f \"$${dir}/so_locations\""; \
rm -f "$${dir}/so_locations"; \
done
-liberror.la: $(liberror_la_OBJECTS) $(liberror_la_DEPENDENCIES)
- $(LINK) $(liberror_la_LDFLAGS) $(liberror_la_OBJECTS)
$(liberror_la_LIBADD) $(LIBS)
+libgetopt.la: $(libgetopt_la_OBJECTS) $(libgetopt_la_DEPENDENCIES)
+ $(LINK) $(libgetopt_la_LDFLAGS) $(libgetopt_la_OBJECTS)
$(libgetopt_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
@@ -304,7 +311,10 @@
distclean-compile:
-rm -f *.tab.c
address@hidden@@am__include@ @address@hidden/$(DEPDIR)/address@hidden@
address@hidden@@am__include@ @address@hidden/$(DEPDIR)/address@hidden@
address@hidden@@am__include@ @address@hidden/$(DEPDIR)/address@hidden@
address@hidden@@am__include@ @address@hidden/$(DEPDIR)/address@hidden@
address@hidden@@am__include@ @address@hidden/$(DEPDIR)/address@hidden@
.c.o:
@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c
-o $@ $<; \
Modified: GNUnet/src/util/getopt/getopt.c
===================================================================
--- GNUnet/src/util/getopt/getopt.c 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/getopt/getopt.c 2006-06-22 17:50:56 UTC (rev 3024)
@@ -32,8 +32,14 @@
/**
* @file util/getopt/getopt.c
* @brief GNU style option parsing
+ *
+ * TODO: get rid of statics (make reentrant) and
+ * replace main GNU getopt parser with one that
+ * actually fits our API.
*/
+#include "gnunet_util_error.h"
+#include "gnunet_util_string.h"
#include "gnunet_util_getopt.h"
#include "platform.h"
@@ -147,7 +153,7 @@
If this is zero, or a null string, it means resume the scan
by advancing to the next ARGV-element. */
-static static char *nextchar;
+static char *nextchar;
/* Callers store zero here to inhibit the error message
for unrecognized options. */
@@ -966,25 +972,22 @@
}
}
-
static int
-GNgetopt_long (argc, argv, options, long_options, opt_index)
- int argc;
- char *const *argv;
- const char *options;
- const struct GNoption *long_options;
- int *opt_index;
-{
- return GN_getopt_internal (argc, argv, options, long_options, opt_index, 0);
+GNgetopt_long(int argc,
+ const char ** argv,
+ const char * options,
+ const struct GNoption * long_options,
+ int * opt_index) {
+ return GN_getopt_internal(argc,
+ argv,
+ options,
+ long_options,
+ opt_index,
+ 0);
}
-
/* ******************** now the GNUnet specific modifications...
********************* */
-
-
-
-
/**
* Parse the command line.
*
@@ -994,8 +997,8 @@
* @param allOptions defined options and handlers
* @param argc number of arguments
* @param argv actual arguments
- * @return OK on success, SYSERR on error (bad options
- * or command line handlers signal abort).
+ * @return index into argv with first non-option
+ * argument, or -1 on error
*/
int gnunet_parse_options(const char * binaryName,
struct GE_Context * ectx,
@@ -1004,12 +1007,21 @@
unsigned int argc,
const char ** argv) {
struct GNoption * long_options;
+ CommandLineProcessorContext clpc;
int count;
int i;
char * shorts;
int spos;
int cont;
+ int c;
+ GE_ASSERT(ectx, argc > 0);
+ clpc.binaryName = argv[0];
+ clpc.allOptions = allOptions;
+ clpc.argv = argv;
+ clpc.argc = argc;
+ clpc.ectx = ectx;
+ clpc.cfg = cfg;
count = 0;
while (allOptions[count].name != NULL)
count++;
@@ -1041,12 +1053,13 @@
long_options,
&option_index);
- if (c == -1)
+ if (c == SYSERR)
break; /* No more flags to process */
for (i=0;i<count;i++) {
- if (c == allOptions[i].shortName) {
- cont = allOptions[i].processor(mctx,
+ clpc.currentArgument = GNoptind - 1;
+ if ((char)c == allOptions[i].shortName) {
+ cont = allOptions[i].processor(&clpc,
allOptions[i].scls,
allOptions[i].name,
GNoptarg);
@@ -1055,7 +1068,7 @@
}
if (i == count) {
GE_LOG(ectx,
- LOG_FAILURE | GE_USER | GE_IMMEDIATE,
+ GE_INFO | GE_USER | GE_IMMEDIATE,
_("Use --help to get a list of options.\n"));
cont = SYSERR;
}
@@ -1063,29 +1076,7 @@
FREE(shorts);
FREE(long_options);
-
- if (GNoptind < argc) {
- LOG(LOG_WARNING,
- _("Invalid command-line arguments:\n"));
- while (GNoptind < argc) {
- LOG(LOG_WARNING,
- _("Argument %d: `%s'\n"),
- GNoptind+1,
- argv[GNoptind]);
- GNoptind++;
- }
- LOG(LOG_FATAL,
- _("Invalid command-line arguments.\n"));
- return SYSERR;
- }
-
+ return GNoptind;
}
-
-
-
-
-
-
-
/* end of getopt.c */
Modified: GNUnet/src/util/getopt/printhelp.c
===================================================================
--- GNUnet/src/util/getopt/printhelp.c 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/getopt/printhelp.c 2006-06-22 17:50:56 UTC (rev 3024)
@@ -42,7 +42,7 @@
int p;
char * scp;
const char * trans;
- struct CommandLineOption * opt;
+ const struct CommandLineOption * opt;
printf("%s",
gettext(about));
@@ -55,7 +55,7 @@
printf(" ");
else
printf(" -%c, ",
- opt[i].shortArg);
+ opt[i].shortName);
printf("--%s",
opt[i].name);
slen = 8 + strlen(opt[i].name);
Modified: GNUnet/src/util/getopt/setoption.c
===================================================================
--- GNUnet/src/util/getopt/setoption.c 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/getopt/setoption.c 2006-06-22 17:50:56 UTC (rev 3024)
@@ -32,7 +32,7 @@
int gnunet_getopt_configure_set_option(CommandLineProcessorContext * ctx,
void * scls,
- const char * option,
+ const char * cmdLineOption,
const char * value) {
char * section = STRDUP(scls);
struct GC_Configuration * cfg = ctx->cfg;
@@ -55,7 +55,7 @@
int gnunet_getopt_configure_increment_value(CommandLineProcessorContext * ctx,
void * scls,
- const char * option,
+ const char * cmdLineOption,
const char * value) {
char * section = STRDUP(scls);
struct GC_Configuration * cfg = ctx->cfg;
Deleted: GNUnet/src/util/io.c
===================================================================
--- GNUnet/src/util/io.c 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/io.c 2006-06-22 17:50:56 UTC (rev 3024)
@@ -1,359 +0,0 @@
-/*
- This file is part of GNUnet.
- (C) 2003 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/io.c
- * @brief (network) input/output operations
- * @author Christian Grothoff
- */
-
-#include "gnunet_util.h"
-#include "platform.h"
-
-/* some systems send us signals, so we'd better
- catch them (& ignore) */
-#ifndef LINUX
-static void catcher(int sig) {
- LOG(LOG_INFO,
- _("Caught signal %d.\n"),
- sig);
- /* re-install signal handler! */
- signal(sig, catcher);
-}
-
-
-#endif
-
-void gnunet_util_initIO() {
-#if ! (defined(LINUX) || defined(MINGW))
- if ( SIG_ERR == signal(SIGPIPE, SIG_IGN))
- if ( SIG_ERR == signal(SIGPIPE, catcher))
- LOG_STRERROR(LOG_WARNING, "signal");
-#endif
-}
-
-void gnunet_util_doneIO() {
-}
-
-/**
- * Depending on doBlock, enable or disable the nonblocking mode
- * of socket s.
- *
- * @param doBlock use YES to change the socket to blocking, NO to non-blocking
- * @return Upon successful completion, it returns zero, otherwise -1
- */
-int setBlocking(int s, int doBlock) {
-#if MINGW
- u_long l = !doBlock;
- if (ioctlsocket(s, FIONBIO, &l) == SOCKET_ERROR) {
- SetErrnoFromWinsockError(WSAGetLastError());
-
- return -1;
- } else {
- /* store the blocking mode */
- __win_SetHandleBlockingMode(s, doBlock);
- return 0;
- }
-#else
- int flags = fcntl(s, F_GETFL);
- if (doBlock)
- flags &= ~O_NONBLOCK;
- else
- flags |= O_NONBLOCK;
-
- return fcntl(s,
- F_SETFL,
- flags);
-#endif
-}
-
-/**
- * Check whether the socket is blocking
- * @param s the socket
- * @return YES if blocking, NO non-blocking
- */
-int isSocketBlocking(int s)
-{
-#ifndef MINGW
- return (fcntl(s, F_GETFL) & O_NONBLOCK) ? NO : YES;
-#else
- return __win_IsHandleMarkedAsBlocking(s);
-#endif
-}
-
-/* recv wrappers */
-
-/**
- * Do a NONBLOCKING read on the given socket. Note that in order to
- * avoid blocking, the caller MUST have done a select call before
- * calling this function. Though the caller must be prepared to the
- * fact that this function may fail with EWOULDBLOCK in any case (Win32).
- *
- * @brief Reads at most max bytes to buf. Interrupts are IGNORED.
- * @param s socket
- * @param buf buffer
- * @param max maximum number of bytes to read
- * @param read number of bytes actually read.
- * 0 is returned if no more bytes can be read
- * @return SYSERR on error, YES on success or NO if the operation
- * would have blocked
- */
-int RECV_NONBLOCKING(int s,
- void * buf,
- size_t max,
- size_t *read) {
- int flags;
-
- setBlocking(s, NO);
-
-#ifdef CYGWIN
- flags = MSG_NOSIGNAL;
-#elif OSX
- flags = 0;
-#elif SOMEBSD || SOLARIS
- flags = MSG_DONTWAIT;
-#elif LINUX
- flags = MSG_DONTWAIT | MSG_NOSIGNAL;
-#else
- /* good luck */
- flags = 0;
-#endif
-
- do {
- *read = (size_t) RECV(s,
- buf,
- max,
- flags);
- } while ( ( *read == -1) && ( errno == EINTR) );
-
- setBlocking(s, YES);
-
- if (*read == SYSERR && (errno == EWOULDBLOCK || errno == EAGAIN))
- return NO;
- else if ( (*read < 0) || (*read > max) )
- return SYSERR;
-
- return YES;
-}
-
-/**
- * Do a BLOCKING read on the given socket. Read len bytes (if needed
- * try multiple reads). Interrupts are ignored.
- *
- * @return SYSERR if len bytes could not be read,
- * otherwise the number of bytes read (must be len)
- */
-int RECV_BLOCKING_ALL(int s,
- void * buf,
- size_t len) {
- size_t pos;
- int i, flags;
-
- pos = 0;
- setBlocking(s, YES);
-
- while (pos < len) {
-#if LINUX || CYGWIN
- flags = MSG_NOSIGNAL;
-#else
- flags = 0;
-#endif
-
- i = RECV(s,
- &((char*)buf)[pos],
- len - pos,
- flags);
-
- if ( (i == -1) && (errno == EINTR) )
- continue;
- if (i <= 0)
- {
- setBlocking(s, NO);
- return SYSERR;
- }
- pos += i;
- }
- GNUNET_ASSERT(pos == len);
-
- setBlocking(s, NO);
-
- return pos;
-}
-
-/**
- * Do a NONBLOCKING write on the given socket.
- * Write at most max bytes from buf.
- * Interrupts are ignored (cause a re-try).
- *
- * The caller must be prepared to the fact that this function
- * may fail with EWOULDBLOCK in any case (Win32).
- *
- * @param s socket
- * @param buf buffer to send
- * @param max maximum number of bytes to send
- * @param sent number of bytes actually sent
- * @return SYSERR on error, YES on success or
- * NO if the operation would have blocked.
- */
-int SEND_NONBLOCKING(int s,
- const void * buf,
- size_t max,
- size_t * sent) {
- int flags;
-
- setBlocking(s, NO);
-
-#ifdef SOMEBSD
- flags = MSG_DONTWAIT;
-#elif SOLARIS
- flags = MSG_DONTWAIT;
-#elif OSX
- /* As braindead as Win32? */
- flags = 0;
-#elif CYGWIN
- flags = MSG_NOSIGNAL;
-#elif LINUX
- flags = MSG_DONTWAIT | MSG_NOSIGNAL;
-#else
- /* pray */
- flags = 0;
-#endif
-
- do {
- *sent = (size_t) SEND(s,
- buf,
- max,
- flags);
-
- } while ( (*sent == -1) &&
- (errno == EINTR) );
-
- setBlocking(s, YES);
-
- if (*sent == SYSERR && (errno == EWOULDBLOCK || errno == EAGAIN))
- return NO;
- else if ( (*sent < 0) || (*sent > max) )
- return SYSERR;
-
- return YES;
-}
-
-/**
- * Do a BLOCKING write on the given socket. Write len bytes (if
- * needed do multiple write). Interrupts are ignored (cause a
- * re-try).
- *
- * @return SYSERR if len bytes could not be send,
- * otherwise the number of bytes transmitted (must be len)
- */
-int SEND_BLOCKING_ALL(int s,
- const void * buf,
- size_t len) {
- size_t pos;
- int i, flags;
-
- pos = 0;
- setBlocking(s, YES);
- while (pos < len) {
-#if CYGWIN || LINUX
- flags = MSG_NOSIGNAL;
-#else
- flags = 0;
-#endif
- i = SEND(s,
- &((char*)buf)[pos],
- len - pos,
- flags);
-
- if ( (i == -1) &&
- (errno == EINTR) )
- continue; /* ingnore interrupts */
- if (i <= 0) {
- if (i == -1)
- LOG_STRERROR(LOG_WARNING, "send");
- return SYSERR;
- }
- pos += i;
- }
- setBlocking(s, NO);
- GNUNET_ASSERT(pos == len);
- return pos;
-}
-
-/**
- * Check if socket is valid
- * @return 1 if valid, 0 otherwise
- */
-int isSocketValid(int s)
-{
-#ifndef MINGW
- struct stat buf;
- return -1 != fstat(s, &buf);
-#else
- long l;
- return ioctlsocket(s, FIONREAD, &l) != SOCKET_ERROR;
-#endif
-}
-
-/**
- * Open a file
- */
-int fileopen(const char *filename, int oflag, ...)
-{
- int mode;
- char *fn;
-
-#ifdef MINGW
- char szFile[_MAX_PATH + 1];
- long lRet;
-
- if ((lRet = plibc_conv_to_win_path(filename, szFile)) != ERROR_SUCCESS)
- {
- errno = ENOENT;
- SetLastError(lRet);
-
- return -1;
- }
- fn = szFile;
-#else
- fn = (char *) filename;
-#endif
-
- if (oflag & O_CREAT)
- {
- va_list arg;
- va_start(arg, oflag);
- mode = va_arg(arg, int);
- va_end(arg);
- }
- else
- {
- mode = 0;
- }
-
-#ifdef MINGW
- /* Set binary mode */
- oflag |= O_BINARY;
-#endif
-
- return open(fn, oflag, mode);
-}
-
-/* end of io.c */
Deleted: GNUnet/src/util/ipcheck.c
===================================================================
--- GNUnet/src/util/ipcheck.c 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/ipcheck.c 2006-06-22 17:50:56 UTC (rev 3024)
@@ -1,325 +0,0 @@
-/*
- This file is part of GNUnet.
- (C) 2001, 2002, 2003, 2004 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/ipcheck.c
- * @brief test if an IP matches a given subnet
- * @author Christian Grothoff
- */
-
-#include "gnunet_util.h"
-#include "platform.h"
-
-/**
- * @brief IPV4 network in CIDR notation.
- */
-typedef struct CIDRNetwork {
- IPaddr network;
- IPaddr netmask;
-} CIDRNetwork;
-
-/**
- * @brief network in CIDR notation for IPV6.
- */
-typedef struct CIDR6Network {
- IP6addr network;
- IP6addr netmask;
-} CIDR6Network;
-
-
-/**
- * Parse a network specification. The argument specifies
- * a list of networks. The format is
- * <tt>[network/netmask;]*</tt> (no whitespace, must be terminated
- * with a semicolon). The network must be given in dotted-decimal
- * notation. The netmask can be given in CIDR notation (/16) or
- * in dotted-decimal (/255.255.0.0).
- * <p>
- * @param routeList a string specifying the forbidden networks
- * @return the converted list, NULL if the synatx is flawed
- */
-CIDRNetwork * parseRoutes(const char * routeList) {
- unsigned int count;
- unsigned int i;
- unsigned int j;
- unsigned int len;
- int cnt;
- unsigned int pos;
- unsigned int temps[8];
- int slash;
- CIDRNetwork * result;
-
- if (routeList == NULL)
- return NULL;
- len = strlen(routeList);
- if (len == 0)
- return NULL;
- count = 0;
- for (i=0;i<len;i++)
- if (routeList[i] == ';')
- count++;
- result = MALLOC(sizeof(CIDRNetwork) * (count+1));
- /* add termination */
- memset(result,
- 0,
- sizeof(CIDRNetwork)*(count+1));
- i=0;
- pos = 0;
- while (i < count) {
- cnt = sscanf(&routeList[pos],
- "%u.%u.%u.%u/%u.%u.%u.%u;",
- &temps[0],
- &temps[1],
- &temps[2],
- &temps[3],
- &temps[4],
- &temps[5],
- &temps[6],
- &temps[7]);
- if (cnt == 8) {
- for (j=0;j<8;j++)
- if (temps[j] > 0xFF) {
- LOG(LOG_ERROR,
- _("Invalid format for IP: `%s'\n"),
- &routeList[pos]);
- FREE(result);
- return NULL;
- }
- result[i].network.addr
- = htonl((temps[0] << 24) + (temps[1] << 16) + (temps[2] << 8) +
temps[3]);
- result[i].netmask.addr
- = htonl((temps[4] << 24) + (temps[5] << 16) + (temps[6] << 8) +
temps[7]);
- while (routeList[pos] != ';')
- pos++;
- pos++;
- i++;
- continue;
- }
- /* try second notation */
- cnt = sscanf(&routeList[pos],
- "%u.%u.%u.%u/%u;",
- &temps[0],
- &temps[1],
- &temps[2],
- &temps[3],
- &slash);
- if (cnt == 5) {
- for (j=0;j<4;j++)
- if (temps[j] > 0xFF) {
- LOG(LOG_ERROR,
- "wrong format for IP: %s\n",
- &routeList[pos]);
- FREE(result);
- return NULL;
- }
- result[i].network.addr
- = htonl((temps[0] << 24) + (temps[1] << 16) + (temps[2] << 8) +
temps[3]);
- if ( (slash <= 32) && (slash > 0) ) {
- result[i].netmask.addr = 0;
- while (slash > 0) {
- result[i].netmask.addr
- = (result[i].netmask.addr >> 1) + 0x80000000;
- slash--;
- }
- result[i].netmask.addr
- = htonl(result[i].netmask.addr);
- while (routeList[pos] != ';')
- pos++;
- pos++;
- i++;
- continue;
- } else {
- LOG(LOG_ERROR,
- _("Invalid network notation ('/%d' is not legal in IPv4 CIDR)."),
- slash);
- FREE(result);
- return NULL; /* error */
- }
- }
- LOG(LOG_ERROR,
- "invalid network notation: >>%s<<",
- &routeList[pos]);
- FREE(result);
- return NULL; /* error */
- }
- if (pos < strlen(routeList)) {
- LOG(LOG_ERROR,
- _("Invalid network notation (additional characters: `%s')."),
- &routeList[pos]);
- FREE(result);
- return NULL; /* oops */
- }
- return result; /* ok */
-}
-
-
-
-/**
- * Check if the given IP address is in the list of IP addresses.
- *
- * @param list a list of networks
- * @param ip the IP to check (in network byte order)
- * @return NO if the IP is not in the list, YES if it it is
- */
-int checkIPListed(const CIDRNetwork * list,
- IPaddr ip) {
- int i;
- IPaddr add;
-
- add = ip;
- i=0;
- if (list == NULL)
- return NO;
-
- while ( (list[i].network.addr != 0) ||
- (list[i].netmask.addr != 0) ) {
- if ( (add.addr & list[i].netmask.addr) ==
- (list[i].network.addr & list[i].netmask.addr) )
- return YES;
- i++;
- }
- return NO;
-}
-
-/**
- * Parse a network specification. The argument specifies
- * a list of networks. The format is
- * <tt>[network/netmask;]*</tt> (no whitespace, must be terminated
- * with a semicolon). The network must be given in colon-hex
- * notation. The netmask must be given in CIDR notation (/16) or
- * can be omitted to specify a single host.
- * <p>
- * @param routeList a string specifying the forbidden networks
- * @return the converted list, NULL if the synatx is flawed
- */
-CIDR6Network * parseRoutes6(const char * routeListX) {
- unsigned int count;
- unsigned int i;
- unsigned int len;
- unsigned int pos;
- int start;
- int slash;
- int ret;
- char * routeList;
- CIDR6Network * result;
-
- if (routeListX == NULL)
- return NULL;
- len = strlen(routeListX);
- if (len == 0)
- return NULL;
- routeList = STRDUP(routeListX);
- count = 0;
- for (i=0;i<len;i++)
- if (routeList[i] == ';')
- count++;
- if (routeList[len-1] != ';') {
- LOG(LOG_ERROR,
- _("Invalid network notation (does not end with ';': `%s')\n"),
- routeList);
- FREE(routeList);
- return NULL;
- }
-
- result = MALLOC(sizeof(CIDR6Network) * (count+1));
- memset(result,
- 0,
- sizeof(CIDR6Network) * (count+1));
- i=0;
- pos = 0;
- while (i < count) {
- start = pos;
- while (routeList[pos] != ';')
- pos++;
- slash = pos;
- while ( (slash >= start) &&
- (routeList[slash] != '/') )
- slash--;
- if (slash < start) {
- memset(&result[i].netmask,
- 0xFF,
- sizeof(IP6addr));
- slash = pos;
- } else {
- routeList[pos] = '\0';
- ret = inet_pton(AF_INET6,
- &routeList[slash+1],
- &result[i].netmask);
- if (ret <= 0) {
- LOG(LOG_ERROR,
- _("Wrong format `%s' for netmask: %s\n"),
- &routeList[slash+1],
- STRERROR(errno));
- FREE(result);
- FREE(routeList);
- return NULL;
- }
- }
- routeList[slash] = '\0';
- ret = inet_pton(AF_INET6,
- &routeList[start],
- &result[i].network);
- if (ret <= 0) {
- LOG(LOG_ERROR,
- _("Wrong format `%s' for network: %s\n"),
- &routeList[slash+1],
- STRERROR(errno));
- FREE(result);
- FREE(routeList);
- return NULL;
- }
- pos++;
- }
- FREE(routeList);
- return result;
-}
-
-/**
- * Check if the given IP address is in the list of IP addresses.
- *
- * @param list a list of networks
- * @param ip the IP to check (in network byte order)
- * @return NO if the IP is not in the list, YES if it it is
- */
-int checkIP6Listed(const CIDR6Network * list,
- const IP6addr * ip) {
- unsigned int i;
- unsigned int j;
- struct in6_addr zero;
-
- i=0;
- if (list == NULL)
- return NO;
-
- memset(&zero, 0, sizeof(struct in6_addr));
- while ( (memcmp(&zero, &list[i].network, sizeof(struct in6_addr)) != 0) ||
- (memcmp(&zero, &list[i].netmask, sizeof(struct in6_addr)) != 0) ) {
- for (j=0;j<sizeof(struct in6_addr)/sizeof(int);j++)
- if ( ((((int*)ip)[j] & ((int*)&list[i].netmask)[j])) !=
- (((int*)&list[i].network)[j] & ((int*)&list[i].netmask)[j]) ) {
- i++;
- continue;
- }
- return YES;
- }
- return NO;
-}
-
-/* end of ipcheck.c */
Modified: GNUnet/src/util/loggers/file.c
===================================================================
--- GNUnet/src/util/loggers/file.c 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/loggers/file.c 2006-06-22 17:50:56 UTC (rev 3024)
@@ -249,6 +249,7 @@
FREENONNULL(fctx->filename);
FREENONNULL(fctx->basename);
if ( (fctx->handle != stderr) &&
+ (fctx->handle != stdout) &&
(0 != fclose(fctx->handle)) )
GE_LOG_STRERROR(fctx->ectx,
GE_ERROR | GE_USER | GE_ADMIN | GE_IMMEDIATE | GE_BULK,
@@ -332,3 +333,29 @@
&fileclose);
}
+
+/**
+ * Create a logger that writes events to stderr
+ *
+ * @param mask which events should be logged?
+ */
+struct GE_Context *
+GE_create_context_stdout(int logDate,
+ GE_KIND mask) {
+ FileContext * fctx;
+
+ fctx = MALLOC(sizeof(FileContext));
+ fctx->ectx = NULL;
+ fctx->logdate = logDate;
+ fctx->logrotate = 0;
+ fctx->handle = stdout;
+ fctx->filename = NULL;
+ fctx->basename = NULL;
+ fctx->logstart = 0;
+ MUTEX_CREATE_RECURSIVE(&fctx->lock);
+ return GE_create_context_callback(mask,
+ &filelogger,
+ fctx,
+ &fileclose);
+
+}
Added: GNUnet/src/util/network/Makefile.am
===================================================================
--- GNUnet/src/util/network/Makefile.am 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/network/Makefile.am 2006-06-22 17:50:56 UTC (rev 3024)
@@ -0,0 +1,27 @@
+INCLUDES = -I$(top_srcdir)/src/include
+
+SUBDIRS = .
+
+noinst_LTLIBRARIES = \
+ libnetwork.la
+
+libnetwork_la_SOURCES = \
+ endian.c \
+ io.c \
+ ipcheck.c \
+ port.c \
+ tcp_return.c \
+ tcpio.c
+
+check_PROGRAMS = \
+ tcpiotest
+
+TESTS = $(check_PROGRAMS)
+
+tcpiotest_SOURCES = \
+ tcpiotest.c
+tcpiotest_LDADD = \
+ $(top_builddir)/src/util/libgnunetutil.la
+
+
+
Added: GNUnet/src/util/network/endian.c
===================================================================
--- GNUnet/src/util/network/endian.c 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/network/endian.c 2006-06-22 17:50:56 UTC (rev 3024)
@@ -0,0 +1,48 @@
+/*
+ This file is part of GNUnet.
+ (C) 2001, 2002, 2003, 2004, 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/endian.c
+ * @brief endian conversion helpers
+ * @author Christian Grothoff
+ */
+
+#include "platform.h"
+#include "gnunet_util.h"
+
+unsigned long long ntohll(unsigned long long n) {
+#if __BYTE_ORDER == __BIG_ENDIAN
+ return n;
+#else
+ return (((unsigned long long)ntohl(n)) << 32) + ntohl(n >> 32);
+#endif
+}
+
+unsigned long long htonll(unsigned long long n) {
+#if __BYTE_ORDER == __BIG_ENDIAN
+ return n;
+#else
+ return (((unsigned long long)htonl(n)) << 32) + htonl(n >> 32);
+#endif
+}
+
+
+
+/* end of endian.c */
Added: GNUnet/src/util/network/io.c
===================================================================
--- GNUnet/src/util/network/io.c 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/network/io.c 2006-06-22 17:50:56 UTC (rev 3024)
@@ -0,0 +1,315 @@
+/*
+ This file is part of GNUnet.
+ (C) 2003 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/io.c
+ * @brief (network) input/output operations
+ * @author Christian Grothoff
+ */
+
+#include "gnunet_util.h"
+#include "platform.h"
+
+/* some systems send us signals, so we'd better
+ catch them (& ignore) */
+#ifndef LINUX
+static void catcher(int sig) {
+ LOG(LOG_INFO,
+ _("Caught signal %d.\n"),
+ sig);
+ /* re-install signal handler! */
+ signal(sig, catcher);
+}
+
+
+#endif
+
+void gnunet_util_initIO() {
+#if ! (defined(LINUX) || defined(MINGW))
+ if ( SIG_ERR == signal(SIGPIPE, SIG_IGN))
+ if ( SIG_ERR == signal(SIGPIPE, catcher))
+ LOG_STRERROR(LOG_WARNING, "signal");
+#endif
+}
+
+void gnunet_util_doneIO() {
+}
+
+/**
+ * Depending on doBlock, enable or disable the nonblocking mode
+ * of socket s.
+ *
+ * @param doBlock use YES to change the socket to blocking, NO to non-blocking
+ * @return Upon successful completion, it returns zero, otherwise -1
+ */
+int setBlocking(int s, int doBlock) {
+#if MINGW
+ u_long l = !doBlock;
+ if (ioctlsocket(s, FIONBIO, &l) == SOCKET_ERROR) {
+ SetErrnoFromWinsockError(WSAGetLastError());
+
+ return -1;
+ } else {
+ /* store the blocking mode */
+ __win_SetHandleBlockingMode(s, doBlock);
+ return 0;
+ }
+#else
+ int flags = fcntl(s, F_GETFL);
+ if (doBlock)
+ flags &= ~O_NONBLOCK;
+ else
+ flags |= O_NONBLOCK;
+
+ return fcntl(s,
+ F_SETFL,
+ flags);
+#endif
+}
+
+/**
+ * Check whether the socket is blocking
+ * @param s the socket
+ * @return YES if blocking, NO non-blocking
+ */
+int isSocketBlocking(int s)
+{
+#ifndef MINGW
+ return (fcntl(s, F_GETFL) & O_NONBLOCK) ? NO : YES;
+#else
+ return __win_IsHandleMarkedAsBlocking(s);
+#endif
+}
+
+/* recv wrappers */
+
+/**
+ * Do a NONBLOCKING read on the given socket. Note that in order to
+ * avoid blocking, the caller MUST have done a select call before
+ * calling this function. Though the caller must be prepared to the
+ * fact that this function may fail with EWOULDBLOCK in any case (Win32).
+ *
+ * @brief Reads at most max bytes to buf. Interrupts are IGNORED.
+ * @param s socket
+ * @param buf buffer
+ * @param max maximum number of bytes to read
+ * @param read number of bytes actually read.
+ * 0 is returned if no more bytes can be read
+ * @return SYSERR on error, YES on success or NO if the operation
+ * would have blocked
+ */
+int RECV_NONBLOCKING(int s,
+ void * buf,
+ size_t max,
+ size_t *read) {
+ int flags;
+
+ setBlocking(s, NO);
+
+#ifdef CYGWIN
+ flags = MSG_NOSIGNAL;
+#elif OSX
+ flags = 0;
+#elif SOMEBSD || SOLARIS
+ flags = MSG_DONTWAIT;
+#elif LINUX
+ flags = MSG_DONTWAIT | MSG_NOSIGNAL;
+#else
+ /* good luck */
+ flags = 0;
+#endif
+
+ do {
+ *read = (size_t) RECV(s,
+ buf,
+ max,
+ flags);
+ } while ( ( *read == -1) && ( errno == EINTR) );
+
+ setBlocking(s, YES);
+
+ if (*read == SYSERR && (errno == EWOULDBLOCK || errno == EAGAIN))
+ return NO;
+ else if ( (*read < 0) || (*read > max) )
+ return SYSERR;
+
+ return YES;
+}
+
+/**
+ * Do a BLOCKING read on the given socket. Read len bytes (if needed
+ * try multiple reads). Interrupts are ignored.
+ *
+ * @return SYSERR if len bytes could not be read,
+ * otherwise the number of bytes read (must be len)
+ */
+int RECV_BLOCKING_ALL(int s,
+ void * buf,
+ size_t len) {
+ size_t pos;
+ int i, flags;
+
+ pos = 0;
+ setBlocking(s, YES);
+
+ while (pos < len) {
+#if LINUX || CYGWIN
+ flags = MSG_NOSIGNAL;
+#else
+ flags = 0;
+#endif
+
+ i = RECV(s,
+ &((char*)buf)[pos],
+ len - pos,
+ flags);
+
+ if ( (i == -1) && (errno == EINTR) )
+ continue;
+ if (i <= 0)
+ {
+ setBlocking(s, NO);
+ return SYSERR;
+ }
+ pos += i;
+ }
+ GNUNET_ASSERT(pos == len);
+
+ setBlocking(s, NO);
+
+ return pos;
+}
+
+/**
+ * Do a NONBLOCKING write on the given socket.
+ * Write at most max bytes from buf.
+ * Interrupts are ignored (cause a re-try).
+ *
+ * The caller must be prepared to the fact that this function
+ * may fail with EWOULDBLOCK in any case (Win32).
+ *
+ * @param s socket
+ * @param buf buffer to send
+ * @param max maximum number of bytes to send
+ * @param sent number of bytes actually sent
+ * @return SYSERR on error, YES on success or
+ * NO if the operation would have blocked.
+ */
+int SEND_NONBLOCKING(int s,
+ const void * buf,
+ size_t max,
+ size_t * sent) {
+ int flags;
+
+ setBlocking(s, NO);
+
+#ifdef SOMEBSD
+ flags = MSG_DONTWAIT;
+#elif SOLARIS
+ flags = MSG_DONTWAIT;
+#elif OSX
+ /* As braindead as Win32? */
+ flags = 0;
+#elif CYGWIN
+ flags = MSG_NOSIGNAL;
+#elif LINUX
+ flags = MSG_DONTWAIT | MSG_NOSIGNAL;
+#else
+ /* pray */
+ flags = 0;
+#endif
+
+ do {
+ *sent = (size_t) SEND(s,
+ buf,
+ max,
+ flags);
+
+ } while ( (*sent == -1) &&
+ (errno == EINTR) );
+
+ setBlocking(s, YES);
+
+ if (*sent == SYSERR && (errno == EWOULDBLOCK || errno == EAGAIN))
+ return NO;
+ else if ( (*sent < 0) || (*sent > max) )
+ return SYSERR;
+
+ return YES;
+}
+
+/**
+ * Do a BLOCKING write on the given socket. Write len bytes (if
+ * needed do multiple write). Interrupts are ignored (cause a
+ * re-try).
+ *
+ * @return SYSERR if len bytes could not be send,
+ * otherwise the number of bytes transmitted (must be len)
+ */
+int SEND_BLOCKING_ALL(int s,
+ const void * buf,
+ size_t len) {
+ size_t pos;
+ int i, flags;
+
+ pos = 0;
+ setBlocking(s, YES);
+ while (pos < len) {
+#if CYGWIN || LINUX
+ flags = MSG_NOSIGNAL;
+#else
+ flags = 0;
+#endif
+ i = SEND(s,
+ &((char*)buf)[pos],
+ len - pos,
+ flags);
+
+ if ( (i == -1) &&
+ (errno == EINTR) )
+ continue; /* ingnore interrupts */
+ if (i <= 0) {
+ if (i == -1)
+ LOG_STRERROR(LOG_WARNING, "send");
+ return SYSERR;
+ }
+ pos += i;
+ }
+ setBlocking(s, NO);
+ GNUNET_ASSERT(pos == len);
+ return pos;
+}
+
+/**
+ * Check if socket is valid
+ * @return 1 if valid, 0 otherwise
+ */
+int isSocketValid(int s)
+{
+#ifndef MINGW
+ struct stat buf;
+ return -1 != fstat(s, &buf);
+#else
+ long l;
+ return ioctlsocket(s, FIONREAD, &l) != SOCKET_ERROR;
+#endif
+}
+
+/* end of io.c */
Added: GNUnet/src/util/network/ipcheck.c
===================================================================
--- GNUnet/src/util/network/ipcheck.c 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/network/ipcheck.c 2006-06-22 17:50:56 UTC (rev 3024)
@@ -0,0 +1,325 @@
+/*
+ This file is part of GNUnet.
+ (C) 2001, 2002, 2003, 2004 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/ipcheck.c
+ * @brief test if an IP matches a given subnet
+ * @author Christian Grothoff
+ */
+
+#include "gnunet_util.h"
+#include "platform.h"
+
+/**
+ * @brief IPV4 network in CIDR notation.
+ */
+typedef struct CIDRNetwork {
+ IPaddr network;
+ IPaddr netmask;
+} CIDRNetwork;
+
+/**
+ * @brief network in CIDR notation for IPV6.
+ */
+typedef struct CIDR6Network {
+ IP6addr network;
+ IP6addr netmask;
+} CIDR6Network;
+
+
+/**
+ * Parse a network specification. The argument specifies
+ * a list of networks. The format is
+ * <tt>[network/netmask;]*</tt> (no whitespace, must be terminated
+ * with a semicolon). The network must be given in dotted-decimal
+ * notation. The netmask can be given in CIDR notation (/16) or
+ * in dotted-decimal (/255.255.0.0).
+ * <p>
+ * @param routeList a string specifying the forbidden networks
+ * @return the converted list, NULL if the synatx is flawed
+ */
+CIDRNetwork * parseRoutes(const char * routeList) {
+ unsigned int count;
+ unsigned int i;
+ unsigned int j;
+ unsigned int len;
+ int cnt;
+ unsigned int pos;
+ unsigned int temps[8];
+ int slash;
+ CIDRNetwork * result;
+
+ if (routeList == NULL)
+ return NULL;
+ len = strlen(routeList);
+ if (len == 0)
+ return NULL;
+ count = 0;
+ for (i=0;i<len;i++)
+ if (routeList[i] == ';')
+ count++;
+ result = MALLOC(sizeof(CIDRNetwork) * (count+1));
+ /* add termination */
+ memset(result,
+ 0,
+ sizeof(CIDRNetwork)*(count+1));
+ i=0;
+ pos = 0;
+ while (i < count) {
+ cnt = sscanf(&routeList[pos],
+ "%u.%u.%u.%u/%u.%u.%u.%u;",
+ &temps[0],
+ &temps[1],
+ &temps[2],
+ &temps[3],
+ &temps[4],
+ &temps[5],
+ &temps[6],
+ &temps[7]);
+ if (cnt == 8) {
+ for (j=0;j<8;j++)
+ if (temps[j] > 0xFF) {
+ LOG(LOG_ERROR,
+ _("Invalid format for IP: `%s'\n"),
+ &routeList[pos]);
+ FREE(result);
+ return NULL;
+ }
+ result[i].network.addr
+ = htonl((temps[0] << 24) + (temps[1] << 16) + (temps[2] << 8) +
temps[3]);
+ result[i].netmask.addr
+ = htonl((temps[4] << 24) + (temps[5] << 16) + (temps[6] << 8) +
temps[7]);
+ while (routeList[pos] != ';')
+ pos++;
+ pos++;
+ i++;
+ continue;
+ }
+ /* try second notation */
+ cnt = sscanf(&routeList[pos],
+ "%u.%u.%u.%u/%u;",
+ &temps[0],
+ &temps[1],
+ &temps[2],
+ &temps[3],
+ &slash);
+ if (cnt == 5) {
+ for (j=0;j<4;j++)
+ if (temps[j] > 0xFF) {
+ LOG(LOG_ERROR,
+ "wrong format for IP: %s\n",
+ &routeList[pos]);
+ FREE(result);
+ return NULL;
+ }
+ result[i].network.addr
+ = htonl((temps[0] << 24) + (temps[1] << 16) + (temps[2] << 8) +
temps[3]);
+ if ( (slash <= 32) && (slash > 0) ) {
+ result[i].netmask.addr = 0;
+ while (slash > 0) {
+ result[i].netmask.addr
+ = (result[i].netmask.addr >> 1) + 0x80000000;
+ slash--;
+ }
+ result[i].netmask.addr
+ = htonl(result[i].netmask.addr);
+ while (routeList[pos] != ';')
+ pos++;
+ pos++;
+ i++;
+ continue;
+ } else {
+ LOG(LOG_ERROR,
+ _("Invalid network notation ('/%d' is not legal in IPv4 CIDR)."),
+ slash);
+ FREE(result);
+ return NULL; /* error */
+ }
+ }
+ LOG(LOG_ERROR,
+ "invalid network notation: >>%s<<",
+ &routeList[pos]);
+ FREE(result);
+ return NULL; /* error */
+ }
+ if (pos < strlen(routeList)) {
+ LOG(LOG_ERROR,
+ _("Invalid network notation (additional characters: `%s')."),
+ &routeList[pos]);
+ FREE(result);
+ return NULL; /* oops */
+ }
+ return result; /* ok */
+}
+
+
+
+/**
+ * Check if the given IP address is in the list of IP addresses.
+ *
+ * @param list a list of networks
+ * @param ip the IP to check (in network byte order)
+ * @return NO if the IP is not in the list, YES if it it is
+ */
+int checkIPListed(const CIDRNetwork * list,
+ IPaddr ip) {
+ int i;
+ IPaddr add;
+
+ add = ip;
+ i=0;
+ if (list == NULL)
+ return NO;
+
+ while ( (list[i].network.addr != 0) ||
+ (list[i].netmask.addr != 0) ) {
+ if ( (add.addr & list[i].netmask.addr) ==
+ (list[i].network.addr & list[i].netmask.addr) )
+ return YES;
+ i++;
+ }
+ return NO;
+}
+
+/**
+ * Parse a network specification. The argument specifies
+ * a list of networks. The format is
+ * <tt>[network/netmask;]*</tt> (no whitespace, must be terminated
+ * with a semicolon). The network must be given in colon-hex
+ * notation. The netmask must be given in CIDR notation (/16) or
+ * can be omitted to specify a single host.
+ * <p>
+ * @param routeList a string specifying the forbidden networks
+ * @return the converted list, NULL if the synatx is flawed
+ */
+CIDR6Network * parseRoutes6(const char * routeListX) {
+ unsigned int count;
+ unsigned int i;
+ unsigned int len;
+ unsigned int pos;
+ int start;
+ int slash;
+ int ret;
+ char * routeList;
+ CIDR6Network * result;
+
+ if (routeListX == NULL)
+ return NULL;
+ len = strlen(routeListX);
+ if (len == 0)
+ return NULL;
+ routeList = STRDUP(routeListX);
+ count = 0;
+ for (i=0;i<len;i++)
+ if (routeList[i] == ';')
+ count++;
+ if (routeList[len-1] != ';') {
+ LOG(LOG_ERROR,
+ _("Invalid network notation (does not end with ';': `%s')\n"),
+ routeList);
+ FREE(routeList);
+ return NULL;
+ }
+
+ result = MALLOC(sizeof(CIDR6Network) * (count+1));
+ memset(result,
+ 0,
+ sizeof(CIDR6Network) * (count+1));
+ i=0;
+ pos = 0;
+ while (i < count) {
+ start = pos;
+ while (routeList[pos] != ';')
+ pos++;
+ slash = pos;
+ while ( (slash >= start) &&
+ (routeList[slash] != '/') )
+ slash--;
+ if (slash < start) {
+ memset(&result[i].netmask,
+ 0xFF,
+ sizeof(IP6addr));
+ slash = pos;
+ } else {
+ routeList[pos] = '\0';
+ ret = inet_pton(AF_INET6,
+ &routeList[slash+1],
+ &result[i].netmask);
+ if (ret <= 0) {
+ LOG(LOG_ERROR,
+ _("Wrong format `%s' for netmask: %s\n"),
+ &routeList[slash+1],
+ STRERROR(errno));
+ FREE(result);
+ FREE(routeList);
+ return NULL;
+ }
+ }
+ routeList[slash] = '\0';
+ ret = inet_pton(AF_INET6,
+ &routeList[start],
+ &result[i].network);
+ if (ret <= 0) {
+ LOG(LOG_ERROR,
+ _("Wrong format `%s' for network: %s\n"),
+ &routeList[slash+1],
+ STRERROR(errno));
+ FREE(result);
+ FREE(routeList);
+ return NULL;
+ }
+ pos++;
+ }
+ FREE(routeList);
+ return result;
+}
+
+/**
+ * Check if the given IP address is in the list of IP addresses.
+ *
+ * @param list a list of networks
+ * @param ip the IP to check (in network byte order)
+ * @return NO if the IP is not in the list, YES if it it is
+ */
+int checkIP6Listed(const CIDR6Network * list,
+ const IP6addr * ip) {
+ unsigned int i;
+ unsigned int j;
+ struct in6_addr zero;
+
+ i=0;
+ if (list == NULL)
+ return NO;
+
+ memset(&zero, 0, sizeof(struct in6_addr));
+ while ( (memcmp(&zero, &list[i].network, sizeof(struct in6_addr)) != 0) ||
+ (memcmp(&zero, &list[i].netmask, sizeof(struct in6_addr)) != 0) ) {
+ for (j=0;j<sizeof(struct in6_addr)/sizeof(int);j++)
+ if ( ((((int*)ip)[j] & ((int*)&list[i].netmask)[j])) !=
+ (((int*)&list[i].network)[j] & ((int*)&list[i].netmask)[j]) ) {
+ i++;
+ continue;
+ }
+ return YES;
+ }
+ return NO;
+}
+
+/* end of ipcheck.c */
Added: GNUnet/src/util/network/port.c
===================================================================
--- GNUnet/src/util/network/port.c 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/network/port.c 2006-06-22 17:50:56 UTC (rev 3024)
@@ -0,0 +1,102 @@
+/*
+ This file is part of GNUnet
+
+ 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/port.c
+ * @brief functions for GNUnet clients to establish connection with gnunetd
+ * @author Christian Grothoff
+ */
+
+#include "gnunet_util.h"
+#include "platform.h"
+
+/**
+ * Return the port-number (in host byte order)
+ */
+unsigned short getGNUnetPort() {
+ static unsigned short port;
+ const char *setting;
+
+ if (port != 0)
+ return port;
+ if (testConfigurationString("GNUNETD",
+ "_MAGIC_",
+ "YES"))
+ setting = "PORT";
+ else
+ setting = "CLIENT-PORT";
+
+ port = (unsigned short) getConfigurationInt("NETWORK",
+ setting);
+ if (port == 0) {
+ errexit(_("Cannot determine port of gnunetd server. "
+ "Define in configuration file in section `%s' under `%s'.\n"),
+ "NETWORK",
+ setting);
+ }
+ return port;
+}
+
+/**
+ * Configuration: get the GNUnetd host where the client
+ * should connect to (via TCP)
+ * @return the name of the host
+ */
+static const char * getGNUnetdHost() {
+ static char * res;
+
+ if (res != NULL)
+ return res;
+ res = getConfigurationString("NETWORK",
+ "HOST");
+ if (res == NULL)
+ res = "localhost";
+ return res;
+}
+
+/**
+ * Get a GNUnet TCP socket that is connected to gnunetd.
+ */
+GNUNET_TCP_SOCKET * getClientSocket() {
+ GNUNET_TCP_SOCKET * sock;
+ const char * host;
+
+ sock = MALLOC(sizeof(GNUNET_TCP_SOCKET));
+ host = getGNUnetdHost();
+ if (SYSERR == initGNUnetClientSocket(getGNUnetPort(),
+ host,
+ sock)) {
+ LOG(LOG_ERROR,
+ _("Could not connect to gnunetd.\n"));
+ FREE(sock);
+ return NULL;
+ }
+ return sock;
+}
+
+/**
+ * Free a Client socket.
+ */
+void releaseClientSocket(GNUNET_TCP_SOCKET * sock) {
+ if (sock != NULL) {
+ destroySocket(sock);
+ FREE(sock);
+ }
+}
+
+/* end of port.c */
Added: GNUnet/src/util/network/tcp_return.c
===================================================================
--- GNUnet/src/util/network/tcp_return.c 2006-06-22 17:39:19 UTC (rev
3023)
+++ GNUnet/src/util/network/tcp_return.c 2006-06-22 17:50:56 UTC (rev
3024)
@@ -0,0 +1,94 @@
+/*
+ This file is part of GNUnet.
+ (C) 2001, 2002, 2004 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/tcp_return.c
+ * @brief code to communicate simple (int) return values via reliable
+ * TCP stream
+ * @author Christian Grothoff
+ *
+ * Helper methods to send and receive return values over a TCP stream
+ * that has tcpio (see util/tcpio.c) semantics.
+ */
+
+#include "gnunet_util.h"
+#include "gnunet_protocols.h"
+#include "platform.h"
+
+/**
+ * Obtain a return value from a remote call from TCP.
+ *
+ * @param sock the TCP socket
+ * @param ret the return value from TCP
+ * @return SYSERR on error, OK if the return value was read
+ * successfully
+ */
+int readTCPResult(GNUNET_TCP_SOCKET * sock,
+ int * ret) {
+ CS_returnvalue_MESSAGE * rv;
+
+ rv = NULL;
+ if (SYSERR == readFromSocket(sock,
+ (CS_MESSAGE_HEADER **) &rv)) {
+ LOG(LOG_WARNING,
+ _("`%s' failed, other side closed connection.\n"),
+ __FUNCTION__);
+ return SYSERR;
+ }
+ if ( (ntohs(rv->header.size) != sizeof(CS_returnvalue_MESSAGE)) ||
+ (ntohs(rv->header.type) != CS_PROTO_RETURN_VALUE) ) {
+ LOG(LOG_WARNING,
+ _("`%s' failed, reply invalid!\n"),
+ __FUNCTION__);
+ FREE(rv);
+ return SYSERR;
+ }
+ *ret = ntohl(rv->return_value);
+ FREE(rv);
+ return OK;
+}
+
+/**
+ * Send a return value to the caller of a remote call via
+ * TCP.
+ * @param sock the TCP socket
+ * @param ret the return value to send via TCP
+ * @return SYSERR on error, OK if the return value was
+ * send successfully
+ */
+int sendTCPResult(GNUNET_TCP_SOCKET * sock,
+ int ret) {
+ CS_returnvalue_MESSAGE rv;
+
+ rv.header.size
+ = htons(sizeof(CS_returnvalue_MESSAGE));
+ rv.header.type
+ = htons(CS_PROTO_RETURN_VALUE);
+ rv.return_value
+ = htonl(ret);
+ return writeToSocket(sock,
+ &rv.header);
+}
+
+
+
+
+
+/* end of tcp_return.c */
Added: GNUnet/src/util/network/tcpio.c
===================================================================
--- GNUnet/src/util/network/tcpio.c 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/network/tcpio.c 2006-06-22 17:50:56 UTC (rev 3024)
@@ -0,0 +1,463 @@
+/*
+ This file is part of GNUnet.
+ (C) 2001, 2002 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/tcpio.c
+ * @brief code for synchronized access to TCP streams
+ * @author Christian Grothoff
+ *
+ * Generic TCP code for reliable, mostly blocking, record-oriented TCP
+ * connections. GNUnet uses the "tcpio" code for trusted client-server
+ * (e.g. gnunet-gtk to gnunetd via loopback) communications. Note
+ * that an unblocking write is also provided since if both client and
+ * server use blocking IO, both may block on a write and cause a
+ * mutual inter-process deadlock.
+ *
+ * Since we do not want other peers (!) to be able to block a peer by
+ * not reading from the TCP stream, the peer-to-peer TCP transport
+ * uses unreliable, buffered, non-blocking, record-oriented TCP code
+ * with a select call to reduce the number of threads which is
+ * provided in transports/tcp.c.
+ */
+
+#include "gnunet_util.h"
+#include "platform.h"
+
+#define DEBUG_TCPIO NO
+
+/**
+ * Initialize a GNUnet client socket.
+ * @param port the portnumber in host byte order
+ * @param ip IP of the host to connect to, in network byte order
+ * @param result the SOCKET (filled in)
+ * @return OK if successful, SYSERR on failure
+ */
+int initGNUnetClientSocketIP(unsigned short port,
+ IPaddr ip,
+ GNUNET_TCP_SOCKET * result) {
+ result->ip = ip;
+ result->port = port;
+ result->socket = -1; /* closed */
+ result->outBufLen = 0;
+ result->outBufPending = NULL;
+ MUTEX_CREATE(&result->readlock);
+ MUTEX_CREATE(&result->writelock);
+ return OK;
+}
+
+/**
+ * Initialize a GNUnet client socket.
+ * @param port the portnumber in host byte order
+ * @param hostname the name of the host to connect to
+ * @param result the SOCKET (filled in)
+ * @return OK if successful, SYSERR on failure
+ */
+int initGNUnetClientSocket(unsigned short port,
+ const char * hostname,
+ GNUNET_TCP_SOCKET * result) {
+ GNUNET_ASSERT(hostname != NULL);
+#if DEBUG_TCPIO
+ LOG(LOG_DEBUG,
+ "Connecting to host '%s:%d'.\n",
+ hostname,
+ port);
+#endif
+ if (OK != GN_getHostByName(hostname,
+ &result->ip))
+ return SYSERR;
+ result->port = port;
+ result->socket = -1; /* closed */
+ result->outBufLen = 0;
+ result->outBufPending = NULL;
+ MUTEX_CREATE(&result->readlock);
+ MUTEX_CREATE(&result->writelock);
+ return OK;
+}
+
+/**
+ * Initialize a GNUnet server socket.
+ * @param sock the open socket
+ * @param result the SOCKET (filled in)
+ * @return OK (always successful)
+ */
+int initGNUnetServerSocket(int sock,
+ GNUNET_TCP_SOCKET * result) {
+ result->ip.addr = 0;
+ result->port = 0;
+ result->socket = sock;
+ result->outBufLen = 0;
+ result->outBufPending = NULL;
+ MUTEX_CREATE(&result->readlock);
+ MUTEX_CREATE(&result->writelock);
+ return OK;
+}
+
+/**
+ * Check if a socket is open. Will ALWAYS return 'true'
+ * for a valid client socket (even if the connection is
+ * closed), but will return false for a closed server socket.
+ * @return 1 if open, 0 if closed
+ */
+int isOpenConnection(GNUNET_TCP_SOCKET * sock) {
+ return (sock->socket != -1);
+}
+
+/**
+ * Check a socket, open and connect if it is closed and it is a client-socket.
+ */
+int checkSocket(GNUNET_TCP_SOCKET * sock) {
+ int res;
+ struct sockaddr_in soaddr;
+ fd_set rset;
+ fd_set wset;
+ fd_set eset;
+ struct timeval timeout;
+ int ret;
+ int wasSockBlocking;
+
+ if (sock->socket != -1)
+ return OK;
+ sock->socket = SOCKET(PF_INET, SOCK_STREAM, 6); /* 6: TCP */
+ if (sock->socket == -1) {
+ LOG_STRERROR(LOG_FAILURE, "socket");
+ return SYSERR;
+ }
+
+ wasSockBlocking = isSocketBlocking(sock->socket);
+ setBlocking(sock->socket, NO);
+
+ soaddr.sin_family = AF_INET;
+ GNUNET_ASSERT(sizeof(struct in_addr) == sizeof(sock->ip.addr));
+ memcpy(&soaddr.sin_addr,
+ &sock->ip.addr,
+ sizeof(struct in_addr));
+ soaddr.sin_port = htons(sock->port);
+ res = CONNECT(sock->socket,
+ (struct sockaddr*)&soaddr,
+ sizeof(soaddr));
+ if ( (res < 0) &&
+ (errno != EINPROGRESS) ) {
+ LOG(LOG_INFO,
+ _("Cannot connect to %u.%u.%u.%u:%u: %s\n"),
+ PRIP(ntohl(*(int*)&sock->ip.addr)),
+ sock->port,
+ STRERROR(errno));
+ closefile(sock->socket);
+ sock->socket = -1;
+ return SYSERR;
+ }
+
+ /* we call select() first with a timeout of 5s to
+ avoid blocking on a later write indefinitely;
+ this is mostly needed for gnunet-testbed to keep
+ working if an advertised testbed-client is behind
+ a firewall and unreachable. But it is also nice
+ if a local firewall decides to just drop the TCP
+ handshake...*/
+ FD_ZERO(&rset);
+ FD_ZERO(&wset);
+ FD_ZERO(&eset);
+ if (sock->socket < 0)
+ return SYSERR;
+ FD_SET(sock->socket, &wset);
+ timeout.tv_sec = 5;
+ timeout.tv_usec = 0;
+ ret = SELECT(sock->socket+1, &rset, &wset, &eset, &timeout);
+ if ( (ret == -1) ||
+ (sock->socket == -1) ||
+ (! FD_ISSET(sock->socket,
+ &wset)) ) {
+ LOG(LOG_INFO,
+ _("Cannot connect to %u.%u.%u.%u:%u: %s\n"),
+ PRIP(ntohl(*(int*)&sock->ip.addr)),
+ sock->port,
+ STRERROR(errno));
+ setBlocking(sock->socket, wasSockBlocking);
+ return SYSERR;
+ }
+ setBlocking(sock->socket, wasSockBlocking);
+
+ return OK;
+}
+
+/**
+ * Write to a GNUnet TCP socket. Will also potentially complete the
+ * sending of a previous non-blocking writeToSocket call.
+ *
+ * @param sock the socket to write to
+ * @param buffer the buffer to write
+ * @return OK if the write was sucessful, otherwise SYSERR.
+ */
+int writeToSocket(GNUNET_TCP_SOCKET * sock,
+ const CS_MESSAGE_HEADER * buffer) {
+ int res;
+ int size;
+
+ if (SYSERR == checkSocket(sock))
+ return SYSERR;
+ size = ntohs(buffer->size);
+ MUTEX_LOCK(&sock->writelock);
+
+ /* write pending data from prior non-blocking call
+ -- but this time use blocking IO! */
+ if (sock->outBufLen > 0) {
+ res = SEND_BLOCKING_ALL(sock->socket,
+ sock->outBufPending,
+ sock->outBufLen);
+ if (res < 0) {
+ if (errno == EAGAIN) {
+ MUTEX_UNLOCK(&sock->writelock);
+ return SYSERR; /* can not send right now;
+ but do NOT close socket in this case! */
+ }
+ LOG_STRERROR(LOG_INFO, "send");
+ closeSocketTemporarily(sock);
+ MUTEX_UNLOCK(&sock->writelock);
+ return SYSERR;
+ }
+ FREE(sock->outBufPending);
+ sock->outBufPending = NULL;
+ sock->outBufLen = 0;
+ }
+
+ res = SEND_BLOCKING_ALL(sock->socket,
+ buffer,
+ size);
+ if (res < 0) {
+ if (errno == EAGAIN) {
+ MUTEX_UNLOCK(&sock->writelock);
+ return SYSERR; /* would block, can not send right now;
+ but do NOT close socket in this case! */
+ }
+ LOG_STRERROR(LOG_INFO, "send");
+ closeSocketTemporarily(sock);
+ MUTEX_UNLOCK(&sock->writelock);
+ return SYSERR;
+ }
+ MUTEX_UNLOCK(&sock->writelock);
+ return OK;
+}
+
+
+/**
+ * Write to a GNUnet TCP socket non-blocking. Note that it is
+ * possible that only a part of the message is send and that tcpio
+ * buffers the rest until the next writeToSocket operation. If that
+ * buffer is full or if send did not transmit any byte of the message,
+ * NO is returned to indicate that the write failed (would have
+ * blocked).
+ *
+ * @param sock the socket to write to
+ * @param buffer the buffer to write
+ * @return OK if the write was sucessful, NO if it would have blocked and was
not performed,
+ * otherwise SYSERR.
+ */
+int writeToSocketNonBlocking(GNUNET_TCP_SOCKET * sock,
+ const CS_MESSAGE_HEADER * buffer) {
+ size_t res;
+ size_t size;
+
+ if (SYSERR == checkSocket(sock))
+ return SYSERR;
+ MUTEX_LOCK(&sock->writelock);
+ if (sock->outBufLen > 0) {
+ SEND_NONBLOCKING(sock->socket,
+ sock->outBufPending,
+ sock->outBufLen,
+ &res);
+ if (res == (size_t)-1) {
+ if ( (errno == EWOULDBLOCK) ||
+ (errno == EAGAIN) ) {
+ MUTEX_UNLOCK(&sock->writelock);
+ return NO;
+ }
+ LOG_STRERROR(LOG_INFO, "write");
+ closeSocketTemporarily(sock);
+ MUTEX_UNLOCK(&sock->writelock);
+ return SYSERR;
+ }
+ if (res < sock->outBufLen) {
+ memcpy(sock->outBufPending,
+ &((char*)sock->outBufPending)[res],
+ sock->outBufLen - res);
+ sock->outBufLen -= res;
+ MUTEX_UNLOCK(&sock->writelock);
+ return SYSERR;
+ }
+ /* completely send out deferred buffer, so
+ we can in fact continue! */
+ FREENONNULL(sock->outBufPending);
+ sock->outBufPending = NULL;
+ sock->outBufLen = 0;
+ }
+
+ size = ntohs(buffer->size);
+
+ SEND_NONBLOCKING(sock->socket,
+ (const char*)buffer,
+ size,
+ &res);
+ if (res == (size_t) -1) {
+ if ( (errno == EWOULDBLOCK) ||
+ (errno == EAGAIN) ) {
+ MUTEX_UNLOCK(&sock->writelock);
+ return NO; /* would block, can not send right now;
+ but do NOT close socket in this case;
+ do not use SYSERR as return value
+ since this is not an error! */
+ }
+ LOG_STRERROR(LOG_INFO, "send");
+ closeSocketTemporarily(sock);
+ MUTEX_UNLOCK(&sock->writelock);
+ return SYSERR;
+ }
+ GNUNET_ASSERT(res <= size);
+ if (res != size) {
+ sock->outBufPending = MALLOC(size - res);
+ memcpy(sock->outBufPending,
+ &((const char*)buffer)[res],
+ size - res);
+ sock->outBufLen = size - res;
+ MUTEX_UNLOCK(&sock->writelock);
+ return OK; /* return OK here means that the message will be transmitted,
+ though it may be a bit later (on the next call, in fact). */
+ }
+ MUTEX_UNLOCK(&sock->writelock);
+ return OK;
+}
+
+/**
+ * Read from a GNUnet TCP socket.
+ * @param sock the socket
+ * @param buffer the buffer to write data to
+ * @return OK if the read was successful, SYSERR if the socket
+ * was closed by the other side (if the socket is a
+ * client socket and is used again, tcpio will attempt
+ * to re-establish the connection [temporary error]).
+ */
+int readFromSocket(GNUNET_TCP_SOCKET * sock,
+ CS_MESSAGE_HEADER ** buffer) {
+ int res;
+ unsigned int pos;
+ char * buf;
+ unsigned short size;
+
+ if (SYSERR == checkSocket(sock))
+ return SYSERR;
+
+ MUTEX_LOCK(&sock->readlock);
+ pos = 0;
+ res = 0;
+
+ pos = RECV_BLOCKING_ALL(sock->socket,
+ &size,
+ sizeof(unsigned short));
+ if (pos != sizeof(unsigned short)) {
+#if DEBUG_TCPIO
+ LOG_STRERROR(LOG_INFO, "recv");
+#endif
+ closeSocketTemporarily(sock);
+ MUTEX_UNLOCK(&sock->readlock);
+ return SYSERR; /* other side closed socket or invalid header */
+ }
+ size = ntohs(size);
+ if (size < sizeof(CS_MESSAGE_HEADER)) {
+#if DEBUG_TCPIO
+ LOG_STRERROR(LOG_INFO, "recv");
+#endif
+ closeSocketTemporarily(sock);
+ MUTEX_UNLOCK(&sock->readlock);
+ return SYSERR; /* invalid header */
+ }
+
+ buf = (char*) *buffer;
+ if (buf == NULL)
+ buf = MALLOC(size);
+
+ res = RECV_BLOCKING_ALL(sock->socket,
+ &buf[pos],
+ size - pos);
+
+ if (res != (int)(size - pos)) { /* error, abort */
+ if (sock->socket != -1)
+ LOG_STRERROR(LOG_INFO, "recv");
+ closeSocketTemporarily(sock);
+ if (*buffer == NULL)
+ FREE(buf);
+ MUTEX_UNLOCK(&sock->readlock);
+ return SYSERR;
+ }
+#if DEBUG_TCPIO
+ LOG(LOG_DEBUG,
+ "Successfully received %d bytes from TCP socket.\n",
+ size);
+#endif
+ MUTEX_UNLOCK(&sock->readlock);
+ *buffer = (CS_MESSAGE_HEADER*) buf;
+ (*buffer)->size = htons(size);
+ return OK; /* success */
+}
+
+/**
+ * Close a GNUnet TCP socket for now (use to temporarily close
+ * a TCP connection that will probably not be used for a long
+ * time; the socket will still be auto-reopened by the
+ * readFromSocket/writeToSocket methods if it is a client-socket).
+ */
+void closeSocketTemporarily(GNUNET_TCP_SOCKET * sock) {
+ if (sock == NULL)
+ return;
+ if (sock->socket != -1) {
+ int i;
+
+ i = sock->socket;
+#if DEBUG_TCPIO
+ LOG(LOG_DEBUG,
+ "TCP: closing socket %d.\n",
+ sock->socket);
+#endif
+ sock->socket = -1;
+ if (0 != SHUTDOWN(i, SHUT_RDWR))
+ LOG_STRERROR(LOG_DEBUG, "shutdown");
+ closefile(i);
+ }
+ sock->outBufLen = 0;
+ FREENONNULL(sock->outBufPending);
+ sock->outBufPending = NULL;
+}
+
+/**
+ * Destroy a socket for good. If you use this socket afterwards,
+ * you must first invoke initializeSocket, otherwise the operation
+ * will fail.
+ */
+void destroySocket(GNUNET_TCP_SOCKET * sock) {
+ closeSocketTemporarily(sock);
+ sock->ip.addr = 0;
+ sock->port = 0;
+ sock->outBufLen = 0;
+ FREENONNULL(sock->outBufPending);
+ sock->outBufPending = NULL;
+ MUTEX_DESTROY(&sock->readlock);
+ MUTEX_DESTROY(&sock->writelock);
+}
+
+
+/* end of tcpio.c */
Added: GNUnet/src/util/network/tcpiotest.c
===================================================================
--- GNUnet/src/util/network/tcpiotest.c 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/network/tcpiotest.c 2006-06-22 17:50:56 UTC (rev 3024)
@@ -0,0 +1,261 @@
+/**
+ * @file test/tcpiotest.c
+ * @brief testcase for util/tcpiotest.c
+ */
+
+#include "gnunet_util.h"
+#include "platform.h"
+
+static int openServerSocket() {
+ int listenerFD;
+ int listenerPort;
+ struct sockaddr_in serverAddr;
+ const int on = 1;
+
+ listenerPort = getGNUnetPort();
+ /* create the socket */
+ while ( (listenerFD = SOCKET(PF_INET, SOCK_STREAM, 0)) < 0) {
+ LOG(LOG_ERROR,
+ "ERROR opening socket (%s). "
+ "No client service started. "
+ "Trying again in 30 seconds.\n",
+ STRERROR(errno));
+ sleep(30);
+ }
+
+ /* fill in the inet address structure */
+ memset((char *) &serverAddr,
+ 0,
+ sizeof(serverAddr));
+ serverAddr.sin_family = AF_INET;
+ serverAddr.sin_addr.s_addr=htonl(INADDR_ANY);
+ serverAddr.sin_port=htons(listenerPort);
+
+ if ( SETSOCKOPT(listenerFD,
+ SOL_SOCKET,
+ SO_REUSEADDR,
+ &on, sizeof(on)) < 0 )
+ perror("setsockopt");
+
+ /* bind the socket */
+ if (BIND (listenerFD,
+ (struct sockaddr *) &serverAddr,
+ sizeof(serverAddr)) < 0) {
+ LOG(LOG_ERROR,
+ "ERROR (%s) binding the TCP listener to port %d. "
+ "Test failed. Is gnunetd running?\n",
+ STRERROR(errno),
+ listenerPort);
+ return -1;
+ }
+
+ /* start listening for new connections */
+ if (0 != LISTEN(listenerFD, 5)) {
+ LOG(LOG_ERROR,
+ " listen failed: %s\n",
+ STRERROR(errno));
+ return -1;
+ }
+ return listenerFD;
+}
+
+static int doAccept(int serverSocket) {
+ int incomingFD;
+ int lenOfIncomingAddr;
+ struct sockaddr_in clientAddr;
+
+ incomingFD = -1;
+ while (incomingFD < 0) {
+ lenOfIncomingAddr = sizeof(clientAddr);
+ incomingFD = ACCEPT(serverSocket,
+ (struct sockaddr *)&clientAddr,
+ &lenOfIncomingAddr);
+ if (incomingFD < 0) {
+ LOG(LOG_ERROR,
+ "ERROR accepting new connection (%s).\n",
+ STRERROR(errno));
+ continue;
+ }
+ }
+ return incomingFD;
+}
+
+/**
+ * Perform option parsing from the command line.
+ */
+static int parseCommandLine(int argc,
+ char * argv[]) {
+ char c;
+
+ while (1) {
+ int option_index = 0;
+ static struct GNoption long_options[] = {
+ { "config", 1, 0, 'c' },
+ { 0,0,0,0 }
+ };
+
+ c = GNgetopt_long(argc,
+ argv,
+ "c:",
+ long_options,
+ &option_index);
+
+ if (c == -1)
+ break; /* No more flags to process */
+
+ switch(c) {
+ case 'c':
+ FREENONNULL(setConfigurationString("FILES",
+ "gnunet.conf",
+ GNoptarg));
+ break;
+ } /* end of parsing commandline */
+ }
+ FREENONNULL(setConfigurationString("GNUNETD",
+ "LOGFILE",
+ NULL));
+ FREENONNULL(setConfigurationString("GNUNETD",
+ "LOGLEVEL",
+ "DEBUG"));
+ return OK;
+}
+
+static int testTransmission(GNUNET_TCP_SOCKET * a,
+ GNUNET_TCP_SOCKET * b) {
+ CS_MESSAGE_HEADER * hdr;
+ CS_MESSAGE_HEADER * buf;
+ int i;
+ int j;
+
+ hdr = MALLOC(1024);
+ for (i=0;i<1024-sizeof(CS_MESSAGE_HEADER);i+=7) {
+ fprintf(stderr, ".");
+ for (j=0;j<i;j++)
+ ((char*)&hdr[1])[j] = (char)i+j;
+ hdr->size = htons(i+sizeof(CS_MESSAGE_HEADER));
+ hdr->type = 0;
+ if (OK != writeToSocket(a, hdr)) {
+ FREE(hdr);
+ return 1;
+ }
+ buf = NULL;
+ if (OK != readFromSocket(b, &buf)) {
+ FREE(hdr);
+ return 2;
+ }
+ if (0 != memcmp(buf, hdr, i+sizeof(CS_MESSAGE_HEADER))) {
+ FREE(buf);
+ FREE(hdr);
+ return 4;
+ }
+ FREE(buf);
+ }
+ FREE(hdr);
+ return 0;
+}
+
+static int testNonblocking(GNUNET_TCP_SOCKET * a,
+ GNUNET_TCP_SOCKET * b) {
+ CS_MESSAGE_HEADER * hdr;
+ CS_MESSAGE_HEADER * buf;
+ int i;
+ int cnt;
+
+ hdr = MALLOC(1024);
+ for (i=0;i<1024-sizeof(CS_MESSAGE_HEADER);i+=11)
+ ((char*)&hdr[1])[i] = (char)i;
+ hdr->size = htons(64+sizeof(CS_MESSAGE_HEADER));
+ hdr->type = 0;
+ while (OK == writeToSocketNonBlocking(a,
+ hdr))
+ hdr->type++;
+ i = 0;
+ cnt = hdr->type;
+ /* printf("Reading %u messages.\n", cnt); */
+ if (cnt < 2)
+ return 8; /* could not write ANY data non-blocking!? */
+ for (i=0;i<cnt;i++) {
+ hdr->type = i;
+ buf = NULL;
+ if (OK != readFromSocket(b, &buf)) {
+ FREE(hdr);
+ return 16;
+ }
+ if (0 != memcmp(buf, hdr, 64+sizeof(CS_MESSAGE_HEADER))) {
+ printf("Failure in message %u. Headers: %d ? %d\n",
+ i,
+ buf->type,
+ hdr->type);
+ FREE(buf);
+ FREE(hdr);
+ return 32;
+ }
+ FREE(buf);
+ if (i == cnt - 2) {
+ /* printf("Blocking write to flush last non-blocking message.\n"); */
+ hdr->type = cnt;
+ if (OK != writeToSocket(a,
+ hdr)) {
+ FREE(hdr);
+ return 64;
+ }
+ }
+ }
+ hdr->type = i;
+ buf = NULL;
+ if (OK != readFromSocket(b, &buf)) {
+ FREE(hdr);
+ return 128;
+ }
+ if (0 != memcmp(buf, hdr, 64+sizeof(CS_MESSAGE_HEADER))) {
+ FREE(buf);
+ FREE(hdr);
+ return 256;
+ }
+ FREE(buf);
+ FREE(hdr);
+ return 0;
+}
+
+int main(int argc, char * argv[]){
+ int i;
+ int ret;
+ int serverSocket;
+ GNUNET_TCP_SOCKET * clientSocket;
+ GNUNET_TCP_SOCKET acceptSocket;
+
+ ret = 0;
+ initUtil(argc, argv, &parseCommandLine);
+ serverSocket = openServerSocket();
+ clientSocket = getClientSocket();
+ if (serverSocket == -1) {
+ releaseClientSocket(clientSocket);
+ doneUtil();
+ return 1;
+ }
+ for (i=0;i<2;i++) {
+ if (OK == checkSocket(clientSocket)) {
+ if (OK == initGNUnetServerSocket(doAccept(serverSocket),
+ &acceptSocket)) {
+ ret = ret | testTransmission(clientSocket, &acceptSocket);
+ ret = ret | testTransmission(&acceptSocket, clientSocket);
+ ret = ret | testNonblocking(clientSocket, &acceptSocket);
+ ret = ret | testNonblocking(&acceptSocket, clientSocket);
+ closeSocketTemporarily(clientSocket);
+ destroySocket(&acceptSocket);
+ fprintf(stderr, "\n");
+ } else {
+ fprintf(stderr, "initGNUnetServerSocket failed.\n");
+ ret = -1;
+ }
+ } else {
+ fprintf(stderr, "checkSocket faild.\n");
+ ret = -1;
+ }
+ }
+ releaseClientSocket(clientSocket);
+ doneUtil();
+ if (ret > 0)
+ fprintf(stderr, "Error %d\n", ret);
+ return ret;
+}
Added: GNUnet/src/util/os/Makefile.am
===================================================================
--- GNUnet/src/util/os/Makefile.am 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/os/Makefile.am 2006-06-22 17:50:56 UTC (rev 3024)
@@ -0,0 +1,35 @@
+INCLUDES = -I$(top_srcdir)/src/include
+
+SUBDIRS = .
+
+noinst_LTLIBRARIES = \
+ libos.la
+
+libos_la_SOURCES = \
+ daemon.c \
+ dso.c \
+ osconfig.c \
+ semaphore.c \
+ statuscalls.c
+
+check_PROGRAMS = \
+ daemontest \
+ semaphoretest \
+ statuscallstest
+
+TESTS = $(check_PROGRAMS)
+
+daemontest_SOURCES = \
+ daemontest.c
+daemontest_LDADD = \
+ $(top_builddir)/src/util/libgnunetutil.la
+
+semaphoretest_SOURCES = \
+ semaphoretest.c
+semaphoretest_LDADD = \
+ $(top_builddir)/src/util/libgnunetutil.la
+
+statuscallstest_SOURCES = \
+ statuscallstest.c
+statuscallstest_LDADD = \
+ $(top_builddir)/src/util/libgnunetutil.la
Added: GNUnet/src/util/os/daemon.c
===================================================================
--- GNUnet/src/util/os/daemon.c 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/os/daemon.c 2006-06-22 17:50:56 UTC (rev 3024)
@@ -0,0 +1,336 @@
+/*
+ This file is part of GNUnet.
+ (C) 2005 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 src/util/daemon.c
+ * @brief code for client-gnunetd interaction (start, stop, waitpid, check
running)
+ * @author Christian Grothoff
+ */
+
+#include "platform.h"
+#include "gnunet_util.h"
+#include "gnunet_protocols.h"
+
+
+/**
+ * Checks if gnunetd is running
+ *
+ * Uses CS_PROTO_traffic_COUNT query to determine if gnunetd is
+ * running.
+ *
+ * @return OK if gnunetd is running, SYSERR if not
+ */
+int checkGNUnetDaemonRunning(struct GE_Context * ectx) {
+ GNUNET_TCP_SOCKET * sock;
+ CS_MESSAGE_HEADER csHdr;
+ int ret;
+
+ sock = getClientSocket(ectx);
+ if (sock == NULL)
+ return SYSERR;
+
+ csHdr.size
+ = htons(sizeof(CS_MESSAGE_HEADER));
+ csHdr.type
+ = htons(CS_PROTO_traffic_COUNT);
+ if (SYSERR == writeToSocket(sock,
+ &csHdr)) {
+ releaseClientSocket(sock);
+ return SYSERR;
+ }
+ if (SYSERR == readTCPResult(sock,
+ &ret)) {
+ releaseClientSocket(sock);
+ return SYSERR;
+ }
+ releaseClientSocket(sock);
+ return OK;
+}
+
+
+#if LINUX || OSX || SOLARIS || SOMEBSD
+/**
+ * Fork a gnunetd process
+ *
+ * @param daemonize YES if gnunetd should be daemonized
+ * @return pid_t of gnunetd if NOT daemonized, 0 if
+ * daemonized sucessfully, -1 on error
+ */
+static pid_t launchWithExec(int daemonize) {
+ pid_t pid;
+
+ pid = fork();
+ if (pid == 0) {
+ char * args[5];
+ char * path;
+ char * cp;
+
+ path = NULL;
+ cp = getConfigurationString("MAIN",
+ "ARGV[0]");
+ if (cp != NULL) {
+ int i = strlen(cp);
+ while ( (i >= 0) &&
+ (cp[i] != DIR_SEPARATOR) )
+ i--;
+ if ( i != -1 ) {
+ cp[i+1] = '\0';
+ path = MALLOC(i+2+strlen("gnunetd"));
+ strcpy(path, cp);
+ strcat(path, "gnunetd");
+ if (ACCESS(path, X_OK) == 0) {
+ args[0] = path;
+ } else {
+ FREE(path);
+ path = NULL;
+ args[0] = "gnunetd";
+ }
+ FREE(cp);
+ } else {
+ args[0] = "gnunetd";
+ }
+ }
+ cp = getConfigurationString("GNUNET",
+ "GNUNETD-CONFIG");
+ if (cp != NULL) {
+ args[1] = "-c";
+ args[2] = cp;
+ if (NO == daemonize) {
+ args[3] = "-d";
+ args[4] = NULL;
+ } else
+ args[3] = NULL;
+ } else {
+ if (NO == daemonize) {
+ args[1] = "-d";
+ args[2] = NULL;
+ } else
+ args[1] = NULL;
+ }
+ errno = 0;
+ nice(10); /* return value is not well-defined */
+ if (errno != 0)
+ LOG_STRERROR(LOG_WARNING, "nice");
+ if (path != NULL)
+ execv(path,
+ args);
+ else
+ execvp("gnunetd",
+ args);
+ LOG_STRERROR(LOG_FAILURE, "exec");
+ LOG(LOG_FAILURE,
+ _("Attempted path to `%s' was `%s'.\n"),
+ "gnunetd",
+ (path == NULL) ? "gnunetd" : path);
+ FREENONNULL(path); /* yeah, right, like we're likely to get
+ here... */
+ _exit(-1);
+ } else if (daemonize) {
+ pid_t ret;
+ int status;
+
+ ret = waitpid(pid, &status, 0);
+ if (ret == -1) {
+ LOG_STRERROR(LOG_ERROR, "waitpid");
+ return SYSERR;
+ }
+ if ( (WIFEXITED(status) &&
+ (0 != WEXITSTATUS(status)) ) ) {
+ return SYSERR;
+ }
+#ifdef WCOREDUMP
+ if (WCOREDUMP(status)) {
+ return SYSERR;
+ }
+#endif
+ if (WIFSIGNALED(status) ||
+ WTERMSIG(status) ) {
+ return SYSERR;
+ }
+ return 0;
+ }
+ return pid;
+}
+#endif
+
+/**
+ * Start gnunetd process
+ *
+ * @param daemonize YES if gnunetd should be daemonized
+ * @return pid_t of gnunetd if NOT daemonized, 0 if
+ * daemonized sucessfully, -1 on error
+ */
+int startGNUnetDaemon(int daemonize) {
+#if LINUX || OSX || SOLARIS || SOMEBSD
+ return launchWithExec(daemonize);
+#elif MINGW
+ char szCall[_MAX_PATH + 1], szWd[_MAX_PATH + 1], szCWd[_MAX_PATH + 1];
+ char *args[1], *cp = NULL;
+ int pid;
+ int idx = 0;
+
+ plibc_conv_to_win_path("/bin/gnunetd.exe", szCall);
+ plibc_conv_to_win_path("/bin", szWd);
+ _getcwd(szCWd, _MAX_PATH);
+
+ chdir(szWd);
+
+ if (daemonize == NO) {
+ args[0] = "-d";
+ idx = 1;
+
+ cp = getConfigurationString("GNUNET",
+ "GNUNETD-CONFIG");
+ if (cp) {
+ args[1] = "-c";
+ args[2] = cp;
+ idx=3;
+ }
+ }
+
+ args[idx] = NULL;
+ pid = spawnvp(_P_NOWAIT, szCall, (const char *const *) args);
+ chdir(szCWd);
+
+ FREENONNULL(cp);
+
+ return (daemonize == NO) ? pid : 0;
+#else
+ /* any system out there that does not support THIS!? */
+ system("gnunetd"); /* we may not have nice,
+ so let's be minimalistic here. */
+ return 0;
+#endif
+}
+
+
+/**
+ * Stop gnunetd
+ *
+ * Note that returning an error does NOT mean that
+ * gnunetd will continue to run (it may have been
+ * shutdown by something else in the meantime or
+ * crashed). Call checkDaemonRunning() frequently
+ * to check the status of gnunetd.
+ *
+ * Furthermore, note that this WILL potentially kill
+ * gnunetd processes on remote machines that cannot
+ * be restarted with startGNUnetDaemon!
+ *
+ * This function does NOT need the PID and will also
+ * kill daemonized gnunetd's.
+ *
+ * @return OK successfully stopped, SYSERR: error
+ */
+int stopGNUnetDaemon() {
+ GNUNET_TCP_SOCKET * sock;
+ CS_MESSAGE_HEADER csHdr;
+ int ret;
+
+ sock = getClientSocket();
+ if (sock == NULL)
+ return SYSERR;
+ csHdr.size
+ = htons(sizeof(CS_MESSAGE_HEADER));
+ csHdr.type
+ = htons(CS_PROTO_SHUTDOWN_REQUEST);
+ if (SYSERR == writeToSocket(sock,
+ &csHdr)) {
+ releaseClientSocket(sock);
+ return SYSERR;
+ }
+ if (SYSERR == readTCPResult(sock,
+ &ret)) {
+ releaseClientSocket(sock);
+ return SYSERR;
+ }
+ releaseClientSocket(sock);
+ return ret;
+}
+
+/**
+ * Wait until the gnunet daemon is
+ * running.
+ *
+ * @param timeout how long to wait at most
+ * @return OK if gnunetd is now running
+ */
+int waitForGNUnetDaemonRunning(cron_t timeout) {
+ timeout += cronTime(NULL);
+ while (OK != checkGNUnetDaemonRunning()) {
+ gnunet_util_sleep(100 * cronMILLIS);
+ if (timeout < cronTime(NULL))
+ return checkGNUnetDaemonRunning();
+ }
+ return OK;
+}
+
+/**
+ * Wait until the gnunet daemon (or any other CHILD process for that
+ * matter) with the given PID has terminated. Assumes that
+ * the daemon was started with startGNUnetDaemon in no-daemonize mode.
+ * On arbitrary PIDs, this function may fail unexpectedly.
+ *
+ * @return YES if gnunetd shutdown with
+ * return value 0, SYSERR if waitpid
+ * failed, NO if gnunetd shutdown with
+ * some error
+ */
+int waitForGNUnetDaemonTermination(int pid) {
+ pid_t p;
+ int status;
+
+ p = pid;
+ if (p != WAITPID(p, &status, 0)) {
+ LOG_STRERROR(LOG_ERROR, "waitpid");
+ return SYSERR;
+ }
+ if (WEXITSTATUS(status) == 0)
+ return YES;
+ else
+ return NO;
+}
+
+int termProcess(int pid) {
+#ifndef MINGW
+ return kill(pid, SIGTERM) == 0;
+#else
+ int ret;
+ DWORD dwExitCode = 0;
+
+ HANDLE hProc = OpenProcess(1, 0, pid);
+ GenerateConsoleCtrlEvent(CTRL_C_EVENT, pid);
+
+ WaitForSingleObject(hProc, 3000);
+
+ GetExitCodeProcess(hProc, &dwExitCode);
+ if(dwExitCode == STILL_ACTIVE) {
+ ret = TerminateProcess(hProc, 0);
+ }
+ else
+ ret = 1;
+
+ CloseHandle(hProc);
+
+ return ret;
+#endif
+}
+
+/* end of daemon.c */
Added: GNUnet/src/util/os/daemontest.c
===================================================================
--- GNUnet/src/util/os/daemontest.c 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/os/daemontest.c 2006-06-22 17:50:56 UTC (rev 3024)
@@ -0,0 +1,61 @@
+/*
+ This file is part of GNUnet.
+ (C) 2005 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 test/daemontest.c
+ * @brief Testcase for the daemon functions
+ * @author Christian Grothoff
+ */
+
+#include "gnunet_util.h"
+#include "platform.h"
+static int parseCommandLine(int argc,
+ char * argv[]) {
+ FREENONNULL(setConfigurationString("GNUNETD",
+ "_MAGIC_",
+ "NO"));
+ FREENONNULL(setConfigurationString("GNUNETD",
+ "LOGFILE",
+ NULL));
+ FREENONNULL(setConfigurationString("GNUNET",
+ "LOGLEVEL",
+ "NOTHING"));
+ FREENONNULL(setConfigurationString("GNUNET",
+ "GNUNETD-CONFIG",
+ "check.conf"));
+ return OK;
+}
+
+int main(int argc, char *argv[]) {
+ int daemon;
+
+ if (OK != initUtil(argc,
+ argv,
+ &parseCommandLine))
+ return -1;
+ daemon = startGNUnetDaemon(NO);
+ GNUNET_ASSERT(daemon > 0);
+ GNUNET_ASSERT(OK == waitForGNUnetDaemonRunning(30 * cronSECONDS));
+ GNUNET_ASSERT(OK == stopGNUnetDaemon());
+ GNUNET_ASSERT(OK == waitForGNUnetDaemonTermination(daemon));
+ doneUtil();
+ return 0;
+}
+
+/* end of deamontest.c */
Added: GNUnet/src/util/os/dso.c
===================================================================
--- GNUnet/src/util/os/dso.c 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/os/dso.c 2006-06-22 17:50:56 UTC (rev 3024)
@@ -0,0 +1,160 @@
+/*
+ This file is part of GNUnet
+ (C) 2002, 2003, 2004, 2005 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/dso.c
+ * @brief Methods to access dynamic shared objects (DSOs).
+ * @author Christian Grothoff
+ */
+
+#include "platform.h"
+#include "gnunet_util.h"
+
+static int using_valgrind;
+
+static char * old_dlsearchpath = NULL;
+
+/* using libtool, needs init! */
+void __attribute__ ((constructor)) gnc_ltdl_init(void) {
+ int err;
+
+ err = lt_dlinit ();
+ if (err > 0)
+ {
+#if DEBUG
+ fprintf(stderr,
+ _("Initialization of plugin mechanism failed: %s!\n"),
+ lt_dlerror());
+#endif
+ return;
+ }
+ if (lt_dlgetsearchpath() != NULL)
+ old_dlsearchpath = strdup(lt_dlgetsearchpath());
+ if (lt_dlgetsearchpath () == NULL)
+ lt_dladdsearchdir ("/usr/lib/GNUnet");
+ else if (strstr (lt_dlgetsearchpath (), "/usr/lib/GNUnet") == NULL)
+ lt_dladdsearchdir ("/usr/lib/GNUnet");
+ if (strstr (lt_dlgetsearchpath (), "/usr/local/lib/GNUnet") == NULL)
+ lt_dladdsearchdir ("/usr/local/lib/GNUnet");
+#ifdef PLUGIN_PATH
+ if (strstr (lt_dlgetsearchpath (), PLUGIN_PATH) == NULL)
+ lt_dladdsearchdir (PLUGIN_PATH);
+#endif
+}
+
+void __attribute__ ((destructor)) gnc_ltdl_fini(void) {
+ lt_dlsetsearchpath(old_dlsearchpath);
+ if (old_dlsearchpath != NULL) {
+ free(old_dlsearchpath);
+ old_dlsearchpath = NULL;
+ }
+ if (0 != using_valgrind)
+ lt_dlexit ();
+}
+
+
+static char * buildLibName(const char * prefix,
+ const char * dso) {
+ char * libname;
+
+ libname = MALLOC(strlen(dso) +
+ strlen(prefix) + 1);
+ libname[0] = '\0';
+ strcat(libname, prefix);
+ strcat(libname, dso);
+ return libname;
+}
+
+void * loadDynamicLibrary(const char * libprefix,
+ const char * dsoname) {
+ void * libhandle;
+ char * libname;
+
+ if (0 != lt_dlinit())
+ DIE_STRERROR("lt_dlinit");
+ /* finally, load the library */
+ libname = buildLibName(libprefix,
+ dsoname);
+ libhandle = lt_dlopenext(libname);
+ if (libhandle == NULL) {
+ LOG(LOG_ERROR,
+ _("`%s' failed for library `%s' at %s:%d with error: %s\n"),
+ "lt_dlopenext",
+ libname,
+ __FILE__, __LINE__,
+ lt_dlerror());
+ }
+ FREE(libname);
+ return libhandle;
+}
+
+void unloadDynamicLibrary(void * libhandle) {
+ /* when valgrinding, comment out these lines
+ to get decent traces for memory leaks on exit */
+ if (0 != getConfigurationInt("GNUNETD",
+ "VALGRIND")) {
+ lt_dlclose(libhandle);
+ if (0 != lt_dlexit())
+ LOG_STRERROR(LOG_WARNING, "lt_dlexit");
+ } else
+ using_valgrind = 1;
+}
+
+void * trybindDynamicMethod(void * libhandle,
+ const char * methodprefix,
+ const char * dsoname) {
+ char * initName;
+ void * mptr;
+
+ initName = MALLOC(strlen(dsoname) +
+ strlen(methodprefix) + 2);
+ initName[0] = '\0';
+ strcat(initName, "_");
+ strcat(initName, methodprefix);
+ strcat(initName, dsoname);
+ mptr = lt_dlsym(libhandle, &initName[1]);
+ if (mptr == NULL) {
+ /* try again with "_" prefix; some systems use that
+ variant. */
+ mptr = lt_dlsym(libhandle, initName);
+ }
+ FREE(initName);
+ return mptr;
+}
+
+void * bindDynamicMethod(void * libhandle,
+ const char * methodprefix,
+ const char * dsoname) {
+ void * mptr;
+
+ mptr = trybindDynamicMethod(libhandle,
+ methodprefix,
+ dsoname);
+ if (mptr == NULL)
+ LOG(LOG_ERROR,
+ _("`%s' failed to resolve method '%s%s' at %s:%d with error: %s\n"),
+ "lt_dlsym",
+ methodprefix, dsoname,
+ __FILE__, __LINE__,
+ lt_dlerror());
+ return mptr;
+}
+
+/* end of dso.c */
Added: GNUnet/src/util/os/osconfig.c
===================================================================
--- GNUnet/src/util/os/osconfig.c 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/os/osconfig.c 2006-06-22 17:50:56 UTC (rev 3024)
@@ -0,0 +1,403 @@
+/*
+ This file is part of GNUnet.
+ (C) 2004, 2005 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/osconfig.c
+ * @brief functions to read or change the OS configuration
+ * @author Nils Durner
+ */
+#include "platform.h"
+#include "gnunet_util.h"
+
+/**
+ * @brief Enumerate all network interfaces
+ * @param callback the callback function
+ */
+void enumNetworkIfs(void (*callback) (const char *, int, void *),
+ void * cls) {
+#ifdef MINGW
+ ListNICs(callback, cls);
+#else
+ char entry[11], *dst;
+ FILE *f;
+
+ if (system("ifconfig > /dev/null 2> /dev/null"))
+ if (system("/sbin/ifconfig > /dev/null 2> /dev/null") == 0)
+ f = popen("/sbin/ifconfig 2> /dev/null", "r");
+ else
+ f = NULL;
+ else
+ f = popen("ifconfig 2> /dev/null", "r");
+
+ if (!f)
+ return;
+
+ while(1)
+ {
+ int i = 0;
+ int c = fgetc(f);
+
+ if (c == EOF)
+ break;
+
+ dst = entry;
+
+ /* Read interface name until the first space (or colon under OS X) */
+ while (c != EOF && c != '\n' &&
+#ifdef OSX
+ c != ':'
+#else
+ c != ' '
+#endif
+ && i < 10)
+ {
+ *dst++ = c;
+ i++;
+ c = fgetc(f);
+ }
+ *dst = 0;
+
+ if (entry[0])
+ callback(entry, strcmp(entry, "eth0") == 0, cls);
+
+ while(c != '\n' && c != EOF)
+ c = fgetc(f);
+ }
+
+ pclose(f);
+#endif
+}
+
+/**
+ * @brief Checks if we can start GNUnet automatically
+ * @return 1 if yes, 0 otherwise
+ */
+int isOSAutostartCapable() {
+#ifdef LINUX
+ if (ACCESS("/usr/sbin/update-rc.d", X_OK) == 0) {
+ /* Debian */
+ if (ACCESS("/etc/init.d/", W_OK) == 0)
+ return 1;
+ }
+ return 0;
+#else
+ #ifdef WINDOWS
+ return 1;
+ #else
+ return 0;
+ #endif
+#endif
+}
+
+/**
+ * @brief Make GNUnet start automatically
+ * @param doAutoStart true to enable autostart, false to disable it
+ * @param username name of the user account to use
+ * @param groupname name of the group to use
+ * @return 0 on success
+ */
+int autostartService(int doAutoStart,
+ const char * username,
+ const char * groupname) {
+#ifdef WINDOWS
+ if (doAutoStart)
+ {
+ if (IsWinNT())
+ {
+ char *err = NULL;
+ DWORD dwErr = 0;
+
+ if (username && !strlen(username))
+ username = NULL;
+
+ /* Install service */
+ switch(InstallAsService(username))
+ {
+ case 0:
+ case 1:
+ break;
+ case 2:
+ if (GetLastError() != ERROR_SERVICE_EXISTS)
+ return 1;
+ case 3:
+ return 2;
+ default:
+ return -1;
+ }
+
+ /* Grant permissions to the GNUnet directory */
+ if ((!err || dwErr == ERROR_SERVICE_EXISTS) && username)
+ {
+ char szHome[_MAX_PATH + 1];
+
+ plibc_conv_to_win_path("/", szHome);
+
+ if (!AddPathAccessRights(szHome, username, GENERIC_ALL))
+ return 3;
+ }
+ }
+ else
+ {
+ char szPath[_MAX_PATH + 1];
+ HKEY hKey;
+
+ plibc_conv_to_win_path("/bin/gnunetd.exe", szPath);
+
+ if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+ "Software\\Microsoft\\Windows\\CurrentVersion\\Run", 0, KEY_EXECUTE,
+ &hKey) == ERROR_SUCCESS)
+ {
+ if (RegSetValueEx(hKey, "GNUnet", 0, REG_SZ, szPath, strlen(szPath)) !=
+ ERROR_SUCCESS)
+ return 4;
+
+ RegCloseKey(hKey);
+ }
+ else
+ return 4;
+ }
+ }
+ else
+ {
+ if (IsWinNT())
+ {
+ switch (UninstallService())
+ {
+ case 0:
+ case 1:
+ break;
+ case 2:
+ return 1;
+ case 3:
+ return 5;
+ case 4:
+ return 6;
+ default:
+ return -1;
+ }
+ }
+ else
+ {
+ HKEY hKey;
+
+ if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+ "Software\\Microsoft\\Windows\\CurrentVersion\\Run",
0, KEY_SET_VALUE,
+ &hKey) == ERROR_SUCCESS)
+ {
+ RegDeleteValue(hKey, "GNUnet");
+
+ RegCloseKey(hKey);
+ }
+ }
+ }
+#else
+ /* Unix */
+ if (ACCESS("/usr/sbin/update-rc.d", X_OK) == 0) {
+ /* Debian */
+ if (doAutoStart) {
+ struct stat buf;
+ if (STAT("/etc/init.d/gnunetd", &buf) == -1) {
+ /* create init file */
+ FILE *f = FOPEN("/etc/init.d/gnunetd", "w");
+ if (! f)
+ return 1;
+
+ fputs("#! /bin/sh\n"
+ "#\n"
+ "# Automatically created by gnunet-setup\n"
+ "#\n"
+ "\n"
+ "PATH=$PATH:" PREFIX_PATH "/bin"
+ "PIDFILE=/var/run/gnunetd/gnunetd.pid\n"
+ "\n"
+ "case \"$1\" in\n"
+ " start)\n"
+ " echo -n \"Starting GNUnet: \"\n"
+ " gnunetd\n"
+ " echo \"gnunetd\"\n"
+ " ;;\n"
+ " stop)\n"
+ " echo -n \"Stopping GNUnet: \"\n"
+ " kill `cat $PIDFILE`\n"
+ " echo \"gnunetd\"\n"
+ " ;;\n"
+ " reload)\n"
+ " echo -n \"Reloading GNUnet: \"\n"
+ " kill -HUP `cat $PIDFILE`\n"
+ " echo \"gnunetd\"\n"
+ " ;;\n"
+ " restart|force-reload)\n"
+ " echo \"Restarting GNUnet: gnunetd...\"\n"
+ " $0 stop\n"
+ " sleep 1\n"
+ " $0 start\n"
+ " ;;\n"
+ " *)\n"
+ " echo \"Usage: /etc/init.d/gnunetd
{start|stop|reload|restart|force-reload}\" >&2\n"
+ " exit 1\n"
+ " ;;\n"
+ "\n"
+ "esac\n"
+ "exit 0\n", f);
+ fclose(f);
+ CHMOD("/etc/init.d/gnunetd", S_IRWXU | S_IRGRP | S_IXGRP |
+ S_IROTH | S_IXOTH);
+ }
+ errno = system("/usr/sbin/update-rc.d gnunetd defaults");
+ if (errno != 0)
+ return 1;
+ }
+ else {
+ if ( (UNLINK("/etc/init.d/gnunetd") != -1) ||
+ (errno != ENOENT)) {
+ if (ACCESS("/usr/sbin/update-rc.d", X_OK) == 0) {
+ errno = system("/usr/sbin/update-rc.d gnunetd remove");
+ if (errno != 0) {
+ errno = EPERM;
+ return 1;
+ }
+ }
+ else {
+ errno = EPERM;
+ return 1;
+ }
+ }
+ else
+ return 0;
+ }
+ }
+ else
+ return 1;
+#endif
+ return 0;
+}
+
+/**
+ * @brief Checks if we can add an user for the GNUnet service
+ * @return 1 if yes, 0 otherwise
+ * @todo support for useradd(8)
+ */
+int isOSUserAddCapable(){
+#ifdef WINDOWS
+ return IsWinNT();
+#endif
+#ifdef LINUX
+ if (ACCESS("/usr/sbin/adduser", X_OK) == 0)
+ return (geteuid() == 0);
+ else
+ /* TODO: useradd */
+#endif
+ return 0;
+}
+
+/**
+ * @brief Checks if we can add a group for the GNUnet service
+ * @return 1 if yes, 0 otherwise
+ * @todo support for groupadd(8)
+ */
+int isOSGroupAddCapable() {
+#ifdef LINUX
+ if (ACCESS("/usr/sbin/addgroup", X_OK) == 0) {
+ return (geteuid() == 0);
+ }
+ /* TODO: groupadd */
+ else
+#endif
+ return 0;
+}
+
+/**
+ * @brief Add a service account for GNUnet
+ * @param group the group of the new user
+ * @param name the name of the new user
+ * @return 0 on success
+ */
+int createGroupUser(const char *group_name,
+ const char *user_name) {
+ int haveGroup;
+
+ if ( (user_name == NULL) ||
+ (0 == strlen(user_name)) )
+ return 0;
+
+#ifdef WINDOWS
+ if (IsWinNT())
+ {
+ return CreateServiceAccount(user_name, "GNUnet service
account");
+ }
+#else
+
+ if (ACCESS("/usr/sbin/adduser", X_OK) == 0) {
+ /* Debian */
+ /* TODO: FreeBSD?
http://www.freebsd.org/cgi/man.cgi?query=adduser&sektion=8 */
+ char *cmd;
+
+ haveGroup = group_name && strlen(group_name) > 0;
+ cmd = MALLOC(haveGroup ? strlen(group_name) : 0 +
strlen(user_name) + 64);
+
+ if (haveGroup) {
+ sprintf(cmd, "/usr/sbin/addgroup --quiet --system %s",
group_name);
+ system(cmd);
+ }
+
+ sprintf(cmd, "/usr/sbin/adduser --quiet --system %s %s "
+ "--no-create-home %s", haveGroup ? "--ingroup" : "",
+ haveGroup ? group_name : "", user_name);
+ system(cmd);
+
+ FREE(cmd);
+ }
+ /* TODO: useradd */
+ else
+ return 1;
+#endif
+
+ return 0;
+}
+
+char *winErrorStr(const char *prefix, int dwErr)
+{
+#ifdef WINDOWS
+ 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 = "";
+ }
+
+ mem = strlen(err) + strlen(prefix) + 20;
+ ret = (char *) malloc(mem);
+
+ snprintf(ret, mem, "%s: %s (#%u)", prefix, err, dwErr);
+
+ LocalFree(err);
+
+ return ret;
+#else
+ return NULL;
+#endif
+}
+
+
+/* end of osconfig.c */
Added: GNUnet/src/util/os/statuscalls.c
===================================================================
--- GNUnet/src/util/os/statuscalls.c 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/os/statuscalls.c 2006-06-22 17:50:56 UTC (rev 3024)
@@ -0,0 +1,873 @@
+/*
+ This file is part of GNUnet.
+ (C) 2001, 2002, 2003, 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/statuscalls.c
+ * @brief calls to determine current network and CPU load
+ * @author Tzvetan Horozov
+ * @author Christian Grothoff
+ * @author Igor Wronsky
+ *
+ * Status calls implementation for load management.
+ */
+
+#include "platform.h"
+#include "gnunet_util.h"
+
+#if SOLARIS
+#if HAVE_KSTAT_H
+#include <kstat.h>
+#endif
+#if HAVE_SYS_SYSINFO_H
+#include <sys/sysinfo.h>
+#endif
+#if HAVE_KVM_H
+#include <kvm.h>
+#endif
+#endif
+#if SOMEBSD
+#if HAVE_KVM_H
+#include <kvm.h>
+#endif
+#endif
+
+#define DEBUG_STATUSCALLS NO
+
+/**
+ * where to read network interface information from
+ * under Linux
+ */
+#define PROC_NET_DEV "/proc/net/dev"
+
+typedef struct {
+ char * name;
+ unsigned long long last_in;
+ unsigned long long last_out;
+} NetworkStats;
+
+/**
+ * Traffic counter for only gnunetd traffic.
+ */
+static NetworkStats globalTrafficBetweenProc;
+
+/**
+ * tracking
+ */
+static NetworkStats * ifcs;
+
+/**
+ * how many interfaces do we have?
+ */
+static unsigned int ifcsSize;
+
+/**
+ * Current load of the machine, -1 for error
+ */
+static int currentLoad;
+
+/**
+ * Maximum bandwidth (down) as per config.
+ */
+static int maxNetDownBPS;
+
+/**
+ * Maximum bandwidth (up) as per config.
+ */
+static int maxNetUpBPS;
+
+/**
+ * Maximum load as per config.
+ */
+static int maxCPULoad;
+
+/**
+ * How to measure traffic (YES == only gnunetd,
+ * NO == try to include all apps)
+ */
+static int useBasicMethod = YES;
+
+/**
+ * Lock.
+ */
+static Mutex statusMutex;
+
+static int initialized_ = NO;
+
+#ifdef LINUX
+static FILE * proc_stat;
+static FILE * proc_net_dev;
+#endif
+
+/**
+ * Increment the number of bytes sent. Transports should use this
+ * so that statuscalls module can measure gnunet traffic usage between
+ * calls to /proc.
+ *
+ * Note: the caller doesn't know what interface it is attached to,
+ * so this type of bandwidth limitation is always global (for all
+ * network interfaces).
+ */
+void incrementBytesSent(unsigned long long delta) {
+ if (initialized_ == NO)
+ return;
+ MUTEX_LOCK(&statusMutex);
+ globalTrafficBetweenProc.last_out += delta;
+ MUTEX_UNLOCK(&statusMutex);
+}
+
+void incrementBytesReceived(unsigned long long delta) {
+ if (initialized_ == NO)
+ return;
+ MUTEX_LOCK(&statusMutex);
+ globalTrafficBetweenProc.last_in += delta;
+ MUTEX_UNLOCK(&statusMutex);
+}
+
+/**
+ * Reset the traffic counters for GNUnet traffic between
+ * systemwide readings.
+ */
+static void resetBetweenProc() {
+ globalTrafficBetweenProc.last_in = 0;
+ globalTrafficBetweenProc.last_out = 0;
+}
+
+#define MAX_PROC_LINE 5000
+
+static void updateInterfaceTraffic() {
+#ifdef LINUX
+ unsigned long long rxnew;
+ unsigned long long txnew;
+ char line[MAX_PROC_LINE];
+ char * data;
+ int i;
+ int found;
+
+ MUTEX_LOCK(&statusMutex);
+ if (proc_net_dev != NULL) {
+ found = 0;
+ rewind(proc_net_dev);
+ fflush(proc_net_dev);
+ /* Parse the line matching the interface ('eth0') */
+ while (! feof(proc_net_dev) ) {
+ if (NULL == fgets(line,
+ MAX_PROC_LINE,
+ proc_net_dev))
+ break;
+ for (i=0;i<ifcsSize;i++) {
+ if (NULL != strstr(line, ifcs[i].name) ) {
+ data = strchr(line, ':');
+ if (data == NULL)
+ continue;
+ data++;
+ if (2 != SSCANF(data,
+ "%llu %*s %*s %*s %*s %*s %*s %*s %llu",
+ &rxnew,
+ &txnew)) {
+ LOG(LOG_ERROR,
+ _("Failed to parse interface data from `%s' at %s:%d.\n"),
+ PROC_NET_DEV,
+ __FILE__,
+ __LINE__);
+ continue;
+ }
+ ifcs[i].last_in = rxnew;
+ ifcs[i].last_out = txnew;
+ resetBetweenProc();
+ break;
+ }
+ }
+ }
+ }
+ MUTEX_UNLOCK(&statusMutex);
+
+#elif MINGW
+ unsigned long long rxnew;
+ unsigned long long txnew;
+ int i;
+ PMIB_IFTABLE pTable;
+ DWORD dwIfIdx;
+ unsigned long long l;
+ BYTE bPhysAddr[MAXLEN_PHYSADDR];
+ int iLine = 0;
+ char line[MAX_PROC_LINE];
+ FILE * command;
+
+ MUTEX_LOCK(&statusMutex);
+ /* Win 98 and NT SP 4 */
+ if (GNGetIfEntry) {
+ EnumNICs(&pTable, NULL);
+ for (i=0;i<ifcsSize;i++) {
+ for (dwIfIdx=0; dwIfIdx < pTable->dwNumEntries; dwIfIdx++) {
+ l = _atoi64(ifcs[i].name);
+
+ memset(bPhysAddr,
+ 0,
+ MAXLEN_PHYSADDR);
+ memcpy(bPhysAddr,
+ pTable->table[dwIfIdx].bPhysAddr,
+ pTable->table[dwIfIdx].dwPhysAddrLen);
+
+ if (0 == memcmp(bPhysAddr,
+ &l,
+ sizeof(unsigned long long))) {
+ ifcs[i].last_in
+ = pTable->table[dwIfIdx].dwInOctets;
+ ifcs[i].last_out
+ = pTable->table[dwIfIdx].dwOutOctets;
+ resetBetweenProc();
+ break;
+ }
+ }
+ }
+ GlobalFree(pTable);
+ } else { /* Win 95 */
+ if ( ( command = popen("netstat -e", "rt") ) == NULL ) {
+ LOG_FILE_STRERROR(LOG_ERROR,
+ "popen",
+ "netstat -e");
+ MUTEX_UNLOCK(&statusMutex);
+ return;
+ }
+ while (!feof(command)) {
+ if (NULL == fgets(line,
+ MAX_PROC_LINE,
+ command))
+ break;
+ /* PORT-ME: any way to do this per-ifc? */
+ if (iLine == 1) {
+ sscanf("%*s%i%i",
+ &rxnew,
+ &txnew);
+ ifcs[0].last_in
+ = rxnew;
+ ifcs[0].last_out
+ = txnew;
+ resetBetweenProc();
+ break;
+ }
+ iLine++;
+ }
+ pclose(command);
+ }
+ MUTEX_UNLOCK(&statusMutex);
+#else
+ /* PORT-ME! */
+#endif
+}
+
+/**
+ * The following routine returns a number between 0-100 (can be larger
+ * than 100 if the load is > 1) which indicates the percentage CPU
+ * usage.
+ *
+ * Before its first invocation the method initStatusCalls() must be called.
+ * If there is an error the method returns -1
+ */
+static void updateCpuUsage(){
+ if (initialized_ == NO) {
+ currentLoad = -1;
+ return;
+ }
+ MUTEX_LOCK(&statusMutex);
+
+#ifdef LINUX
+ /* under linux, first try %idle/usage using /proc/stat;
+ if that does not work, disable /proc/stat for the future
+ by closing the file and use the next-best method. */
+ if (proc_stat != NULL) {
+ static unsigned long long last_cpu_results[4] = { 0, 0, 0, 0 };
+ static int have_last_cpu = NO;
+ char line[128];
+ unsigned long long user_read, system_read, nice_read, idle_read;
+ unsigned long long user, system, nice, idle;
+ unsigned long long usage_time=0, total_time=1;
+
+ /* Get the first line with the data */
+ rewind(proc_stat);
+ fflush(proc_stat);
+ if (NULL == fgets(line, 128, proc_stat)) {
+ LOG_FILE_STRERROR(LOG_ERROR,
+ "fgets",
+ "/proc/stat");
+ fclose(proc_stat);
+ proc_stat = NULL; /* don't try again */
+ } else {
+ if (sscanf(line, "%*s %llu %llu %llu %llu",
+ &user_read,
+ &system_read,
+ &nice_read,
+ &idle_read) != 4) {
+ LOG_FILE_STRERROR(LOG_ERROR,
+ "fgets-sscanf",
+ "/proc/stat");
+ fclose(proc_stat);
+ proc_stat = NULL; /* don't try again */
+ have_last_cpu = NO;
+ } else {
+ /* Store the current usage*/
+ user = user_read - last_cpu_results[0];
+ system = system_read - last_cpu_results[1];
+ nice = nice_read - last_cpu_results[2];
+ idle = idle_read - last_cpu_results[3];
+ /* Calculate the % usage */
+ if ( (user + system + nice + idle) > 0) {
+ usage_time = user + system + nice;
+ total_time = usage_time + idle;
+ }
+ if ( (total_time > 0) &&
+ (have_last_cpu == YES) )
+ currentLoad = (100 * usage_time) / total_time;
+ else
+ currentLoad = -1;
+ /* Store the values for the next calculation*/
+ last_cpu_results[0] = user_read;
+ last_cpu_results[1] = system_read;
+ last_cpu_results[2] = nice_read;
+ last_cpu_results[3] = idle_read;
+ have_last_cpu = YES;
+ MUTEX_UNLOCK(&statusMutex);
+ return;
+ }
+ }
+ }
+#endif
+
+ /* try kstat (Solaris only) */
+#if SOLARIS && HAVE_KSTAT_H && HAVE_SYS_SYSINFO_H
+ {
+ static long long last_idlecount;
+ static long long last_totalcount;
+ static int kstat_once; /* if open fails, don't keep
+ trying */
+ kstat_ctl_t * kc;
+ kstat_t * khelper;
+ long long idlecount;
+ long long totalcount;
+ long long deltaidle;
+ long long deltatotal;
+
+ if (kstat_once == 1)
+ goto ABORT_KSTAT;
+ kc = kstat_open();
+ if (kc == NULL) {
+ LOG_STRERROR(LOG_ERROR, "kstat_open");
+ goto ABORT_KSTAT;
+ }
+
+ idlecount = 0;
+ totalcount = 0;
+ for (khelper = kc->kc_chain;
+ khelper != NULL;
+ khelper = khelper->ks_next) {
+ cpu_stat_t stats;
+
+ if (0 != strncmp(khelper->ks_name,
+ "cpu_stat",
+ strlen("cpu_stat")) )
+ continue;
+ if (khelper->ks_data_size > sizeof(cpu_stat_t))
+ continue; /* better save then sorry! */
+ if (-1 != kstat_read(kc, khelper, &stats)) {
+ idlecount
+ += stats.cpu_sysinfo.cpu[CPU_IDLE];
+ totalcount
+ += stats.cpu_sysinfo.cpu[CPU_IDLE] +
+ stats.cpu_sysinfo.cpu[CPU_USER] +
+ stats.cpu_sysinfo.cpu[CPU_KERNEL] +
+ stats.cpu_sysinfo.cpu[CPU_WAIT];
+ }
+ }
+ if (0 != kstat_close(kc))
+ LOG_STRERROR(LOG_ERROR, "kstat_close");
+ if ( (idlecount == 0) &&
+ (totalcount == 0) )
+ goto ABORT_KSTAT; /* no stats found => abort */
+ deltaidle = idlecount - last_idlecount;
+ deltatotal = totalcount - last_totalcount;
+ if ( (deltatotal > 0) &&
+ (last_totalcount > 0) )
+ currentLoad = (int) (100 * deltaidle / deltatotal);
+ else
+ currentLoad = -1;
+ last_idlecount = idlecount;
+ last_totalcount = totalcount;
+ MUTEX_UNLOCK(&statusMutex);
+ return;
+ ABORT_KSTAT:
+ kstat_once = 1; /* failed, don't try again */
+ }
+#endif
+
+ /* insert methods better than getloadavg for
+ other platforms HERE! */
+
+ /* ok, maybe we have getloadavg on this platform */
+#if HAVE_GETLOADAVG
+ {
+ static int warnOnce = 0;
+ double loadavg;
+ if (1 != getloadavg(&loadavg, 1)) {
+ /* only warn once, if there is a problem with
+ getloadavg, we're going to hit it frequently... */
+ if (warnOnce == 0) {
+ warnOnce = 1;
+ LOG_STRERROR(LOG_ERROR, "getloadavg");
+ }
+ currentLoad = -1;
+ } else {
+ /* success with getloadavg */
+ currentLoad = (int) (100 * loadavg);
+ MUTEX_UNLOCK(&statusMutex);
+ return;
+ }
+ }
+#endif
+
+#if MINGW
+ /* Win NT? */
+ if (GNNtQuerySystemInformation) {
+ static double dLastKernel;
+ static double dLastIdle;
+ static double dLastUser;
+ double dKernel;
+ double dIdle;
+ double dUser;
+ double dDiffKernel;
+ double dDiffIdle;
+ double dDiffUser;
+ SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION theInfo;
+
+ if (GNNtQuerySystemInformation(SystemProcessorPerformanceInformation,
+ &theInfo,
+ sizeof(theInfo),
+ NULL) == NO_ERROR) {
+ /* PORT-ME MINGW: Multi-processor? */
+ dKernel = Li2Double(theInfo.KernelTime);
+ dIdle = Li2Double(theInfo.IdleTime);
+ dUser = Li2Double(theInfo.UserTime);
+ dDiffKernel = dKernel - dLastKernel;
+ dDiffIdle = dIdle - dLastIdle;
+ dDiffUser = dUser - dLastUser;
+
+ if ( ( (dDiffKernel + dDiffUser) > 0) &&
+ (dLastIdle + dLastKernel + dLastUser > 0) )
+ currentLoad = 100.0 - (dDiffIdle / (dDiffKernel + dDiffUser)) * 100.0;
+ else
+ currentLoad = -1; /* don't know (yet) */
+
+ dLastKernel = dKernel;
+ dLastIdle = dIdle;
+ dLastUser = dUser;
+
+ MUTEX_UNLOCK(&statusMutex);
+ return;
+ } else {
+ /* only warn once, if there is a problem with
+ NtQuery..., we're going to hit it frequently... */
+ static int once;
+ if (once == 0) {
+ once = 1;
+ LOG(LOG_ERROR,
+ _("Cannot query the CPU usage (Windows NT).\n"));
+ }
+ }
+ } else { /* Win 9x */
+ HKEY hKey;
+ DWORD dwDataSize, dwType, dwDummy;
+
+ /* Start query */
+ if (RegOpenKeyEx(HKEY_DYN_DATA,
+ "PerfStats\\StartSrv",
+ 0,
+ KEY_ALL_ACCESS,
+ &hKey) != ERROR_SUCCESS) {
+ /* only warn once */
+ static int once = 0;
+ if (once == 0) {
+ once = 1;
+ LOG(LOG_ERROR,
+ _("Cannot query the CPU usage (Win 9x)\n"));
+ }
+ }
+
+ RegOpenKeyEx(HKEY_DYN_DATA,
+ "PerfStats\\StartStat",
+ 0,
+ KEY_ALL_ACCESS,
+ &hKey);
+ dwDataSize = sizeof(dwDummy);
+ RegQueryValueEx(hKey,
+ "KERNEL\\CPUUsage",
+ NULL,
+ &dwType,
+ (LPBYTE) &dwDummy,
+ &dwDataSize);
+ RegCloseKey(hKey);
+
+ /* Get CPU usage */
+ RegOpenKeyEx(HKEY_DYN_DATA,
+ "PerfStats\\StatData",
+ 0,
+ KEY_ALL_ACCESS,
+ &hKey);
+ dwDataSize = sizeof(currentLoad);
+ RegQueryValueEx(hKey,
+ "KERNEL\\CPUUsage",
+ NULL,
+ &dwType,
+ (LPBYTE) ¤tLoad,
+ &dwDataSize);
+ RegCloseKey(hKey);
+
+ /* Stop query */
+ RegOpenKeyEx(HKEY_DYN_DATA,
+ "PerfStats\\StopStat",
+ 0,
+ KEY_ALL_ACCESS,
+ &hKey);
+ RegOpenKeyEx(HKEY_DYN_DATA,
+ "PerfStats\\StopSrv",
+ 0,
+ KEY_ALL_ACCESS,
+ &hKey);
+ dwDataSize = sizeof(dwDummy);
+ RegQueryValueEx(hKey,
+ "KERNEL\\CPUUsage",
+ NULL,
+ &dwType,
+ (LPBYTE)&dwDummy,
+ &dwDataSize);
+ RegCloseKey(hKey);
+
+ MUTEX_UNLOCK(&statusMutex);
+ return;
+ }
+#endif
+
+ /* loadaverage not defined and no platform
+ specific alternative defined
+ => default: error
+ */
+ currentLoad = -1;
+ MUTEX_UNLOCK(&statusMutex);
+}
+
+static void cronLoadUpdate(void * unused) {
+ updateCpuUsage();
+ if (! useBasicMethod)
+ updateInterfaceTraffic();
+}
+
+/**
+ * Re-read the configuration for statuscalls.
+ */
+static void resetStatusCalls() {
+ char * interfaces;
+ int i;
+ int numInterfaces;
+
+ MUTEX_LOCK(&statusMutex);
+ for (i=0;i<ifcsSize;i++)
+ FREE(ifcs[i].name);
+ GROW(ifcs,
+ ifcsSize,
+ 0);
+ interfaces
+ = getConfigurationString("LOAD",
+ "INTERFACES");
+ /* fail if config-file is incomplete */
+ if ( (interfaces == NULL) ||
+ (strlen(interfaces) == 0) ) {
+ LOG(LOG_ERROR,
+ _("No network interfaces defined in configuration section `%s' under
`%s'!\n"),
+ "LOAD",
+ "INTERFACES");
+ } else {
+ /* The string containing the interfaces is formatted in the following way:
+ * each comma is replaced by '\0' and the pointers to the beginning of
every
+ * interface are stored
+ */
+ numInterfaces = 1;
+ for (i=strlen(interfaces)-1;i>=0;i--)
+ if (interfaces[i] == ',')
+ numInterfaces++;
+ GROW(ifcs,
+ ifcsSize,
+ numInterfaces);
+ for (i=strlen(interfaces)-1;i>=0;i--) {
+ if (interfaces[i] == ',') {
+ ifcs[--numInterfaces].name = STRDUP(&interfaces[i+1]);
+ numInterfaces++;
+ interfaces[i] = '\0';
+ }
+ }
+ ifcs[--numInterfaces].name = STRDUP(interfaces);
+ GNUNET_ASSERT(numInterfaces == 0);
+ for (i=0;i<ifcsSize;i++) {
+ ifcs[i].last_in = 0;
+ ifcs[i].last_out = 0;
+ }
+ }
+ FREENONNULL(interfaces);
+ useBasicMethod
+ = testConfigurationString("LOAD",
+ "BASICLIMITING",
+ "YES");
+ maxNetDownBPS
+ = getConfigurationInt("LOAD",
+ "MAXNETDOWNBPSTOTAL");
+ if (maxNetDownBPS == 0)
+ maxNetDownBPS = 50000;
+ maxNetUpBPS
+ = getConfigurationInt("LOAD",
+ "MAXNETUPBPSTOTAL");
+ if (maxNetUpBPS == 0)
+ maxNetUpBPS = 50000;
+ maxCPULoad
+ = getConfigurationInt("LOAD",
+ "MAXCPULOAD");
+ if (maxCPULoad == 0)
+ maxCPULoad = 100;
+ MUTEX_UNLOCK(&statusMutex);
+}
+
+
+
+/**
+ * Get the load of the network relative to what is allowed.
+ * @return the network load as a percentage of allowed
+ * (100 is equivalent to full load)
+ */
+int getNetworkLoadUp() {
+ static unsigned long long overload;
+ static unsigned long long lastSum;
+ static cron_t lastCall;
+ static int lastValue;
+ cron_t now;
+ unsigned long long maxExpect;
+ unsigned long long currentLoadSum;
+ int i;
+ int ret;
+
+ MUTEX_LOCK(&statusMutex);
+ currentLoadSum = globalTrafficBetweenProc.last_out;
+ for (i=0;i<ifcsSize;i++)
+ currentLoadSum += ifcs[i].last_out;
+ cronTime(&now);
+ if ( (lastSum > currentLoadSum) ||
+ (lastSum == 0) ||
+ (now < lastCall) ) {
+ /* integer overflow or first datapoint; since we cannot tell where
+ / by how much the overflow happened, all we can do is ignore
+ this datapoint. So we return -1 -- AND reset lastSum / lastCall. */
+ lastSum = currentLoadSum;
+ lastCall = now;
+ MUTEX_UNLOCK(&statusMutex);
+ return -1;
+ }
+ if (maxNetUpBPS == 0) {
+ MUTEX_UNLOCK(&statusMutex);
+ return -1;
+ }
+ if (now - lastCall < cronSECONDS) {
+ /* increase last load proportional to difference in
+ data transmitted and in relation to the limit */
+ ret = lastValue + 100 * (currentLoadSum - lastSum) / maxNetUpBPS;
+ MUTEX_UNLOCK(&statusMutex);
+ return ret;
+ }
+ currentLoadSum -= lastSum;
+ lastSum += currentLoadSum;
+ currentLoadSum += overload;
+ maxExpect = ( (now - lastCall) * maxNetUpBPS ) / cronSECONDS;
+ lastCall = now;
+ if (currentLoadSum < maxExpect)
+ overload = 0;
+ else
+ overload = currentLoadSum - maxExpect;
+ lastValue = currentLoadSum * 100 / maxExpect;
+ ret = lastValue;
+ MUTEX_UNLOCK(&statusMutex);
+ return ret;
+}
+
+/**
+ * Get the load of the network relative to what is allowed.
+ * @return the network load as a percentage of allowed
+ * (100 is equivalent to full load)
+ */
+int getNetworkLoadDown() {
+ static unsigned long long overload;
+ static unsigned long long lastSum;
+ static cron_t lastCall;
+ static int lastValue;
+ cron_t now;
+ unsigned long long maxExpect;
+ unsigned long long currentLoadSum;
+ int i;
+ int ret;
+
+ MUTEX_LOCK(&statusMutex);
+ currentLoadSum = globalTrafficBetweenProc.last_in;
+ for (i=0;i<ifcsSize;i++)
+ currentLoadSum += ifcs[i].last_in;
+ cronTime(&now);
+ if ( (lastSum > currentLoadSum) ||
+ (lastSum == 0) ||
+ (now < lastCall) ) {
+ /* integer overflow or first datapoint; since we cannot tell where
+ / by how much the overflow happened, all we can do is ignore
+ this datapoint. So we return -1 -- AND reset lastSum / lastCall. */
+ lastSum = currentLoadSum;
+ lastCall = now;
+ MUTEX_UNLOCK(&statusMutex);
+ return -1;
+ }
+ if (maxNetDownBPS == 0) {
+ MUTEX_UNLOCK(&statusMutex);
+ return -1;
+ }
+ if (now - lastCall < cronSECONDS) {
+ /* increase last load proportional to difference in
+ data transmitted and in relation to the limit */
+ ret = lastValue + 100 * (currentLoadSum - lastSum) / maxNetDownBPS;
+ MUTEX_UNLOCK(&statusMutex);
+ return ret;
+ }
+ currentLoadSum -= lastSum;
+ lastSum += currentLoadSum;
+ currentLoadSum += overload;
+ maxExpect = ( (now - lastCall) * maxNetDownBPS ) / cronSECONDS;
+ lastCall = now;
+ if (currentLoadSum < maxExpect)
+ overload = 0;
+ else
+ overload = currentLoadSum - maxExpect;
+ lastValue = currentLoadSum * 100 / maxExpect;
+ ret = lastValue;
+ MUTEX_UNLOCK(&statusMutex);
+ return ret;
+}
+
+/**
+ * Get the load of the CPU relative to what is allowed.
+ * @return the CPU load as a percentage of allowed
+ * (100 is equivalent to full load)
+ */
+int getCPULoad() {
+ static int lastRet = -1;
+ static cron_t lastCall;
+ int ret;
+ cron_t now;
+
+ if (initialized_ == NO) {
+ lastRet = -1;
+ return -1;
+ }
+ MUTEX_LOCK(&statusMutex);
+ ret = (100 * currentLoad) / maxCPULoad;
+
+ cronTime(&now);
+ if ( (lastRet != -1) &&
+ (now - lastCall < 250 * cronMILLIS) ) {
+ /* use smoothing, but do NOT update lastRet at frequencies higher
+ than 250ms; this makes the smoothing (mostly) independent from
+ the frequency at which getCPULoad is called. */
+ ret = (ret + 7 * lastRet)/8;
+ MUTEX_UNLOCK(&statusMutex);
+ return ret;
+ }
+
+ /* for CPU, we don't do the 'fast increase' since CPU is much
+ more jitterish to begin with */
+ if (lastRet != -1)
+ ret = (ret + 7 * lastRet)/8;
+ lastRet = ret;
+ lastCall = now;
+ MUTEX_UNLOCK(&statusMutex);
+ return ret;
+}
+
+/**
+ * The following method is called in order to initialize the status calls
+ * routines. After that it is safe to call each of the status calls separately
+ * @return OK on success and SYSERR on error (or calls errexit).
+ */
+void initStatusCalls() {
+#ifdef LINUX
+ proc_stat = fopen("/proc/stat", "r");
+ if (NULL == proc_stat)
+ LOG_FILE_STRERROR(LOG_ERROR,
+ "fopen",
+ "/proc/stat");
+ proc_net_dev = fopen(PROC_NET_DEV, "r");
+ if (NULL == proc_net_dev)
+ LOG_FILE_STRERROR(LOG_ERROR,
+ "fopen",
+ PROC_NET_DEV);
+#endif
+ MUTEX_CREATE_RECURSIVE(&statusMutex);
+ initialized_ = YES;
+ resetBetweenProc();
+ registerConfigurationUpdateCallback(&resetStatusCalls);
+ resetStatusCalls();
+ cronLoadUpdate(NULL);
+ addCronJob(&cronLoadUpdate,
+ 10 * cronSECONDS,
+ 10 * cronSECONDS,
+ NULL);
+ getNetworkLoadUp();
+ getNetworkLoadDown();
+}
+
+/**
+ * Shutdown the status calls module.
+ */
+void doneStatusCalls() {
+ int i;
+
+ if (initialized_ == NO)
+ return;
+ unregisterConfigurationUpdateCallback(&resetStatusCalls);
+ delCronJob(&cronLoadUpdate,
+ 10 * cronSECONDS,
+ NULL);
+ initialized_ = NO;
+#ifdef LINUX
+ if (proc_stat != NULL) {
+ fclose(proc_stat);
+ proc_stat = NULL;
+ }
+ if (proc_net_dev != NULL) {
+ fclose(proc_net_dev);
+ proc_net_dev = NULL;
+ }
+#endif
+ for (i=0;i<ifcsSize;i++)
+ FREE(ifcs[i].name);
+ GROW(ifcs,
+ ifcsSize,
+ 0);
+ MUTEX_DESTROY(&statusMutex);
+}
+
+
+/* end of statuscalls.c */
Added: GNUnet/src/util/os/statuscallstest.c
===================================================================
--- GNUnet/src/util/os/statuscallstest.c 2006-06-22 17:39:19 UTC (rev
3023)
+++ GNUnet/src/util/os/statuscallstest.c 2006-06-22 17:50:56 UTC (rev
3024)
@@ -0,0 +1,76 @@
+/**
+ * @file util/statuscallstest.c
+ * @brief testcase for util/statuscalls.c
+ */
+
+#include "gnunet_util.h"
+#include "platform.h"
+
+/**
+ * Perform option parsing from the command line.
+ */
+static int parseCommandLine(int argc,
+ char * argv[]) {
+ char c;
+
+ FREENONNULL(setConfigurationString("GNUNETD",
+ "_MAGIC_",
+ "YES"));
+ FREENONNULL(setConfigurationString("GNUNETD",
+ "GNUNETD_HOME",
+ "/tmp/gnunet_test/"));
+ FREENONNULL(setConfigurationString("FILES",
+ "gnunet.conf",
+ "check.conf"));
+ while (1) {
+ int option_index = 0;
+ static struct GNoption long_options[] = {
+ { "config", 1, 0, 'c' },
+ { 0,0,0,0 }
+ };
+
+ c = GNgetopt_long(argc,
+ argv,
+ "c:",
+ long_options,
+ &option_index);
+
+ if (c == -1)
+ break; /* No more flags to process*/
+
+ switch(c) {
+ case 'c':
+ FREENONNULL(setConfigurationString("FILES",
+ "gnunet.conf",
+ GNoptarg));
+ break;
+ } /* end of parsing commandline */
+ }
+ return OK;
+}
+
+int main(int argc, char * argv[]){
+ int ret;
+ cron_t start;
+
+ if (OK != initUtil(argc, argv, &parseCommandLine))
+ errexit("Error during initialization!\n");
+ startCron();
+ /* need to run each phase for more than 10s since
+ statuscalls only refreshes that often... */
+ cronTime(&start);
+ while (start + 12 * cronSECONDS > cronTime(NULL))
+ sleep(1);
+ cronTime(&start);
+ ret = getCPULoad();
+ while (start + 12 * cronSECONDS > cronTime(NULL))
+ sqrt(245.2523); /* do some processing to drive load up */
+ if (ret > getCPULoad())
+ printf("busy loop decreased CPU load: %d < %d.\n",
+ ret,
+ getCPULoad());
+ stopCron();
+ doneUtil();
+
+ return 0;
+}
Deleted: GNUnet/src/util/osconfig.c
===================================================================
--- GNUnet/src/util/osconfig.c 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/osconfig.c 2006-06-22 17:50:56 UTC (rev 3024)
@@ -1,403 +0,0 @@
-/*
- This file is part of GNUnet.
- (C) 2004, 2005 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/osconfig.c
- * @brief functions to read or change the OS configuration
- * @author Nils Durner
- */
-#include "platform.h"
-#include "gnunet_util.h"
-
-/**
- * @brief Enumerate all network interfaces
- * @param callback the callback function
- */
-void enumNetworkIfs(void (*callback) (const char *, int, void *),
- void * cls) {
-#ifdef MINGW
- ListNICs(callback, cls);
-#else
- char entry[11], *dst;
- FILE *f;
-
- if (system("ifconfig > /dev/null 2> /dev/null"))
- if (system("/sbin/ifconfig > /dev/null 2> /dev/null") == 0)
- f = popen("/sbin/ifconfig 2> /dev/null", "r");
- else
- f = NULL;
- else
- f = popen("ifconfig 2> /dev/null", "r");
-
- if (!f)
- return;
-
- while(1)
- {
- int i = 0;
- int c = fgetc(f);
-
- if (c == EOF)
- break;
-
- dst = entry;
-
- /* Read interface name until the first space (or colon under OS X) */
- while (c != EOF && c != '\n' &&
-#ifdef OSX
- c != ':'
-#else
- c != ' '
-#endif
- && i < 10)
- {
- *dst++ = c;
- i++;
- c = fgetc(f);
- }
- *dst = 0;
-
- if (entry[0])
- callback(entry, strcmp(entry, "eth0") == 0, cls);
-
- while(c != '\n' && c != EOF)
- c = fgetc(f);
- }
-
- pclose(f);
-#endif
-}
-
-/**
- * @brief Checks if we can start GNUnet automatically
- * @return 1 if yes, 0 otherwise
- */
-int isOSAutostartCapable() {
-#ifdef LINUX
- if (ACCESS("/usr/sbin/update-rc.d", X_OK) == 0) {
- /* Debian */
- if (ACCESS("/etc/init.d/", W_OK) == 0)
- return 1;
- }
- return 0;
-#else
- #ifdef WINDOWS
- return 1;
- #else
- return 0;
- #endif
-#endif
-}
-
-/**
- * @brief Make GNUnet start automatically
- * @param doAutoStart true to enable autostart, false to disable it
- * @param username name of the user account to use
- * @param groupname name of the group to use
- * @return 0 on success
- */
-int autostartService(int doAutoStart,
- const char * username,
- const char * groupname) {
-#ifdef WINDOWS
- if (doAutoStart)
- {
- if (IsWinNT())
- {
- char *err = NULL;
- DWORD dwErr = 0;
-
- if (username && !strlen(username))
- username = NULL;
-
- /* Install service */
- switch(InstallAsService(username))
- {
- case 0:
- case 1:
- break;
- case 2:
- if (GetLastError() != ERROR_SERVICE_EXISTS)
- return 1;
- case 3:
- return 2;
- default:
- return -1;
- }
-
- /* Grant permissions to the GNUnet directory */
- if ((!err || dwErr == ERROR_SERVICE_EXISTS) && username)
- {
- char szHome[_MAX_PATH + 1];
-
- plibc_conv_to_win_path("/", szHome);
-
- if (!AddPathAccessRights(szHome, username, GENERIC_ALL))
- return 3;
- }
- }
- else
- {
- char szPath[_MAX_PATH + 1];
- HKEY hKey;
-
- plibc_conv_to_win_path("/bin/gnunetd.exe", szPath);
-
- if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
- "Software\\Microsoft\\Windows\\CurrentVersion\\Run", 0, KEY_EXECUTE,
- &hKey) == ERROR_SUCCESS)
- {
- if (RegSetValueEx(hKey, "GNUnet", 0, REG_SZ, szPath, strlen(szPath)) !=
- ERROR_SUCCESS)
- return 4;
-
- RegCloseKey(hKey);
- }
- else
- return 4;
- }
- }
- else
- {
- if (IsWinNT())
- {
- switch (UninstallService())
- {
- case 0:
- case 1:
- break;
- case 2:
- return 1;
- case 3:
- return 5;
- case 4:
- return 6;
- default:
- return -1;
- }
- }
- else
- {
- HKEY hKey;
-
- if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
- "Software\\Microsoft\\Windows\\CurrentVersion\\Run",
0, KEY_SET_VALUE,
- &hKey) == ERROR_SUCCESS)
- {
- RegDeleteValue(hKey, "GNUnet");
-
- RegCloseKey(hKey);
- }
- }
- }
-#else
- /* Unix */
- if (ACCESS("/usr/sbin/update-rc.d", X_OK) == 0) {
- /* Debian */
- if (doAutoStart) {
- struct stat buf;
- if (STAT("/etc/init.d/gnunetd", &buf) == -1) {
- /* create init file */
- FILE *f = FOPEN("/etc/init.d/gnunetd", "w");
- if (! f)
- return 1;
-
- fputs("#! /bin/sh\n"
- "#\n"
- "# Automatically created by gnunet-setup\n"
- "#\n"
- "\n"
- "PATH=$PATH:" PREFIX_PATH "/bin"
- "PIDFILE=/var/run/gnunetd/gnunetd.pid\n"
- "\n"
- "case \"$1\" in\n"
- " start)\n"
- " echo -n \"Starting GNUnet: \"\n"
- " gnunetd\n"
- " echo \"gnunetd\"\n"
- " ;;\n"
- " stop)\n"
- " echo -n \"Stopping GNUnet: \"\n"
- " kill `cat $PIDFILE`\n"
- " echo \"gnunetd\"\n"
- " ;;\n"
- " reload)\n"
- " echo -n \"Reloading GNUnet: \"\n"
- " kill -HUP `cat $PIDFILE`\n"
- " echo \"gnunetd\"\n"
- " ;;\n"
- " restart|force-reload)\n"
- " echo \"Restarting GNUnet: gnunetd...\"\n"
- " $0 stop\n"
- " sleep 1\n"
- " $0 start\n"
- " ;;\n"
- " *)\n"
- " echo \"Usage: /etc/init.d/gnunetd
{start|stop|reload|restart|force-reload}\" >&2\n"
- " exit 1\n"
- " ;;\n"
- "\n"
- "esac\n"
- "exit 0\n", f);
- fclose(f);
- CHMOD("/etc/init.d/gnunetd", S_IRWXU | S_IRGRP | S_IXGRP |
- S_IROTH | S_IXOTH);
- }
- errno = system("/usr/sbin/update-rc.d gnunetd defaults");
- if (errno != 0)
- return 1;
- }
- else {
- if ( (UNLINK("/etc/init.d/gnunetd") != -1) ||
- (errno != ENOENT)) {
- if (ACCESS("/usr/sbin/update-rc.d", X_OK) == 0) {
- errno = system("/usr/sbin/update-rc.d gnunetd remove");
- if (errno != 0) {
- errno = EPERM;
- return 1;
- }
- }
- else {
- errno = EPERM;
- return 1;
- }
- }
- else
- return 0;
- }
- }
- else
- return 1;
-#endif
- return 0;
-}
-
-/**
- * @brief Checks if we can add an user for the GNUnet service
- * @return 1 if yes, 0 otherwise
- * @todo support for useradd(8)
- */
-int isOSUserAddCapable(){
-#ifdef WINDOWS
- return IsWinNT();
-#endif
-#ifdef LINUX
- if (ACCESS("/usr/sbin/adduser", X_OK) == 0)
- return (geteuid() == 0);
- else
- /* TODO: useradd */
-#endif
- return 0;
-}
-
-/**
- * @brief Checks if we can add a group for the GNUnet service
- * @return 1 if yes, 0 otherwise
- * @todo support for groupadd(8)
- */
-int isOSGroupAddCapable() {
-#ifdef LINUX
- if (ACCESS("/usr/sbin/addgroup", X_OK) == 0) {
- return (geteuid() == 0);
- }
- /* TODO: groupadd */
- else
-#endif
- return 0;
-}
-
-/**
- * @brief Add a service account for GNUnet
- * @param group the group of the new user
- * @param name the name of the new user
- * @return 0 on success
- */
-int createGroupUser(const char *group_name,
- const char *user_name) {
- int haveGroup;
-
- if ( (user_name == NULL) ||
- (0 == strlen(user_name)) )
- return 0;
-
-#ifdef WINDOWS
- if (IsWinNT())
- {
- return CreateServiceAccount(user_name, "GNUnet service
account");
- }
-#else
-
- if (ACCESS("/usr/sbin/adduser", X_OK) == 0) {
- /* Debian */
- /* TODO: FreeBSD?
http://www.freebsd.org/cgi/man.cgi?query=adduser&sektion=8 */
- char *cmd;
-
- haveGroup = group_name && strlen(group_name) > 0;
- cmd = MALLOC(haveGroup ? strlen(group_name) : 0 +
strlen(user_name) + 64);
-
- if (haveGroup) {
- sprintf(cmd, "/usr/sbin/addgroup --quiet --system %s",
group_name);
- system(cmd);
- }
-
- sprintf(cmd, "/usr/sbin/adduser --quiet --system %s %s "
- "--no-create-home %s", haveGroup ? "--ingroup" : "",
- haveGroup ? group_name : "", user_name);
- system(cmd);
-
- FREE(cmd);
- }
- /* TODO: useradd */
- else
- return 1;
-#endif
-
- return 0;
-}
-
-char *winErrorStr(const char *prefix, int dwErr)
-{
-#ifdef WINDOWS
- 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 = "";
- }
-
- mem = strlen(err) + strlen(prefix) + 20;
- ret = (char *) malloc(mem);
-
- snprintf(ret, mem, "%s: %s (#%u)", prefix, err, dwErr);
-
- LocalFree(err);
-
- return ret;
-#else
- return NULL;
-#endif
-}
-
-
-/* end of osconfig.c */
Deleted: GNUnet/src/util/port.c
===================================================================
--- GNUnet/src/util/port.c 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/port.c 2006-06-22 17:50:56 UTC (rev 3024)
@@ -1,102 +0,0 @@
-/*
- This file is part of GNUnet
-
- 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/port.c
- * @brief functions for GNUnet clients to establish connection with gnunetd
- * @author Christian Grothoff
- */
-
-#include "gnunet_util.h"
-#include "platform.h"
-
-/**
- * Return the port-number (in host byte order)
- */
-unsigned short getGNUnetPort() {
- static unsigned short port;
- const char *setting;
-
- if (port != 0)
- return port;
- if (testConfigurationString("GNUNETD",
- "_MAGIC_",
- "YES"))
- setting = "PORT";
- else
- setting = "CLIENT-PORT";
-
- port = (unsigned short) getConfigurationInt("NETWORK",
- setting);
- if (port == 0) {
- errexit(_("Cannot determine port of gnunetd server. "
- "Define in configuration file in section `%s' under `%s'.\n"),
- "NETWORK",
- setting);
- }
- return port;
-}
-
-/**
- * Configuration: get the GNUnetd host where the client
- * should connect to (via TCP)
- * @return the name of the host
- */
-static const char * getGNUnetdHost() {
- static char * res;
-
- if (res != NULL)
- return res;
- res = getConfigurationString("NETWORK",
- "HOST");
- if (res == NULL)
- res = "localhost";
- return res;
-}
-
-/**
- * Get a GNUnet TCP socket that is connected to gnunetd.
- */
-GNUNET_TCP_SOCKET * getClientSocket() {
- GNUNET_TCP_SOCKET * sock;
- const char * host;
-
- sock = MALLOC(sizeof(GNUNET_TCP_SOCKET));
- host = getGNUnetdHost();
- if (SYSERR == initGNUnetClientSocket(getGNUnetPort(),
- host,
- sock)) {
- LOG(LOG_ERROR,
- _("Could not connect to gnunetd.\n"));
- FREE(sock);
- return NULL;
- }
- return sock;
-}
-
-/**
- * Free a Client socket.
- */
-void releaseClientSocket(GNUNET_TCP_SOCKET * sock) {
- if (sock != NULL) {
- destroySocket(sock);
- FREE(sock);
- }
-}
-
-/* end of port.c */
Deleted: GNUnet/src/util/printhelp.c
===================================================================
--- GNUnet/src/util/printhelp.c 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/printhelp.c 2006-06-22 17:50:56 UTC (rev 3024)
@@ -1,169 +0,0 @@
-/*
- This file is part of GNUnet
-
- 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 printhelp.c
- * @brief Common option processing methods for GNUnet clients.
- * @author Christian Grothoff
- */
-
-#include "gnunet_util.h"
-#include "platform.h"
-
-#define BORDER 29
-
-
-void formatHelp(const char * general,
- const char * description,
- const Help * opt) {
- int slen;
- int i;
- int j;
- int ml;
- int p;
- char * scp;
- const char * trans;
-
- printf(_("Usage: %s\n%s\n\n"),
- gettext(general),
- gettext(description));
- printf(_("Arguments mandatory for long options are also mandatory for short
options.\n"));
- slen = 0;
- i = 0;
- while (opt[i].description != NULL) {
- if (opt[i].shortArg == 0)
- printf(" ");
- else
- printf(" -%c, ",
- opt[i].shortArg);
- printf("--%s",
- opt[i].longArg);
- slen = 8 + strlen(opt[i].longArg);
- if (opt[i].mandatoryArg != NULL) {
- printf("=%s",
- opt[i].mandatoryArg);
- slen += 1+strlen(opt[i].mandatoryArg);
- }
- if (slen > BORDER) {
- printf("\n%*s", BORDER, "");
- slen = BORDER;
- }
- if (slen < BORDER) {
- printf("%*s", BORDER-slen, "");
- slen = BORDER;
- }
- trans = gettext(opt[i].description);
- ml = strlen(trans);
- p = 0;
- OUTER:
- while (ml - p > 78 - slen) {
- for (j=p+78-slen;j>p;j--) {
- if (isspace(trans[j])) {
- scp = malloc(j-p+1);
- memcpy(scp,
- &trans[p],
- j-p);
- scp[j-p] = '\0';
- printf("%s\n%*s",
- scp,
- BORDER+2,
- "");
- free(scp);
- p = j+1;
- slen = BORDER+2;
- goto OUTER;
- }
- }
- /* could not find space to break line */
- scp = malloc(78 - slen + 1);
- memcpy(scp,
- &trans[p],
- 78 - slen);
- scp[78 - slen] = '\0';
- printf("%s\n%*s",
- scp,
- BORDER+2,
- "");
- free(scp);
- slen = BORDER+2;
- p = p + 78 - slen;
- }
- /* print rest */
- if (p < ml)
- printf("%s\n",
- &trans[p]);
- i++;
- }
-}
-
-/**
- * Parse the default set of options and set
- * options in the configuration accordingly.
- * This does not include --help or --version.
- * @return YES if the option was a default option
- * that was successfully processed
- */
-int parseDefaultOptions(char c,
- char * optarg) {
- char * host;
- char * port_string;
- unsigned short port;
-
- switch(c) {
- case 'c':
- FREENONNULL(setConfigurationString("FILES",
- "gnunet.conf",
- optarg));
- break;
- case 'd':
- FREENONNULL(setConfigurationString("GNUNETD",
- "LOGFILE",
- NULL));
- break;
- case 'H': {
- port_string = strstr(optarg, ":");
- if (NULL != port_string) {
- port = (unsigned short) atoi(port_string+1);
- setConfigurationInt("NETWORK",
- "CLIENT-PORT",
- port);
- host = MALLOC(1 + port_string - optarg);
- memcpy(host, optarg, port_string - optarg);
- host[port_string - optarg] = '\0';
- } else {
- host = STRDUP(optarg);
- }
- FREENONNULL(setConfigurationString("NETWORK",
- "HOST",
- host));
- FREE(host);
- break;
- }
- case 'L':
-
- FREENONNULL(setConfigurationString("GNUNET",
- "LOGLEVEL",
- optarg));
- break;
- default:
- return NO;
- }
- return YES;
-}
-
-/* end of printhelp.c */
Deleted: GNUnet/src/util/semaphore.c
===================================================================
--- GNUnet/src/util/semaphore.c 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/semaphore.c 2006-06-22 17:50:56 UTC (rev 3024)
@@ -1,1042 +0,0 @@
-/*
- This file is part of GNUnet.
- (C) 2001, 2002, 2003, 2004 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/semaphore.c
- * @brief functions related to threading and synchronization
- *
- * In particular, functions for mutexes, semaphores
- * and thread creation are provided.
- */
-
-#include "gnunet_util.h"
-#include "platform.h"
-
-#if SOLARIS || FREEBSD || OSX
-#include <semaphore.h>
-#endif
-#if SOMEBSD
-# include <pthread_np.h>
-# include <sys/file.h>
-#endif
-#if LINUX
-# include <sys/ipc.h>
-# include <sys/sem.h>
-#endif
-#ifdef _MSC_VER
-#include <pthread.h>
-#include <semaphore.h>
-#endif
-
-/**
- * Shall we use error-checking (slow)
- * mutexes (e.g. for debugging)
- */
-#define USE_CHECKING_MUTEX 1
-
-typedef struct {
-#if SOLARIS || FREEBSD5 || OSX
- sem_t * internal;
-#elif WINDOWS
- HANDLE internal;
-#elif LINUX
- int internal;
- char * filename;
-#elif SOMEBSD
- int initialValue;
- int fd;
- Mutex internalLock;
- char * filename;
-#elif _MSC_VER
- int internal; /* KLB_FIX */
- char * filename;
-#else
- /* PORT-ME! */
-#endif
-} IPC_Semaphore_Internal;
-
-#ifndef PTHREAD_MUTEX_NORMAL
-#ifdef PTHREAD_MUTEX_TIMED_NP
-#define PTHREAD_MUTEX_NORMAL PTHREAD_MUTEX_TIMED_NP
-#else
-#define PTHREAD_MUTEX_NORMAL NULL
-#endif
-#endif
-
-/**
- * This prototype is somehow missing in various Linux pthread
- * include files. But we need it and it seems to be available
- * on all pthread-systems so far. Odd.
- */
-#ifndef _MSC_VER
-extern int pthread_mutexattr_setkind_np(pthread_mutexattr_t *attr, int kind);
-#endif
-
-/* ********************* public methods ******************* */
-
-void create_mutex_(Mutex * mutex) {
- pthread_mutexattr_t attr;
- pthread_mutex_t * mut;
-
-#if WINDOWS
- attr = NULL;
-#endif
-
- pthread_mutexattr_init(&attr);
-#if USE_CHECKING_MUTEX
-#if LINUX
- pthread_mutexattr_setkind_np(&attr, PTHREAD_MUTEX_ERRORCHECK_NP);
-#else
- pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
-#endif
-#else
-#if LINUX
- pthread_mutexattr_setkind_np(&attr, PTHREAD_MUTEX_NORMAL_NP);
-#else
- pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
-#endif
-#endif
-
- mut = MALLOC(sizeof(pthread_mutex_t));
- mutex->internal = mut;
- GNUNET_ASSERT(0 == pthread_mutex_init(mut, &attr));
-}
-
-void create_recursive_mutex_(Mutex * mutex) {
- pthread_mutexattr_t attr;
- pthread_mutex_t * mut;
-
- pthread_mutexattr_init(&attr);
-#if LINUX
- GNUNET_ASSERT(0 == pthread_mutexattr_setkind_np
- (&attr,
- PTHREAD_MUTEX_RECURSIVE_NP));
-#elif SOMEBSD || FREEBSD || FREEBSD5
- GNUNET_ASSERT(0 == pthread_mutexattr_setkind_np
- (&attr,
- PTHREAD_MUTEX_RECURSIVE));
-#elif SOLARIS || OSX || WINDOWS
- GNUNET_ASSERT(0 == pthread_mutexattr_settype
- (&attr,
- PTHREAD_MUTEX_RECURSIVE));
-#endif
- mut = MALLOC(sizeof(pthread_mutex_t));
- mutex->internal = mut;
- GNUNET_ASSERT(pthread_mutex_init(mut, &attr) == 0);
-}
-
-void destroy_mutex_(Mutex * mutex) {
- pthread_mutex_t * mut;
- int k;
-
- mut = mutex->internal;
- if (mut == NULL) {
- BREAK();
- return;
- }
- mutex->internal = NULL;
- errno = 0;
- if ((k = pthread_mutex_destroy(mut)) != 0) {
- LOG(LOG_FATAL, _("`%s' failed with error code %d: %s\n"),
- "pthread_mutex_destroy",
- k,
- STRERROR(k));
- return;
- }
- FREE(mut);
-}
-
-void mutex_lock_(Mutex * mutex,
- const char * filename,
- const int line) {
- pthread_mutex_t * mut;
- int ret;
-
- mut = mutex->internal;
- if (mut == NULL) {
- BREAK_FL(filename, line);
- return;
- }
- ret = pthread_mutex_lock(mut);
- if (ret != 0) {
- if (ret == EINVAL)
- errexit(_("Invalid argument for `%s' at %s:%d.\n"),
- "pthread_mutex_lock",
- filename, line);
- if (ret == EDEADLK)
- errexit(_("Deadlock due to `%s' at %s:%d.\n"),
- "pthread_mutex_lock",
- filename, line);
- GNUNET_ASSERT(0);
- }
-}
-
-void mutex_unlock_(Mutex * mutex,
- const char * filename,
- const int line) {
- pthread_mutex_t * mut;
- int ret;
-
- mut = mutex->internal;
- if (mut == NULL) {
- BREAK_FL(filename, line);
- return;
- }
-
- ret = pthread_mutex_unlock(mut);
- if (ret != 0) {
- if (ret == EINVAL)
- errexit(_("Invalid argument for `%s' at %s:%d.\n"),
- "pthread_mutex_unlock",
- filename, line);
- if (ret == EPERM)
- errexit(_("Permission denied for `%s' at %s:%d.\n"),
- "pthread_mutex_unlock",
- filename, line);
- GNUNET_ASSERT_FL(0, filename, line);
- }
-}
-
-/**
- * function must be called prior to semaphore use -- handles
- * setup and initialization. semaphore destroy (below) should
- * be called when the semaphore is no longer needed.
- */
-Semaphore * semaphore_new_(int value,
- const char * filename,
- const int linenumber) {
- pthread_cond_t * cond;
-
- Semaphore * s = (Semaphore*)xmalloc_(sizeof(Semaphore),
- filename,
- linenumber);
- s->v = value;
- MUTEX_CREATE(&(s->mutex));
- cond = MALLOC(sizeof(pthread_cond_t));
- s->cond = cond;
- GNUNET_ASSERT_FL(0 == pthread_cond_init(cond, NULL), filename, linenumber);
- return s;
-}
-
-void semaphore_free_(Semaphore * s,
- const char * filename,
- const int linenumber) {
-
- pthread_cond_t * cond;
- int k;
-
- MUTEX_DESTROY(&(s->mutex));
- cond = s->cond;
- if ((k = pthread_cond_destroy(cond)) != 0) {
- LOG(LOG_FATAL, _("`%s' failed with error code %d: %s\n"),
- "pthread_cond_destroy",
- k,
- STRERROR(k));
- return;
- }
- FREE(cond);
- xfree_(s,
- filename,
- linenumber);
-}
-
-/**
- * function increments the semaphore and signals any threads that
- * are blocked waiting a change in the semaphore.
- */
-int semaphore_up_(Semaphore * s,
- const char * filename,
- const int linenumber) {
- int value_after_op;
- pthread_cond_t * cond;
-
- GNUNET_ASSERT_FL(s != NULL, filename, linenumber);
- cond = s->cond;
- MUTEX_LOCK(&(s->mutex));
- (s->v)++;
- value_after_op = s->v;
- GNUNET_ASSERT(0 == pthread_cond_signal(cond));
- MUTEX_UNLOCK(&(s->mutex));
- return value_after_op;
-}
-
-/**
- * function decrements the semaphore and blocks if the semaphore is
- * <= 0 until another thread signals a change.
- */
-int semaphore_down_(Semaphore * s,
- const char * filename,
- const int linenumber) {
- int value_after_op;
- int return_value;
- pthread_cond_t * cond;
-
- GNUNET_ASSERT_FL(s != NULL, filename, linenumber);
- cond = s->cond;
- MUTEX_LOCK(&(s->mutex));
- while (s->v <= 0) {
- if ((return_value = pthread_cond_wait(cond,
- (pthread_mutex_t*)s->mutex.internal))
!= 0)
- DIE_STRERROR_FL("pthread_cond_wait", filename, linenumber);
- }
- (s->v)--;
- value_after_op = s->v;
- MUTEX_UNLOCK(&(s->mutex));
- return value_after_op;
-}
-
-/**
- * Function decrements the semaphore. If the semaphore would become
- * negative, the decrement does not happen and the function returns
- * SYSERR. Otherwise OK is returned.
- */
-int semaphore_down_nonblocking_(Semaphore * s,
- const char * filename,
- const int linenumber) {
- GNUNET_ASSERT_FL(s != NULL, filename, linenumber);
- MUTEX_LOCK(&(s->mutex));
- if (s->v <= 0) {
- MUTEX_UNLOCK(&(s->mutex));
- return SYSERR;
- }
- (s->v)--;
- MUTEX_UNLOCK(&(s->mutex));
- return OK;
-}
-
-#ifdef WINDOWS
-/**
- * @brief Called if a sleeping thread is interrupted
- */
-static void CALLBACK __PTHREAD_SIGNALED(DWORD sig) {
-}
-#endif
-
-/**
- * Returns YES if pt is the handle for THIS thread.
- */
-int PTHREAD_SELF_TEST(PTHREAD_T * pt) {
- pthread_t * handle;
-
- GNUNET_ASSERT(pt != NULL);
- handle = pt->internal;
- if (handle == NULL)
- return NO;
-#if HAVE_NEW_PTHREAD_T
- if (handle->p == pthread_self().p)
-#else
- if (*handle == pthread_self())
-#endif
- return YES;
- else
- return NO;
-}
-
-/**
- * Get the handle for THIS thread.
- */
-void PTHREAD_GET_SELF(PTHREAD_T * pt) {
- pt->internal = MALLOC(sizeof(pthread_t));
- *((pthread_t*)pt->internal) = pthread_self();
-}
-
-/**
- * Release handle for a thread.
- */
-void PTHREAD_REL_SELF(PTHREAD_T * pt) {
- FREENONNULL(pt->internal);
- pt->internal = NULL;
-}
-
-/**
- * Create a thread. Use this method instead of pthread_create since
- * BSD may only give a 1k stack otherwise.
- *
- * @param handle handle to the pthread (for detaching, join)
- * @param main the main method of the thread
- * @param arg the argument to main
- * @param stackSize the size of the stack of the thread in bytes.
- * Note that if the stack overflows, some OSes (seen under BSD)
- * will just segfault and gdb will give a messed-up stacktrace.
- * @return see pthread_create
- */
-int PTHREAD_CREATE(PTHREAD_T * pt,
- PThreadMain main,
- void * arg,
- size_t stackSize) {
- pthread_t * handle;
- pthread_attr_t stack_size_custom_attr;
- int ret;
-
- handle = MALLOC(sizeof(pthread_t));
-#ifdef MINGW
- memset(handle, 0, sizeof(pthread_t));
-#endif
-
- pthread_attr_init(&stack_size_custom_attr);
- pthread_attr_setstacksize(&stack_size_custom_attr,
- stackSize);
- ret = pthread_create(handle,
- &stack_size_custom_attr,
- main,
- arg);
-
- if (ret != 0) {
- FREE(handle);
- pt->internal = NULL;
- return ret;
- }
- pt->internal = handle;
- return ret;
-}
-
-void PTHREAD_JOIN(PTHREAD_T * pt,
- void ** ret) {
- int k;
- pthread_t * handle;
-
- GNUNET_ASSERT(pt != NULL);
- handle = pt->internal;
- GNUNET_ASSERT(handle != NULL);
- GNUNET_ASSERT(NO == PTHREAD_SELF_TEST(pt));
- switch ((k=pthread_join(*handle, ret))) {
- case 0:
- FREE(handle);
- pt->internal = NULL;
- return;
- case ESRCH:
- errexit("`%s' failed with error code %s: %s\n",
- "pthread_join",
- "ESRCH",
- STRERROR(errno));
- case EINVAL:
- errexit("`%s' failed with error code %s: %s\n",
- "pthread_join",
- "EINVAL",
- STRERROR(errno));
- case EDEADLK:
- errexit("`%s' failed with error code %s: %s\n",
- "pthread_join",
- "EDEADLK",
- STRERROR(errno));
- default:
- errexit("`%s' failed with error code %d: %s\n",
- "pthread_join",
- k,
- STRERROR(errno));
- }
-}
-
-void PTHREAD_DETACH(PTHREAD_T * pt) {
- pthread_t * handle;
-
- handle = pt->internal;
- GNUNET_ASSERT(handle != NULL);
- if (0 != pthread_detach(*handle))
- LOG_STRERROR(LOG_ERROR, "pthread_detach");
- pt->internal = NULL;
- FREE(handle);
- return;
-}
-
-void PTHREAD_KILL(PTHREAD_T * pt,
- int signal) {
- pthread_t * handle;
- int ret;
-
- handle = pt->internal;
- if (handle == NULL) {
- BREAK();
- return;
- }
-#ifdef WINDOWS
- if (signal != 0)
- ret = QueueUserAPC((PAPCFUNC) __PTHREAD_SIGNALED,
- pthread_getw32threadhandle_np(*handle), 0) != 0 ? 0 : EINVAL;
- else
- ret = pthread_kill(*handle, 0);
-#else
- ret = pthread_kill(*handle, signal);
-#endif
- switch (ret) {
- case 0:
- break; /* ok */
- case EINVAL:
- LOG(LOG_ERROR,
- _("`%s' failed with error code %s: %s\n"),
- "pthread_kill",
- "EINVAL",
- STRERROR(ret));
- break;
- case ESRCH:
- LOG(LOG_ERROR,
- _("`%s' failed with error code %s: %s\n"),
- "pthread_kill",
- "ESRCH",
- STRERROR(ret));
- break;
- default:
- LOG(LOG_ERROR,
- _("`%s' failed with error code %d: %s\n"),
- "pthread_kill",
- ret,
- STRERROR(ret));
- break;
- }
-}
-
-
-/* ********************** IPC ********************* */
-
-#if LINUX
- /* IPC semaphore kludging for linux */
-
- /* Why don't we start at count 0 and increment when opening? */
- #define PROCCOUNT 10000
-
- /**
- * Implementation for a single semaphore actually uses three :
- *
- * 0 : actual semaphore value
- * 1 : process counter
- * 2 : lock
- */
-
- /* Various operations */
- static struct sembuf op_lock[2] = {
- {2, 0, 0}, /* wait for [2] (lock) to equal 0 */
- {2, 1, SEM_UNDO} /* then increment [2] to 1 - this locks it */
- /* UNDO to release the lock if processes exits */
/* before explicitly unlocking */
- };
- static struct sembuf op_unlock[1] = {
- {2, -1, SEM_UNDO} /* decrement [2] (lock) back to 0 */
- };
- static struct sembuf op_endcreate[2] = {
- {1, -1, SEM_UNDO},/* decrement [1] (proc counter) with undo on exit */
- /* UNDO to adjust proc counter if process exits
- before explicitly calling sem_close() */
- {2, -1, SEM_UNDO} /* then decrement [2] (lock) back to 0 */
- };
- static struct sembuf op_close[3] = {
- {2, 0, 0}, /* wait for [2] (lock) to equal 0 */
- {2, 1, SEM_UNDO}, /* then increment [2] to 1 - this locks it */
- {1, 1, SEM_UNDO} /* then increment [1] (proc counter) */
- };
-#endif
-
-#if SOMEBSD
-static void FLOCK(int fd,
- int operation) {
- int ret;
-
- ret = -1;
- while (ret == -1) {
- ret = flock(fd, operation);
- if (ret == -1) {
- if (errno != EINTR) {
- LOG_STRERROR(LOG_ERROR, "flock");
- return;
- }
- }
- }
- fsync(fd);
-}
-static int LSEEK(int fd, off_t pos, int mode) {
- int ret;
- ret = lseek(fd, pos, mode);
- if (ret == -1)
- LOG_STRERROR(LOG_ERROR, "lseek");
- return ret;
-}
-#endif
-
-IPC_Semaphore * ipc_semaphore_new_(const char * basename,
- const unsigned int initialValue,
- const char * filename,
- const int linenumber) {
- /* Could older FreeBSD use this too since this code can shorten the IPC name
*/
-#if SOLARIS || OSX || FREEBSD5
- char * noslashBasename;
- int i;
- IPC_Semaphore * rret;
- IPC_Semaphore_Internal * ret;
-
- rret = MALLOC(sizeof(IPC_Semaphore));
- ret = MALLOC(sizeof(IPC_Semaphore_Internal));
- rret->platform = ret;
- noslashBasename = STRDUP(basename);
- for (i=strlen(noslashBasename);i>0;i--)
- if (noslashBasename[i] == '/')
- noslashBasename[i] = '.'; /* first character MUST be /, but Solaris
- forbids it afterwards */
- noslashBasename[0] = '/';
- ret->internal = sem_open(noslashBasename,
- O_CREAT,
- S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, /* 660 */
- initialValue);
- while ( (ret->internal == (void *) SEM_FAILED)
- && (errno == ENAMETOOLONG) ) {
- if (strlen(noslashBasename) < 4)
- break; /* definitely OS error... */
- noslashBasename[strlen(noslashBasename)/2] = '\0'; /* cut in half */
- ret->internal = sem_open(noslashBasename,
- O_CREAT,
- S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, /* 660 */
- initialValue);
- }
- if (ret->internal == (void *) SEM_FAILED)
- DIE_FILE_STRERROR("sem_open", noslashBasename);
- FREE(noslashBasename);
- return rret;
-#elif WINDOWS
- char * noslashBasename;
- int i;
- IPC_Semaphore * rret;
- IPC_Semaphore_Internal * ret;
- SECURITY_ATTRIBUTES sec;
- DWORD dwErr;
-
- rret = MALLOC(sizeof(IPC_Semaphore));
- ret = MALLOC(sizeof(IPC_Semaphore_Internal));
- rret->platform = ret;
- noslashBasename = STRDUP(basename);
- for (i=strlen(noslashBasename);i>0;i--)
- if (noslashBasename[i] == '\\')
- noslashBasename[i] = '.'; /* must not contain backslashes */
-
- sec.nLength = sizeof(SECURITY_ATTRIBUTES);
- sec.bInheritHandle = TRUE;
- sec.lpSecurityDescriptor = NULL;
-
- ret->internal = CreateSemaphore(&sec, initialValue, LONG_MAX,
noslashBasename);
- dwErr = GetLastError();
- if (! ret->internal && dwErr == ERROR_ALREADY_EXISTS) {
- ret->internal = OpenSemaphore(SEMAPHORE_MODIFY_STATE, TRUE,
noslashBasename);
- dwErr = GetLastError();
- }
- if (! ret->internal) {
- LOG(LOG_FAILURE, _("Can't create semaphore: %i"), dwErr);
- DIE_FILE_STRERROR("sem_open", noslashBasename);
- }
- FREE(noslashBasename);
- return rret;
-#elif LINUX
- union semun {
- int val;
- struct semid_ds *buf;
- ushort *array;
- } semctl_arg;
- IPC_Semaphore * rret;
- IPC_Semaphore_Internal * ret;
- key_t key;
- FILE * fp;
- int pcount;
-
- rret = MALLOC(sizeof(IPC_Semaphore));
- ret = MALLOC(sizeof(IPC_Semaphore_Internal));
- rret->platform = ret;
-
- fp = FOPEN(basename, "a+");
- if (NULL == fp) {
- LOG_FILE_STRERROR_FL(LOG_FATAL,
- "fopen",
- basename,
- filename,
- linenumber);
- FREE(rret);
- FREE(ret);
- return NULL;
- }
- fclose(fp);
-
- key = ftok(basename,'g');
-
-again:
-
- ret->internal = semget(key, 3, IPC_CREAT|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
-
- if (ret->internal == -1)
- DIE_STRERROR_FL("semget", filename, linenumber);
- if (semop(ret->internal, &op_lock[0], 2) < 0) {
- if (errno == EINVAL)
- goto again;
- else
- DIE_STRERROR_FL("semop", filename, linenumber);
- }
-
- /* get process count */
- if ( (pcount = semctl(ret->internal, 1, GETVAL, 0)) < 0)
- DIE_STRERROR_FL("semctl", filename, linenumber);
- if (pcount==0) {
- semctl_arg.val = initialValue;
- if (semctl(ret->internal, 0, SETVAL, semctl_arg) < 0)
- DIE_STRERROR_FL("semtcl", filename, linenumber);
- semctl_arg.val = PROCCOUNT;
- if (semctl(ret->internal, 1, SETVAL, semctl_arg) < 0)
- DIE_STRERROR_FL("semtcl", filename, linenumber);
- }
-
- if (semop(ret->internal, &op_endcreate[0], 2) < 0)
- DIE_STRERROR_FL("semop", filename, linenumber);
-
- ret->filename = STRDUP(basename);
- return rret;
-#elif SOMEBSD
- int fd;
- int cnt;
- IPC_Semaphore * rret;
- IPC_Semaphore_Internal * ret;
-
- rret = MALLOC(sizeof(IPC_Semaphore));
- ret = MALLOC(sizeof(IPC_Semaphore_Internal));
- rret->platform = ret;
-
- MUTEX_CREATE(&ret->internalLock);
- ret->filename = STRDUP(basename);
- fd = -1;
- while (fd == -1) {
- fd = fileopen(basename,
- O_CREAT|O_RDWR|O_EXCL,
- S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP /* 660 */);
- if ( (fd == -1) &&
- (errno == EEXIST) ) {
- /* try without creation */
- fd = fileopen(basename,
- O_RDWR,
- S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP /* 660 */);
- /* possibly the file was deleted in the meantime,
- then try again with O_CREAT! */
- if ( (fd == -1) &&
- (errno != ENOENT) )
- break;
- }
- }
- if (fd == -1) {
- LOG_FILE_STRERROR(LOG_ERROR, "open", ret->filename);
- MUTEX_DESTROY(&ret->internalLock);
- FREE(ret->filename);
- FREE(ret);
- FREE(rret);
- return NULL;
- }
- FLOCK(fd, LOCK_EX);
- if (sizeof(int) != READ(fd, &cnt, sizeof(int))) {
- cnt = htonl(initialValue);
- LSEEK(fd, 0, SEEK_SET);
- if (sizeof(int) != WRITE(fd, &cnt, sizeof(int)))
- LOG_FILE_STRERROR(LOG_WARNING, "write", basename);
- }
- LSEEK(fd, sizeof(int), SEEK_SET);
- if (sizeof(int) != READ(fd, &cnt, sizeof(int)))
- cnt = htonl(1);
- else
- cnt = htonl(ntohl(cnt)+1);
- LSEEK(fd, sizeof(int), SEEK_SET);
- if (sizeof(int) != WRITE(fd, &cnt, sizeof(int)))
- LOG_FILE_STRERROR(LOG_WARNING, "write", basename);
- FLOCK(fd, LOCK_UN);
- ret->fd = fd;
- ret->initialValue = initialValue;
- return rret;
-#else
- #ifndef _MSC_VER
- #warning Port IPC.
- return NULL;
- #else
- return NULL;
- #endif
-#endif
-}
-
-void ipc_semaphore_up_(IPC_Semaphore * rsem,
- const char * filename,
- const int linenumber) {
- IPC_Semaphore_Internal * sem;
- if (rsem == NULL) /* error on creation, optimistic execution; good luck */
- return;
- sem = rsem->platform;
-#if SOLARIS || OSX || FREEBSD5
- if (0 != sem_post(sem->internal))
- LOG(LOG_WARNING,
- "sem_post signaled error: %s at %s:%d\n",
- STRERROR(errno),
- filename,
- linenumber);
-#elif WINDOWS
- if (!ReleaseSemaphore(sem->internal, 1, NULL))
- LOG(LOG_WARNING,
- "ReleaseSemaphore signaled error: %i at %s:%d\n",
- GetLastError(),
- filename,
- linenumber);
-#elif LINUX
- {
- struct sembuf sops = {0,1,SEM_UNDO};
-
- if (0 != semop(sem->internal,&sops,1))
- LOG(LOG_WARNING,
- "semop signaled error: %s at %s:%d\n",
- STRERROR(errno),
- filename,
- linenumber);
- }
-#elif SOMEBSD
- {
- int cnt;
-
-
- MUTEX_LOCK(&sem->internalLock);
- FLOCK(sem->fd, LOCK_EX);
- LSEEK(sem->fd, 0, SEEK_SET);
- if (sizeof(int) != READ(sem->fd, &cnt, sizeof(int))) {
- LOG(LOG_WARNING,
- "could not read IPC semaphore count (%s) at %s:%d!\n",
- STRERROR(errno),
- __FILE__,
- __LINE__);
- MUTEX_UNLOCK(&sem->internalLock);
- return;
- }
- cnt = htonl(ntohl(cnt)+1);
- LSEEK(sem->fd, 0, SEEK_SET);
- if (sizeof(int) != WRITE(sem->fd, &cnt, sizeof(int)))
- LOG(LOG_WARNING,
- "could not write to IPC file %s (%s) at %s:%d\n",
- sem->filename,
- STRERROR(errno),
- __FILE__,
- __LINE__);
- FLOCK(sem->fd, LOCK_UN);
- MUTEX_UNLOCK(&sem->internalLock);
- }
-#endif
-}
-
-void ipc_semaphore_down_(IPC_Semaphore * rsem,
- const char * filename,
- const int linenumber) {
- IPC_Semaphore_Internal * sem;
-
- if (rsem == NULL) /* error on creation, optimistic execution; good luck */
- return;
- sem = rsem->platform;
-#if OSX || SOLARIS || FREEBSD5
- while (0 != sem_wait(sem->internal)) {
- switch(errno) {
- case EINTR:
- break;
- case EINVAL:
- errexit(" ipc_semaphore_down called on invalid semaphore (in %s:%d)\n",
- filename,
- linenumber);
- case EDEADLK:
- errexit(" ipc_semaphore_down caused deadlock! (in %s:%d)\n",
- filename,
- linenumber);
- case EAGAIN:
- LOG(LOG_WARNING,
- "did not expect EAGAIN from sem_wait (in %s:%d).\n",
- filename,
- linenumber);
- break;
- default:
- LOG(LOG_ERROR,
- "did not expect %s from sem_wait at %s:%d\n",
- STRERROR(errno),
- filename,
- linenumber);
- break;
- }
- }
-#elif WINDOWS
- if (WaitForSingleObject(sem->internal, INFINITE) == WAIT_FAILED)
- LOG(LOG_WARNING,
- "WaitForSingleObject signaled error: %s at %s:%d\n",
- STRERROR(errno),
- filename,
- linenumber);
-#elif LINUX
- {
- struct sembuf sops = {0,-1,SEM_UNDO};
-
- while (0 != semop(sem->internal,&sops,1)) {
- switch(errno) {
- case EINTR:
- break;
- case EINVAL:
- errexit(" ipc_semaphore_down called on invalid semaphore (in %s:%d)\n",
- filename,
- linenumber);
- case EAGAIN:
- LOG(LOG_WARNING,
- "did not expect EAGAIN from sem_wait (in %s:%d).\n",
- filename,
- linenumber);
- break;
- default:
- LOG(LOG_ERROR,
- "did not expect %s from sem_wait at %s:%d\n",
- STRERROR(errno),
- filename,
- linenumber);
- break;
- }
- }
- }
-#elif SOMEBSD
- {
- int cnt;
-
- MUTEX_LOCK(&sem->internalLock);
- FLOCK(sem->fd, LOCK_EX);
- cnt = ntohl(0);
- while (htonl(cnt) == 0) {
- LSEEK(sem->fd, 0, SEEK_SET);
- if (sizeof(int) != READ(sem->fd, &cnt, sizeof(int))) {
- LOG(LOG_WARNING,
- "could not read IPC semaphore count (%s) at %s:%d!\n",
- STRERROR(errno),
- __FILE__,
- __LINE__);
- FLOCK(sem->fd, LOCK_UN);
- MUTEX_UNLOCK(&sem->internalLock);
- return;
- }
- if (htonl(cnt) == 0) {
- /* busy wait! */
- FLOCK(sem->fd, LOCK_UN);
- gnunet_util_sleep(50 * cronMILLIS);
- FLOCK(sem->fd, LOCK_EX);
- }
- }
-
- cnt = htonl(ntohl(cnt)-1);
- LSEEK(sem->fd, 0, SEEK_SET);
- if (sizeof(int) != WRITE(sem->fd, &cnt, sizeof(int)))
- LOG(LOG_WARNING,
- "could not write update to IPC file %s at %s:%d\n",
- sem->filename,
- __FILE__,
- __LINE__);
- FLOCK(sem->fd, LOCK_UN);
- MUTEX_UNLOCK(&sem->internalLock);
- }
-#else
-#endif
-}
-
-void ipc_semaphore_free_(IPC_Semaphore * rsem,
- const char * filename,
- const int linenumber) {
- IPC_Semaphore_Internal * sem;
- if (rsem == NULL) /* error on creation, optimistic execution; good luck */
- return;
- sem = rsem->platform;
- FREE(rsem);
-#if SOLARIS || OSX || FREEBSD5
- if (0 != sem_close(sem->internal))
- LOG(LOG_WARNING,
- "sem_close signaled error: %s at %s:%d\n",
- STRERROR(errno),
- filename,
- linenumber);
-#elif WINDOWS
- if (!CloseHandle(sem->internal))
- LOG(LOG_WARNING,
- "CloseHandle signaled error: %i at %s:%d\n",
- GetLastError(),
- filename,
- linenumber);
-#elif LINUX
- {
- int pcount;
-
- if (semop(sem->internal, &op_close[0], 3) < 0)
- LOG(LOG_WARNING,
- "semop signaled error: %s at %s:%d\n",
- STRERROR(errno),
- filename,
- linenumber);
-
- if ( (pcount = semctl(sem->internal, 1, GETVAL, 0)) < 0)
- LOG(LOG_WARNING,
- "semctl: %s at %s:%d\n",
- STRERROR(errno),
- filename,
- linenumber);
- if (pcount > PROCCOUNT)
- LOG(LOG_WARNING,
- "pcount too large at %s:%d\n",
- filename,
- linenumber);
- else if (pcount == PROCCOUNT) {
- if (0 != semctl(sem->internal,0,IPC_RMID,0))
- LOG(LOG_WARNING,
- "semctl signaled error: %s at %s:%d\n",
- STRERROR(errno),
- filename,
- linenumber);
- UNLINK(sem->filename);
- } else {
- if (semop(sem->internal, &op_unlock[0], 1) < 0)
- LOG(LOG_WARNING,
- "semop %s %s:%d\n",
- STRERROR(errno),
- filename,
- linenumber);
- }
- FREE(sem->filename);
- }
-#elif SOMEBSD
- {
- int cnt;
-
- MUTEX_DESTROY(&sem->internalLock);
- FLOCK(sem->fd, LOCK_EX);
- LSEEK(sem->fd, sizeof(int), SEEK_SET);
- if (sizeof(int) == READ(sem->fd, &cnt, sizeof(int))) {
- cnt = htonl(ntohl(cnt)-1);
- LSEEK(sem->fd, sizeof(int), SEEK_SET);
- if (sizeof(int) != WRITE(sem->fd, &cnt, sizeof(int)))
- LOG(LOG_WARNING,
- "could not write to IPC file %s at %s:%d\n",
- sem->filename,
- __FILE__,
- __LINE__);
- if (ntohl(cnt) == 0) {
- UNLINK(sem->filename);
- }
- } else
- LOG(LOG_WARNING,
- "could not read process count of IPC %s at %s:%d\n",
- sem->filename,
- __FILE__,
- __LINE__);
- FREE(sem->filename);
- FLOCK(sem->fd, LOCK_UN);
- closefile(sem->fd);
- }
-#else
-#endif
- FREE(sem);
-}
-
-
-/* end of semaphore.c */
Deleted: GNUnet/src/util/semaphoretest.c
===================================================================
--- GNUnet/src/util/semaphoretest.c 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/semaphoretest.c 2006-06-22 17:50:56 UTC (rev 3024)
@@ -1,339 +0,0 @@
-/**
- * @file test/hashtest.c
- * @brief testcase for util/semaphore.c
- */
-
-#include "gnunet_util.h"
-#include "platform.h"
-
-#include <sys/types.h>
-#ifndef MINGW /* PORT-ME MINGW */
-
-
-static Mutex lock;
-
-static Semaphore * sem;
-
-static volatile int sv;
-
-static volatile int tv;
-
-static IPC_Semaphore * ipc;
-
-static void lockIt() {
- sv = 0;
- fprintf(stderr, ".");
- while (sv == 0)
- gnunet_util_sleep(50 * cronMILLIS); /* busy waiting may not always work */
- MUTEX_LOCK(&lock);
- sv = 1;
- MUTEX_UNLOCK(&lock);
- sv = 2;
- tv = 2;
-}
-
-static void bigStack() {
- int i;
- char big[1024 * 100];
-
- fprintf(stderr, ".");
- for (i=0;i<1024*100;i++)
- big[i] = (char) i;
-}
-
-static int testPTHREAD_CREATE() {
- PTHREAD_T pt;
- void * unused;
-
- sv = -1; tv = 0;
- fprintf(stderr, ".");
- MUTEX_CREATE(&lock);
- PTHREAD_CREATE(&pt,
- (PThreadMain)&lockIt,
- NULL,
- 1024);
- PTHREAD_DETACH(&pt);
- while (tv != 2) {
- sv = 1;
- gnunet_util_sleep(50 * cronMILLIS); /* busy waiting may not always work */
- }
- MUTEX_DESTROY(&lock);
- PTHREAD_CREATE(&pt,
- (PThreadMain)&bigStack,
- NULL,
- 1024*100 + 25000); /* fails by segfault */
- PTHREAD_JOIN(&pt, &unused);
- return 0;
-}
-
-static int testMutex() {
- PTHREAD_T pt;
- void * unused;
- MUTEX_CREATE(&lock);
-
- sv = 1;
- tv = 0;
- PTHREAD_CREATE(&pt,
- (PThreadMain)&lockIt,
- NULL,
- 1024);
- while (sv == 1)
- gnunet_util_sleep(50 * cronMILLIS); /* busy waiting may not always work */
- MUTEX_LOCK(&lock);
- sv = 5; /* release lockIt from while sv==0 loop,
- blocks it on lock */
- fprintf(stderr, ".");
-
- if (sv != 5) {
- MUTEX_UNLOCK(&lock);
- while (tv != 2)
- gnunet_util_sleep(50 * cronMILLIS); /* busy waiting may not always work
*/
- MUTEX_DESTROY(&lock);
- printf("MUTEX test failed at %s:%u\n",
- __FILE__, __LINE__);
- return 1; /* error */
- } else {
- MUTEX_UNLOCK(&lock);
- while (tv != 2)
- gnunet_util_sleep(50 * cronMILLIS); /* busy waiting may not always work
*/
- PTHREAD_JOIN(&pt, &unused);
- MUTEX_DESTROY(&lock);
- return 0; /* ok */
- }
-}
-
-static int testRecursiveMutex() {
- int i;
-
- fprintf(stderr, ".");
- MUTEX_CREATE_RECURSIVE(&lock);
- for (i=0;i<50;i++)
- MUTEX_LOCK(&lock);
- for (i=0;i<50;i++)
- MUTEX_UNLOCK(&lock);
- MUTEX_DESTROY(&lock);
- return 0; /* ok -- fails by hanging!*/
-}
-
-static void semUpDown() {
- int i;
-
- fprintf(stderr, ".");
- for (i=0;i<42;i++)
- SEMAPHORE_DOWN(sem); /* fails by blocking */
- if (SEMAPHORE_DOWN_NONBLOCKING(sem) != SYSERR) {
- SEMAPHORE_FREE(sem);
- printf("SEMAPHORE_DOWN_NONBLOCKING failed at %s:%u\n"
- "Testcase deadlocked.\n",
- __FILE__, __LINE__);
- return; /* will halt testcase! */
- }
- for (i=0;i<42;i++)
- SEMAPHORE_UP(sem);
-}
-
-static int testSemaphore() {
- int i;
- PTHREAD_T pt;
- void * unused;
-
- sem = SEMAPHORE_NEW(42);
- fprintf(stderr, ".");
- for (i=0;i<42;i++)
- SEMAPHORE_DOWN(sem); /* fails by blocking */
- if (SEMAPHORE_DOWN_NONBLOCKING(sem) != SYSERR) {
- SEMAPHORE_FREE(sem);
- printf("SEMAPHORE_DOWN_NONBLOCKING failed at %s:%u\n",
- __FILE__, __LINE__);
- return 1;
- }
- for (i=0;i<42;i++)
- SEMAPHORE_UP(sem);
- for (i=0;i<42;i++)
- if (OK != SEMAPHORE_DOWN_NONBLOCKING(sem)) {
- SEMAPHORE_FREE(sem);
- printf("SEMAPHORE_DOWN_NONBLOCKING failed at %s:%u\n",
- __FILE__, __LINE__);
- return 1;
- }
- if (SEMAPHORE_DOWN_NONBLOCKING(sem) != SYSERR) {
- SEMAPHORE_FREE(sem);
- printf("SEMAPHORE_DOWN_NONBLOCKING failed at %s:%u\n",
- __FILE__, __LINE__);
- return 1;
- }
- fprintf(stderr, ".");
- PTHREAD_CREATE(&pt,
- (PThreadMain)&semUpDown,
- NULL,
- 1024);
- for (i=0;i<42;i++)
- SEMAPHORE_UP(sem);
- PTHREAD_JOIN(&pt, &unused);
- for (i=0;i<42;i++)
- SEMAPHORE_DOWN(sem);
- if (SEMAPHORE_DOWN_NONBLOCKING(sem) != SYSERR) {
- SEMAPHORE_FREE(sem);
- printf("SEMAPHORE_DOWN_NONBLOCKING failed at %s:%u\n",
- __FILE__, __LINE__);
- return 1;
- }
- return 0;
-}
-
-static int testIPCSemaphore() {
- pid_t me;
- int cnt;
- int i;
- int j;
- FILE * fd;
- int ret;
- int si;
- int sw;
-
- ret = 0;
- REMOVE("/tmp/gnunet_ipc_xchange");
- REMOVE("/tmp/gnunet_ipc_semtest");
- me = fork();
- sw = me;
-
- ipc = IPC_SEMAPHORE_NEW("/tmp/gnunet_ipc_semtest",
- 0);
- for (cnt=0;cnt<3;cnt++) {
- if (sw == 0) {
- for (i=0;i<6;i++) {
- IPC_SEMAPHORE_DOWN(ipc);
- fd = FOPEN("/tmp/gnunet_ipc_xchange",
- "a+");
- if (fd == NULL) {
- printf("Could not open testfile for reading: %s\n",
- STRERROR(errno));
- ret = 1;
- goto END;
- }
- fseek(fd, 4*i, SEEK_SET);
- si = GN_FREAD(&j, 4, 1, fd);
- while (si == 0)
- si = GN_FREAD(&j, 4, 1, fd);
- if (si != 1) {
- printf("Could not read from testfile: %d - %s at %s:%d\n",
- si,
- STRERROR(errno),
- __FILE__,
- __LINE__);
- ret = 1;
- goto END;
- }
- fclose(fd);
- if (j != i+cnt) {
- printf("IPC test failed at cnt=%d i=%d j=%d %s:%u\n",
- cnt, i, j, __FILE__, __LINE__);
- ret = 1;
- goto END;
- } else
- fprintf(stderr, ".");
- }
- REMOVE("/tmp/gnunet_ipc_xchange");
- sw = 1;
- } else {
- for (i=0;i<6;i++) {
- sleep(1);
- fd = FOPEN("/tmp/gnunet_ipc_xchange",
- "w+");
- if (fd == NULL) {
- printf("Could not open testfile for writing: %s\n",
- STRERROR(errno));
- ret = 1;
- goto END;
- }
- fseek(fd, 4*i, SEEK_SET);
- j=cnt+i;
- if (1 != GN_FWRITE(&j, 4, 1, fd)) {
- printf("Could not write to testfile: %s\n",
- STRERROR(errno));
- ret = 1;
- goto END;
- }
- fclose(fd);
- IPC_SEMAPHORE_UP(ipc);
- }
- fprintf(stderr, ".");
- sleep(2); /* give reader ample time to finish */
- sw = 0;
- }
- }
- END:
- IPC_SEMAPHORE_FREE(ipc);
- REMOVE("/tmp/gnunet_ipc_xchange");
- if (me == 0) {
- exit(ret);
- } else {
- LOG(LOG_DEBUG,
- " waiting for other process to exit.\n");
- if (-1 == waitpid(me, &j, 0))
- LOG(LOG_ERROR,
- " waitpid failed: %s\n",
- STRERROR(errno));
- if ((! WIFEXITED(j)) || WEXITSTATUS(j) == 1)
- ret = 1; /* error in child */
- }
- return ret;
-}
-
-
-/**
- * Perform option parsing from the command line.
- */
-static int parseCommandLine(int argc,
- char * argv[]) {
- char c;
-
- while (1) {
- int option_index = 0;
- static struct GNoption long_options[] = {
- { "loglevel",1, 0, 'L' },
- { "config", 1, 0, 'c' },
- { 0,0,0,0 }
- };
-
- c = GNgetopt_long(argc,
- argv,
- "c:L:",
- long_options,
- &option_index);
-
- if (c == -1)
- break; /* No more flags to process */
-
- switch(c) {
- case 'L':
- FREENONNULL(setConfigurationString("GNUNET",
- "LOGLEVEL",
- GNoptarg));
- break;
- case 'c':
- FREENONNULL(setConfigurationString("FILES",
- "gnunet.conf",
- GNoptarg));
- break;
- } /* end of parsing commandline */
- }
- return OK;
-}
-#endif /* PORT-ME MINGW */
-
-int main(int argc, char * argv[]){
- int ret = 0;
-
-#ifndef MINGW
- initUtil(argc, argv, &parseCommandLine);
- ret += testPTHREAD_CREATE();
- ret += testMutex();
- ret += testRecursiveMutex();
- ret += testSemaphore();
- ret += testIPCSemaphore();
- fprintf(stderr, "\n");
- doneUtil();
-#endif
- return ret;
-}
Deleted: GNUnet/src/util/shutdown.c
===================================================================
--- GNUnet/src/util/shutdown.c 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/shutdown.c 2006-06-22 17:50:56 UTC (rev 3024)
@@ -1,138 +0,0 @@
-/*
- This file is part of GNUnet.
- (C) 2001, 2002 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/shutdown.c
- * @brief code to allow clean shutdown of application with signals
- * @author Christian Grothoff
- *
- * Helper code for writing proper termination code when an application
- * receives a SIGTERM/SIGHUP etc.
- */
-
-#include "gnunet_util.h"
-#include "platform.h"
-
-/**
- * Semaphore used to signal "shutdown"
- */
-static Semaphore * shutdown_signal = NULL;
-static int shutdown_active;
-
-/**
- * Stop the application.
- * @param signum is ignored
- */
-void run_shutdown(int signum) {
- if (shutdown_signal != NULL) {
- shutdown_active = YES;
- SEMAPHORE_UP(shutdown_signal);
- }
-}
-
-/**
- * Stop the application under Windows.
- * @param signum is ignored
- */
-#ifdef MINGW
-BOOL WINAPI run_shutdown_win(DWORD dwCtrlType)
-{
- switch(dwCtrlType)
- {
- case CTRL_C_EVENT:
- case CTRL_CLOSE_EVENT:
- case CTRL_SHUTDOWN_EVENT:
- case CTRL_LOGOFF_EVENT:
- run_shutdown(1);
- }
-
- return TRUE;
-}
-#endif
-
-
-/**
- * Test if the shutdown has been initiated.
- * @return YES if we are shutting down, NO otherwise
- */
-int testShutdown() {
- return shutdown_active;
-}
-
-/**
- * Initialize the signal handlers, etc.
- */
-void initializeShutdownHandlers() {
-#ifndef MINGW
- struct sigaction sig;
- struct sigaction oldsig;
-#endif
-
- if (shutdown_signal != NULL)
- errexit(" initializeShutdownHandlers called twice!\n");
- shutdown_signal = SEMAPHORE_NEW(0);
- shutdown_active = NO;
-#ifndef MINGW
- sig.sa_handler = &run_shutdown;
- sigemptyset(&sig.sa_mask);
-#ifdef SA_INTERRUPT
- sig.sa_flags = SA_INTERRUPT; /* SunOS */
-#else
- sig.sa_flags = SA_RESTART;
-#endif
- sigaction(SIGINT, &sig, &oldsig);
- sigaction(SIGTERM, &sig, &oldsig);
- sigaction(SIGQUIT, &sig, &oldsig);
-#else
- SetConsoleCtrlHandler(&run_shutdown_win, TRUE);
-#endif
-}
-
-/**
- * Wait until the shutdown has been initiated.
- */
-void wait_for_shutdown() {
- SEMAPHORE_DOWN(shutdown_signal);
-}
-
-void doneShutdownHandlers() {
-#ifndef MINGW
- struct sigaction sig;
- struct sigaction oldsig;
-
- sig.sa_handler = SIG_DFL;
- sigemptyset(&sig.sa_mask);
-#ifdef SA_INTERRUPT
- sig.sa_flags = SA_INTERRUPT; /* SunOS */
-#else
- sig.sa_flags = SA_RESTART;
-#endif
- sigaction(SIGINT, &sig, &oldsig);
- sigaction(SIGTERM, &sig, &oldsig);
- sigaction(SIGQUIT, &sig, &oldsig);
-#else
- SetConsoleCtrlHandler(&run_shutdown_win, FALSE);
-#endif
-
- SEMAPHORE_FREE(shutdown_signal);
- shutdown_signal = NULL;
-}
-
-/* end of shutdown.c */
Deleted: GNUnet/src/util/shutdowntest.c
===================================================================
--- GNUnet/src/util/shutdowntest.c 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/shutdowntest.c 2006-06-22 17:50:56 UTC (rev 3024)
@@ -1,95 +0,0 @@
-/**
- * @file test/shutdowntest.c
- * @brief testcase for util/shutdown.c
- */
-
-#include "gnunet_util.h"
-#include "platform.h"
-
-static pid_t myPID;
-
-static int check() {
- /* first, test / SIGINT (simulated) */
- initializeShutdownHandlers();
- if (testShutdown() != NO)
- return 1;
-#ifndef MINGW
- kill(myPID, SIGINT);
-#else
- GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0);
-#endif
- if (testShutdown() != YES)
- return 2;
- wait_for_shutdown();
- doneShutdownHandlers();
-
- /* now, test "run_shutdown" */
- initializeShutdownHandlers();
- if (testShutdown() != NO)
- return 3;
- run_shutdown(42);
- if (testShutdown() != YES)
- return 4;
- wait_for_shutdown();
- doneShutdownHandlers();
-
- return 0;
-}
-
-
-/**
- * Perform option parsing from the command line.
- */
-static int parseCommandLine(int argc,
- char * argv[]) {
- char c;
-
- while (1) {
- int option_index = 0;
- static struct GNoption long_options[] = {
- { "config", 1, 0, 'c' },
- { 0,0,0,0 }
- };
-
- c = GNgetopt_long(argc,
- argv,
- "c:",
- long_options,
- &option_index);
-
- if (c == -1)
- break; /* No more flags to process */
-
- switch(c) {
- case 'c':
- FREENONNULL(setConfigurationString("FILES",
- "gnunet.conf",
- GNoptarg));
- break;
- } /* end of parsing commandline */
- }
- FREENONNULL(setConfigurationString("GNUNETD",
- "LOGFILE",
- NULL));
- FREENONNULL(setConfigurationString("GNUNETD",
- "LOGLEVEL",
- "WARNING"));
- return OK;
-}
-
-int main(int argc,
- char * argv[]){
- int ret;
-
- myPID = getpid();
- initUtil(argc, argv, &parseCommandLine);
-
- ret = check();
- if (ret != 0)
- fprintf(stderr,
- "ERROR %d\n", ret);
- doneUtil();
- return ret;
-}
-
-/* end of shutdowntest.c */
Deleted: GNUnet/src/util/state.c
===================================================================
--- GNUnet/src/util/state.c 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/state.c 2006-06-22 17:50:56 UTC (rev 3024)
@@ -1,272 +0,0 @@
-/*
- This file is part of GNUnet.
- (C) 2002, 2003, 2004 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/state.c
- * @brief tiny, stateful database too keep track of internal state
- *
- * Directory based implementation of a tiny, stateful database
- * to keep track of GNUnet _internal_ configuration parameters
- * that users are not supposed to see (e.g. *previous* quota,
- * previous database type for AFS, etc.)
- *
- *
- * @author Christian Grothoff
- */
-
-#include "gnunet_util.h"
-#include "platform.h"
-
-#include <sys/stat.h>
-
-
-#define STATE_DEBUG NO
-
-#define DIR_EXT "state.sdb"
-
-static char * handle = NULL;
-
-/**
- * Initialize the Directory module, expand filename
- * @param dir the directory where content is configured to be stored (e.g.
~/.gnunet/data/content).
- */
-static char * getDirectory(char * dir) {
- char * result;
- char * tmp;
- size_t n;
-
-#if STATE_DEBUG
- LOG(LOG_DEBUG,
- "Database (state): %s\n",
- dir);
-#endif
- n = strlen(dir) + strlen(DIR_EXT) + 5;
- tmp = MALLOC(n);
- SNPRINTF(tmp, n, "%s/%s/", dir, DIR_EXT);
- result = expandFileName(tmp);
- FREE(tmp);
- return result;
-}
-
-void initState() {
- char * dbh;
- char * dir;
- char * base;
- char * baseSect;
-
- if (testConfigurationString("GNUNETD",
- "_MAGIC_",
- "YES")) {
- base = "GNUNETD_HOME";
- baseSect = "GNUNETD";
- }
- else {
- base = "GNUNET_HOME";
- baseSect = "GNUNET";
- }
- dir = getFileName(baseSect,
- base,
- _("Configuration file must specify a directory"
- " for GNUnet to store per-peer data under %s\\%s.\n"));
- dbh = getDirectory(dir);
- FREE(dir);
- GNUNET_ASSERT(dbh != NULL);
- mkdirp(dbh);
- handle = dbh;
-}
-
-/**
- * Clean shutdown of the storage module (not used at the moment)
- */
-void doneState() {
- if (handle == NULL)
- return; /* bogus call! */
- FREE(handle);
- handle = NULL;
-}
-
-/**
- * Read the contents of a bucket to a buffer.
- *
- * @param name the hashcode representing the entry
- * @param result the buffer to write the result to
- * (*result should be NULL, sufficient space is allocated)
- * @return the number of bytes read on success, -1 on failure
- */
-int stateReadContent(const char * name,
- void ** result) {
- /* open file, must exist, open read only */
- char * dbh = handle;
- int fd;
- int size;
- char * fil;
- unsigned long long fsize;
- size_t n;
-
- GNUNET_ASSERT(handle != NULL);
- if (result == NULL)
- return -1;
- n = strlen(dbh) + strlen(name) + 2;
- fil = MALLOC(n);
- SNPRINTF(fil,
- n,
- "%s/%s",
- dbh,
- name);
- if (OK != getFileSize(fil,
- &fsize)) {
- FREE(fil);
- return -1;
- }
- fd = fileopen(fil,
- O_RDONLY,
- S_IRUSR);
- if (fd == -1) {
- FREE(fil);
- return -1;
- }
- FREE(fil);
- if (fsize == 0) { /* also invalid! */
- closefile(fd);
- return -1;
- }
-
- *result = xmalloc_unchecked_(fsize, __FILE__, __LINE__);
- size = READ(fd,
- *result,
- fsize);
- closefile(fd);
- if (size == -1) {
- FREE(*result);
- *result = NULL;
- }
- return size;
-}
-
-
-/**
- * Append content to file.
- *
- * @param name the key for the entry
- * @param len the number of bytes in block
- * @param block the data to store
- * @return SYSERR on error, OK if ok.
- */
-int stateAppendContent(const char * name,
- int len,
- const void * block) {
- char * dbh = handle;
- char * fil;
- int fd;
- size_t n;
-
- GNUNET_ASSERT(handle != NULL);
- n = strlen(dbh) + strlen(name) + 2;
- fil = MALLOC(n);
- SNPRINTF(fil,
- n,
- "%s/%s",
- dbh,
- name);
- fd = fileopen(fil,
- O_RDWR|O_CREAT,
- S_IRUSR|S_IWUSR);
- if (fd == -1) {
- LOG_FILE_STRERROR(LOG_WARNING, "open", fil);
- FREE(fil);
- return SYSERR; /* failed! */
- }
- FREE(fil);
- lseek(fd,
- 0,
- SEEK_END);
- WRITE(fd,
- block,
- len);
- closefile(fd);
- return OK;
-}
-
-/**
- * Write content to a file.
- *
- * @param name the key for the entry
- * @param len the number of bytes in block
- * @param block the data to store
- * @return SYSERR on error, OK if ok.
- */
-int stateWriteContent(const char * name,
- int len,
- const void * block) {
- char * dbh = handle;
- char * fil;
- int fd;
- size_t n;
-
- GNUNET_ASSERT(handle != NULL);
- n = strlen(dbh) + strlen(name) + 2;
- fil = MALLOC(n);
- SNPRINTF(fil,
- n,
- "%s/%s",
- dbh,
- name);
- fd = fileopen(fil,
- O_RDWR|O_CREAT,
- S_IRUSR|S_IWUSR);
- if (fd == -1) {
- LOG_FILE_STRERROR(LOG_WARNING, "open", fil);
- FREE(fil);
- return SYSERR; /* failed! */
- }
- WRITE(fd,
- block,
- len);
- if (0 != ftruncate(fd, len))
- LOG_FILE_STRERROR(LOG_WARNING, "ftruncate", fil);
- closefile(fd);
- FREE(fil);
- return OK;
-}
-
-/**
- * Free space in the database by removing one file
- * @param name the hashcode representing the name of the file
- * (without directory)
- */
-int stateUnlinkFromDB(const char * name) {
- char * dbh = handle;
- char * fil;
- size_t n;
-
- GNUNET_ASSERT(handle != NULL);
- n = strlen(dbh) + strlen(name) + 2;
- fil = MALLOC(n);
- SNPRINTF(fil,
- n,
- "%s/%s",
- dbh,
- name);
- UNLINK(fil);
- FREE(fil);
- return OK;
-}
-
-/* end of state.c */
Deleted: GNUnet/src/util/statetest.c
===================================================================
--- GNUnet/src/util/statetest.c 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/statetest.c 2006-06-22 17:50:56 UTC (rev 3024)
@@ -1,81 +0,0 @@
-/**
- * @file test/storagetest.c
- * @brief testcase for the state module
- * @author Christian Grothoff
- */
-
-#include "gnunet_util.h"
-#include "platform.h"
-
-/**
- * Perform option parsing from the command line.
- */
-static int parseCommandLine(int argc,
- char * argv[]) {
- char c;
-
- while (1) {
- int option_index = 0;
- static struct GNoption long_options[] = {
- { "config", 1, 0, 'c' },
- { 0,0,0,0 }
- };
-
- c = GNgetopt_long(argc,
- argv,
- "c:",
- long_options,
- &option_index);
-
- if (c == -1)
- break; /* No more flags to process */
-
- switch(c) {
- case 'c':
- FREENONNULL(setConfigurationString("FILES",
- "gnunet.conf",
- GNoptarg));
- break;
- } /* end of parsing commandline */
- }
- FREENONNULL(setConfigurationString("GNUNETD",
- "LOGLEVEL",
- "NOTHING"));
- return OK;
-}
-
-#define TH "TestHandle"
-
-int testState() {
- char * testString = "Hello World";
- char * ret;
-
- stateUnlinkFromDB(TH); /* go to defined state */
- if (SYSERR == stateWriteContent(TH,
- 5,
- testString))
- return 1;
- if (SYSERR == stateAppendContent(TH,
- 6,
- &testString[5]))
- return 2;
- ret = NULL;
- if (SYSERR == stateReadContent(TH,
- (void**)&ret))
- return 3;
- if (0 != strncmp(ret, testString, 11))
- return 4;
- FREE(ret);
- if (OK != stateUnlinkFromDB(TH))
- return 5;
- return 0;
-}
-
-int main(int argc, char * argv[]) {
- int ret = 0;
- initUtil(argc, argv, &parseCommandLine);
- ret = testState();
-
- doneUtil();
- return ret;
-} /* end of main */
Deleted: GNUnet/src/util/statuscalls.c
===================================================================
--- GNUnet/src/util/statuscalls.c 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/statuscalls.c 2006-06-22 17:50:56 UTC (rev 3024)
@@ -1,873 +0,0 @@
-/*
- This file is part of GNUnet.
- (C) 2001, 2002, 2003, 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/statuscalls.c
- * @brief calls to determine current network and CPU load
- * @author Tzvetan Horozov
- * @author Christian Grothoff
- * @author Igor Wronsky
- *
- * Status calls implementation for load management.
- */
-
-#include "platform.h"
-#include "gnunet_util.h"
-
-#if SOLARIS
-#if HAVE_KSTAT_H
-#include <kstat.h>
-#endif
-#if HAVE_SYS_SYSINFO_H
-#include <sys/sysinfo.h>
-#endif
-#if HAVE_KVM_H
-#include <kvm.h>
-#endif
-#endif
-#if SOMEBSD
-#if HAVE_KVM_H
-#include <kvm.h>
-#endif
-#endif
-
-#define DEBUG_STATUSCALLS NO
-
-/**
- * where to read network interface information from
- * under Linux
- */
-#define PROC_NET_DEV "/proc/net/dev"
-
-typedef struct {
- char * name;
- unsigned long long last_in;
- unsigned long long last_out;
-} NetworkStats;
-
-/**
- * Traffic counter for only gnunetd traffic.
- */
-static NetworkStats globalTrafficBetweenProc;
-
-/**
- * tracking
- */
-static NetworkStats * ifcs;
-
-/**
- * how many interfaces do we have?
- */
-static unsigned int ifcsSize;
-
-/**
- * Current load of the machine, -1 for error
- */
-static int currentLoad;
-
-/**
- * Maximum bandwidth (down) as per config.
- */
-static int maxNetDownBPS;
-
-/**
- * Maximum bandwidth (up) as per config.
- */
-static int maxNetUpBPS;
-
-/**
- * Maximum load as per config.
- */
-static int maxCPULoad;
-
-/**
- * How to measure traffic (YES == only gnunetd,
- * NO == try to include all apps)
- */
-static int useBasicMethod = YES;
-
-/**
- * Lock.
- */
-static Mutex statusMutex;
-
-static int initialized_ = NO;
-
-#ifdef LINUX
-static FILE * proc_stat;
-static FILE * proc_net_dev;
-#endif
-
-/**
- * Increment the number of bytes sent. Transports should use this
- * so that statuscalls module can measure gnunet traffic usage between
- * calls to /proc.
- *
- * Note: the caller doesn't know what interface it is attached to,
- * so this type of bandwidth limitation is always global (for all
- * network interfaces).
- */
-void incrementBytesSent(unsigned long long delta) {
- if (initialized_ == NO)
- return;
- MUTEX_LOCK(&statusMutex);
- globalTrafficBetweenProc.last_out += delta;
- MUTEX_UNLOCK(&statusMutex);
-}
-
-void incrementBytesReceived(unsigned long long delta) {
- if (initialized_ == NO)
- return;
- MUTEX_LOCK(&statusMutex);
- globalTrafficBetweenProc.last_in += delta;
- MUTEX_UNLOCK(&statusMutex);
-}
-
-/**
- * Reset the traffic counters for GNUnet traffic between
- * systemwide readings.
- */
-static void resetBetweenProc() {
- globalTrafficBetweenProc.last_in = 0;
- globalTrafficBetweenProc.last_out = 0;
-}
-
-#define MAX_PROC_LINE 5000
-
-static void updateInterfaceTraffic() {
-#ifdef LINUX
- unsigned long long rxnew;
- unsigned long long txnew;
- char line[MAX_PROC_LINE];
- char * data;
- int i;
- int found;
-
- MUTEX_LOCK(&statusMutex);
- if (proc_net_dev != NULL) {
- found = 0;
- rewind(proc_net_dev);
- fflush(proc_net_dev);
- /* Parse the line matching the interface ('eth0') */
- while (! feof(proc_net_dev) ) {
- if (NULL == fgets(line,
- MAX_PROC_LINE,
- proc_net_dev))
- break;
- for (i=0;i<ifcsSize;i++) {
- if (NULL != strstr(line, ifcs[i].name) ) {
- data = strchr(line, ':');
- if (data == NULL)
- continue;
- data++;
- if (2 != SSCANF(data,
- "%llu %*s %*s %*s %*s %*s %*s %*s %llu",
- &rxnew,
- &txnew)) {
- LOG(LOG_ERROR,
- _("Failed to parse interface data from `%s' at %s:%d.\n"),
- PROC_NET_DEV,
- __FILE__,
- __LINE__);
- continue;
- }
- ifcs[i].last_in = rxnew;
- ifcs[i].last_out = txnew;
- resetBetweenProc();
- break;
- }
- }
- }
- }
- MUTEX_UNLOCK(&statusMutex);
-
-#elif MINGW
- unsigned long long rxnew;
- unsigned long long txnew;
- int i;
- PMIB_IFTABLE pTable;
- DWORD dwIfIdx;
- unsigned long long l;
- BYTE bPhysAddr[MAXLEN_PHYSADDR];
- int iLine = 0;
- char line[MAX_PROC_LINE];
- FILE * command;
-
- MUTEX_LOCK(&statusMutex);
- /* Win 98 and NT SP 4 */
- if (GNGetIfEntry) {
- EnumNICs(&pTable, NULL);
- for (i=0;i<ifcsSize;i++) {
- for (dwIfIdx=0; dwIfIdx < pTable->dwNumEntries; dwIfIdx++) {
- l = _atoi64(ifcs[i].name);
-
- memset(bPhysAddr,
- 0,
- MAXLEN_PHYSADDR);
- memcpy(bPhysAddr,
- pTable->table[dwIfIdx].bPhysAddr,
- pTable->table[dwIfIdx].dwPhysAddrLen);
-
- if (0 == memcmp(bPhysAddr,
- &l,
- sizeof(unsigned long long))) {
- ifcs[i].last_in
- = pTable->table[dwIfIdx].dwInOctets;
- ifcs[i].last_out
- = pTable->table[dwIfIdx].dwOutOctets;
- resetBetweenProc();
- break;
- }
- }
- }
- GlobalFree(pTable);
- } else { /* Win 95 */
- if ( ( command = popen("netstat -e", "rt") ) == NULL ) {
- LOG_FILE_STRERROR(LOG_ERROR,
- "popen",
- "netstat -e");
- MUTEX_UNLOCK(&statusMutex);
- return;
- }
- while (!feof(command)) {
- if (NULL == fgets(line,
- MAX_PROC_LINE,
- command))
- break;
- /* PORT-ME: any way to do this per-ifc? */
- if (iLine == 1) {
- sscanf("%*s%i%i",
- &rxnew,
- &txnew);
- ifcs[0].last_in
- = rxnew;
- ifcs[0].last_out
- = txnew;
- resetBetweenProc();
- break;
- }
- iLine++;
- }
- pclose(command);
- }
- MUTEX_UNLOCK(&statusMutex);
-#else
- /* PORT-ME! */
-#endif
-}
-
-/**
- * The following routine returns a number between 0-100 (can be larger
- * than 100 if the load is > 1) which indicates the percentage CPU
- * usage.
- *
- * Before its first invocation the method initStatusCalls() must be called.
- * If there is an error the method returns -1
- */
-static void updateCpuUsage(){
- if (initialized_ == NO) {
- currentLoad = -1;
- return;
- }
- MUTEX_LOCK(&statusMutex);
-
-#ifdef LINUX
- /* under linux, first try %idle/usage using /proc/stat;
- if that does not work, disable /proc/stat for the future
- by closing the file and use the next-best method. */
- if (proc_stat != NULL) {
- static unsigned long long last_cpu_results[4] = { 0, 0, 0, 0 };
- static int have_last_cpu = NO;
- char line[128];
- unsigned long long user_read, system_read, nice_read, idle_read;
- unsigned long long user, system, nice, idle;
- unsigned long long usage_time=0, total_time=1;
-
- /* Get the first line with the data */
- rewind(proc_stat);
- fflush(proc_stat);
- if (NULL == fgets(line, 128, proc_stat)) {
- LOG_FILE_STRERROR(LOG_ERROR,
- "fgets",
- "/proc/stat");
- fclose(proc_stat);
- proc_stat = NULL; /* don't try again */
- } else {
- if (sscanf(line, "%*s %llu %llu %llu %llu",
- &user_read,
- &system_read,
- &nice_read,
- &idle_read) != 4) {
- LOG_FILE_STRERROR(LOG_ERROR,
- "fgets-sscanf",
- "/proc/stat");
- fclose(proc_stat);
- proc_stat = NULL; /* don't try again */
- have_last_cpu = NO;
- } else {
- /* Store the current usage*/
- user = user_read - last_cpu_results[0];
- system = system_read - last_cpu_results[1];
- nice = nice_read - last_cpu_results[2];
- idle = idle_read - last_cpu_results[3];
- /* Calculate the % usage */
- if ( (user + system + nice + idle) > 0) {
- usage_time = user + system + nice;
- total_time = usage_time + idle;
- }
- if ( (total_time > 0) &&
- (have_last_cpu == YES) )
- currentLoad = (100 * usage_time) / total_time;
- else
- currentLoad = -1;
- /* Store the values for the next calculation*/
- last_cpu_results[0] = user_read;
- last_cpu_results[1] = system_read;
- last_cpu_results[2] = nice_read;
- last_cpu_results[3] = idle_read;
- have_last_cpu = YES;
- MUTEX_UNLOCK(&statusMutex);
- return;
- }
- }
- }
-#endif
-
- /* try kstat (Solaris only) */
-#if SOLARIS && HAVE_KSTAT_H && HAVE_SYS_SYSINFO_H
- {
- static long long last_idlecount;
- static long long last_totalcount;
- static int kstat_once; /* if open fails, don't keep
- trying */
- kstat_ctl_t * kc;
- kstat_t * khelper;
- long long idlecount;
- long long totalcount;
- long long deltaidle;
- long long deltatotal;
-
- if (kstat_once == 1)
- goto ABORT_KSTAT;
- kc = kstat_open();
- if (kc == NULL) {
- LOG_STRERROR(LOG_ERROR, "kstat_open");
- goto ABORT_KSTAT;
- }
-
- idlecount = 0;
- totalcount = 0;
- for (khelper = kc->kc_chain;
- khelper != NULL;
- khelper = khelper->ks_next) {
- cpu_stat_t stats;
-
- if (0 != strncmp(khelper->ks_name,
- "cpu_stat",
- strlen("cpu_stat")) )
- continue;
- if (khelper->ks_data_size > sizeof(cpu_stat_t))
- continue; /* better save then sorry! */
- if (-1 != kstat_read(kc, khelper, &stats)) {
- idlecount
- += stats.cpu_sysinfo.cpu[CPU_IDLE];
- totalcount
- += stats.cpu_sysinfo.cpu[CPU_IDLE] +
- stats.cpu_sysinfo.cpu[CPU_USER] +
- stats.cpu_sysinfo.cpu[CPU_KERNEL] +
- stats.cpu_sysinfo.cpu[CPU_WAIT];
- }
- }
- if (0 != kstat_close(kc))
- LOG_STRERROR(LOG_ERROR, "kstat_close");
- if ( (idlecount == 0) &&
- (totalcount == 0) )
- goto ABORT_KSTAT; /* no stats found => abort */
- deltaidle = idlecount - last_idlecount;
- deltatotal = totalcount - last_totalcount;
- if ( (deltatotal > 0) &&
- (last_totalcount > 0) )
- currentLoad = (int) (100 * deltaidle / deltatotal);
- else
- currentLoad = -1;
- last_idlecount = idlecount;
- last_totalcount = totalcount;
- MUTEX_UNLOCK(&statusMutex);
- return;
- ABORT_KSTAT:
- kstat_once = 1; /* failed, don't try again */
- }
-#endif
-
- /* insert methods better than getloadavg for
- other platforms HERE! */
-
- /* ok, maybe we have getloadavg on this platform */
-#if HAVE_GETLOADAVG
- {
- static int warnOnce = 0;
- double loadavg;
- if (1 != getloadavg(&loadavg, 1)) {
- /* only warn once, if there is a problem with
- getloadavg, we're going to hit it frequently... */
- if (warnOnce == 0) {
- warnOnce = 1;
- LOG_STRERROR(LOG_ERROR, "getloadavg");
- }
- currentLoad = -1;
- } else {
- /* success with getloadavg */
- currentLoad = (int) (100 * loadavg);
- MUTEX_UNLOCK(&statusMutex);
- return;
- }
- }
-#endif
-
-#if MINGW
- /* Win NT? */
- if (GNNtQuerySystemInformation) {
- static double dLastKernel;
- static double dLastIdle;
- static double dLastUser;
- double dKernel;
- double dIdle;
- double dUser;
- double dDiffKernel;
- double dDiffIdle;
- double dDiffUser;
- SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION theInfo;
-
- if (GNNtQuerySystemInformation(SystemProcessorPerformanceInformation,
- &theInfo,
- sizeof(theInfo),
- NULL) == NO_ERROR) {
- /* PORT-ME MINGW: Multi-processor? */
- dKernel = Li2Double(theInfo.KernelTime);
- dIdle = Li2Double(theInfo.IdleTime);
- dUser = Li2Double(theInfo.UserTime);
- dDiffKernel = dKernel - dLastKernel;
- dDiffIdle = dIdle - dLastIdle;
- dDiffUser = dUser - dLastUser;
-
- if ( ( (dDiffKernel + dDiffUser) > 0) &&
- (dLastIdle + dLastKernel + dLastUser > 0) )
- currentLoad = 100.0 - (dDiffIdle / (dDiffKernel + dDiffUser)) * 100.0;
- else
- currentLoad = -1; /* don't know (yet) */
-
- dLastKernel = dKernel;
- dLastIdle = dIdle;
- dLastUser = dUser;
-
- MUTEX_UNLOCK(&statusMutex);
- return;
- } else {
- /* only warn once, if there is a problem with
- NtQuery..., we're going to hit it frequently... */
- static int once;
- if (once == 0) {
- once = 1;
- LOG(LOG_ERROR,
- _("Cannot query the CPU usage (Windows NT).\n"));
- }
- }
- } else { /* Win 9x */
- HKEY hKey;
- DWORD dwDataSize, dwType, dwDummy;
-
- /* Start query */
- if (RegOpenKeyEx(HKEY_DYN_DATA,
- "PerfStats\\StartSrv",
- 0,
- KEY_ALL_ACCESS,
- &hKey) != ERROR_SUCCESS) {
- /* only warn once */
- static int once = 0;
- if (once == 0) {
- once = 1;
- LOG(LOG_ERROR,
- _("Cannot query the CPU usage (Win 9x)\n"));
- }
- }
-
- RegOpenKeyEx(HKEY_DYN_DATA,
- "PerfStats\\StartStat",
- 0,
- KEY_ALL_ACCESS,
- &hKey);
- dwDataSize = sizeof(dwDummy);
- RegQueryValueEx(hKey,
- "KERNEL\\CPUUsage",
- NULL,
- &dwType,
- (LPBYTE) &dwDummy,
- &dwDataSize);
- RegCloseKey(hKey);
-
- /* Get CPU usage */
- RegOpenKeyEx(HKEY_DYN_DATA,
- "PerfStats\\StatData",
- 0,
- KEY_ALL_ACCESS,
- &hKey);
- dwDataSize = sizeof(currentLoad);
- RegQueryValueEx(hKey,
- "KERNEL\\CPUUsage",
- NULL,
- &dwType,
- (LPBYTE) ¤tLoad,
- &dwDataSize);
- RegCloseKey(hKey);
-
- /* Stop query */
- RegOpenKeyEx(HKEY_DYN_DATA,
- "PerfStats\\StopStat",
- 0,
- KEY_ALL_ACCESS,
- &hKey);
- RegOpenKeyEx(HKEY_DYN_DATA,
- "PerfStats\\StopSrv",
- 0,
- KEY_ALL_ACCESS,
- &hKey);
- dwDataSize = sizeof(dwDummy);
- RegQueryValueEx(hKey,
- "KERNEL\\CPUUsage",
- NULL,
- &dwType,
- (LPBYTE)&dwDummy,
- &dwDataSize);
- RegCloseKey(hKey);
-
- MUTEX_UNLOCK(&statusMutex);
- return;
- }
-#endif
-
- /* loadaverage not defined and no platform
- specific alternative defined
- => default: error
- */
- currentLoad = -1;
- MUTEX_UNLOCK(&statusMutex);
-}
-
-static void cronLoadUpdate(void * unused) {
- updateCpuUsage();
- if (! useBasicMethod)
- updateInterfaceTraffic();
-}
-
-/**
- * Re-read the configuration for statuscalls.
- */
-static void resetStatusCalls() {
- char * interfaces;
- int i;
- int numInterfaces;
-
- MUTEX_LOCK(&statusMutex);
- for (i=0;i<ifcsSize;i++)
- FREE(ifcs[i].name);
- GROW(ifcs,
- ifcsSize,
- 0);
- interfaces
- = getConfigurationString("LOAD",
- "INTERFACES");
- /* fail if config-file is incomplete */
- if ( (interfaces == NULL) ||
- (strlen(interfaces) == 0) ) {
- LOG(LOG_ERROR,
- _("No network interfaces defined in configuration section `%s' under
`%s'!\n"),
- "LOAD",
- "INTERFACES");
- } else {
- /* The string containing the interfaces is formatted in the following way:
- * each comma is replaced by '\0' and the pointers to the beginning of
every
- * interface are stored
- */
- numInterfaces = 1;
- for (i=strlen(interfaces)-1;i>=0;i--)
- if (interfaces[i] == ',')
- numInterfaces++;
- GROW(ifcs,
- ifcsSize,
- numInterfaces);
- for (i=strlen(interfaces)-1;i>=0;i--) {
- if (interfaces[i] == ',') {
- ifcs[--numInterfaces].name = STRDUP(&interfaces[i+1]);
- numInterfaces++;
- interfaces[i] = '\0';
- }
- }
- ifcs[--numInterfaces].name = STRDUP(interfaces);
- GNUNET_ASSERT(numInterfaces == 0);
- for (i=0;i<ifcsSize;i++) {
- ifcs[i].last_in = 0;
- ifcs[i].last_out = 0;
- }
- }
- FREENONNULL(interfaces);
- useBasicMethod
- = testConfigurationString("LOAD",
- "BASICLIMITING",
- "YES");
- maxNetDownBPS
- = getConfigurationInt("LOAD",
- "MAXNETDOWNBPSTOTAL");
- if (maxNetDownBPS == 0)
- maxNetDownBPS = 50000;
- maxNetUpBPS
- = getConfigurationInt("LOAD",
- "MAXNETUPBPSTOTAL");
- if (maxNetUpBPS == 0)
- maxNetUpBPS = 50000;
- maxCPULoad
- = getConfigurationInt("LOAD",
- "MAXCPULOAD");
- if (maxCPULoad == 0)
- maxCPULoad = 100;
- MUTEX_UNLOCK(&statusMutex);
-}
-
-
-
-/**
- * Get the load of the network relative to what is allowed.
- * @return the network load as a percentage of allowed
- * (100 is equivalent to full load)
- */
-int getNetworkLoadUp() {
- static unsigned long long overload;
- static unsigned long long lastSum;
- static cron_t lastCall;
- static int lastValue;
- cron_t now;
- unsigned long long maxExpect;
- unsigned long long currentLoadSum;
- int i;
- int ret;
-
- MUTEX_LOCK(&statusMutex);
- currentLoadSum = globalTrafficBetweenProc.last_out;
- for (i=0;i<ifcsSize;i++)
- currentLoadSum += ifcs[i].last_out;
- cronTime(&now);
- if ( (lastSum > currentLoadSum) ||
- (lastSum == 0) ||
- (now < lastCall) ) {
- /* integer overflow or first datapoint; since we cannot tell where
- / by how much the overflow happened, all we can do is ignore
- this datapoint. So we return -1 -- AND reset lastSum / lastCall. */
- lastSum = currentLoadSum;
- lastCall = now;
- MUTEX_UNLOCK(&statusMutex);
- return -1;
- }
- if (maxNetUpBPS == 0) {
- MUTEX_UNLOCK(&statusMutex);
- return -1;
- }
- if (now - lastCall < cronSECONDS) {
- /* increase last load proportional to difference in
- data transmitted and in relation to the limit */
- ret = lastValue + 100 * (currentLoadSum - lastSum) / maxNetUpBPS;
- MUTEX_UNLOCK(&statusMutex);
- return ret;
- }
- currentLoadSum -= lastSum;
- lastSum += currentLoadSum;
- currentLoadSum += overload;
- maxExpect = ( (now - lastCall) * maxNetUpBPS ) / cronSECONDS;
- lastCall = now;
- if (currentLoadSum < maxExpect)
- overload = 0;
- else
- overload = currentLoadSum - maxExpect;
- lastValue = currentLoadSum * 100 / maxExpect;
- ret = lastValue;
- MUTEX_UNLOCK(&statusMutex);
- return ret;
-}
-
-/**
- * Get the load of the network relative to what is allowed.
- * @return the network load as a percentage of allowed
- * (100 is equivalent to full load)
- */
-int getNetworkLoadDown() {
- static unsigned long long overload;
- static unsigned long long lastSum;
- static cron_t lastCall;
- static int lastValue;
- cron_t now;
- unsigned long long maxExpect;
- unsigned long long currentLoadSum;
- int i;
- int ret;
-
- MUTEX_LOCK(&statusMutex);
- currentLoadSum = globalTrafficBetweenProc.last_in;
- for (i=0;i<ifcsSize;i++)
- currentLoadSum += ifcs[i].last_in;
- cronTime(&now);
- if ( (lastSum > currentLoadSum) ||
- (lastSum == 0) ||
- (now < lastCall) ) {
- /* integer overflow or first datapoint; since we cannot tell where
- / by how much the overflow happened, all we can do is ignore
- this datapoint. So we return -1 -- AND reset lastSum / lastCall. */
- lastSum = currentLoadSum;
- lastCall = now;
- MUTEX_UNLOCK(&statusMutex);
- return -1;
- }
- if (maxNetDownBPS == 0) {
- MUTEX_UNLOCK(&statusMutex);
- return -1;
- }
- if (now - lastCall < cronSECONDS) {
- /* increase last load proportional to difference in
- data transmitted and in relation to the limit */
- ret = lastValue + 100 * (currentLoadSum - lastSum) / maxNetDownBPS;
- MUTEX_UNLOCK(&statusMutex);
- return ret;
- }
- currentLoadSum -= lastSum;
- lastSum += currentLoadSum;
- currentLoadSum += overload;
- maxExpect = ( (now - lastCall) * maxNetDownBPS ) / cronSECONDS;
- lastCall = now;
- if (currentLoadSum < maxExpect)
- overload = 0;
- else
- overload = currentLoadSum - maxExpect;
- lastValue = currentLoadSum * 100 / maxExpect;
- ret = lastValue;
- MUTEX_UNLOCK(&statusMutex);
- return ret;
-}
-
-/**
- * Get the load of the CPU relative to what is allowed.
- * @return the CPU load as a percentage of allowed
- * (100 is equivalent to full load)
- */
-int getCPULoad() {
- static int lastRet = -1;
- static cron_t lastCall;
- int ret;
- cron_t now;
-
- if (initialized_ == NO) {
- lastRet = -1;
- return -1;
- }
- MUTEX_LOCK(&statusMutex);
- ret = (100 * currentLoad) / maxCPULoad;
-
- cronTime(&now);
- if ( (lastRet != -1) &&
- (now - lastCall < 250 * cronMILLIS) ) {
- /* use smoothing, but do NOT update lastRet at frequencies higher
- than 250ms; this makes the smoothing (mostly) independent from
- the frequency at which getCPULoad is called. */
- ret = (ret + 7 * lastRet)/8;
- MUTEX_UNLOCK(&statusMutex);
- return ret;
- }
-
- /* for CPU, we don't do the 'fast increase' since CPU is much
- more jitterish to begin with */
- if (lastRet != -1)
- ret = (ret + 7 * lastRet)/8;
- lastRet = ret;
- lastCall = now;
- MUTEX_UNLOCK(&statusMutex);
- return ret;
-}
-
-/**
- * The following method is called in order to initialize the status calls
- * routines. After that it is safe to call each of the status calls separately
- * @return OK on success and SYSERR on error (or calls errexit).
- */
-void initStatusCalls() {
-#ifdef LINUX
- proc_stat = fopen("/proc/stat", "r");
- if (NULL == proc_stat)
- LOG_FILE_STRERROR(LOG_ERROR,
- "fopen",
- "/proc/stat");
- proc_net_dev = fopen(PROC_NET_DEV, "r");
- if (NULL == proc_net_dev)
- LOG_FILE_STRERROR(LOG_ERROR,
- "fopen",
- PROC_NET_DEV);
-#endif
- MUTEX_CREATE_RECURSIVE(&statusMutex);
- initialized_ = YES;
- resetBetweenProc();
- registerConfigurationUpdateCallback(&resetStatusCalls);
- resetStatusCalls();
- cronLoadUpdate(NULL);
- addCronJob(&cronLoadUpdate,
- 10 * cronSECONDS,
- 10 * cronSECONDS,
- NULL);
- getNetworkLoadUp();
- getNetworkLoadDown();
-}
-
-/**
- * Shutdown the status calls module.
- */
-void doneStatusCalls() {
- int i;
-
- if (initialized_ == NO)
- return;
- unregisterConfigurationUpdateCallback(&resetStatusCalls);
- delCronJob(&cronLoadUpdate,
- 10 * cronSECONDS,
- NULL);
- initialized_ = NO;
-#ifdef LINUX
- if (proc_stat != NULL) {
- fclose(proc_stat);
- proc_stat = NULL;
- }
- if (proc_net_dev != NULL) {
- fclose(proc_net_dev);
- proc_net_dev = NULL;
- }
-#endif
- for (i=0;i<ifcsSize;i++)
- FREE(ifcs[i].name);
- GROW(ifcs,
- ifcsSize,
- 0);
- MUTEX_DESTROY(&statusMutex);
-}
-
-
-/* end of statuscalls.c */
Deleted: GNUnet/src/util/statuscallstest.c
===================================================================
--- GNUnet/src/util/statuscallstest.c 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/statuscallstest.c 2006-06-22 17:50:56 UTC (rev 3024)
@@ -1,76 +0,0 @@
-/**
- * @file util/statuscallstest.c
- * @brief testcase for util/statuscalls.c
- */
-
-#include "gnunet_util.h"
-#include "platform.h"
-
-/**
- * Perform option parsing from the command line.
- */
-static int parseCommandLine(int argc,
- char * argv[]) {
- char c;
-
- FREENONNULL(setConfigurationString("GNUNETD",
- "_MAGIC_",
- "YES"));
- FREENONNULL(setConfigurationString("GNUNETD",
- "GNUNETD_HOME",
- "/tmp/gnunet_test/"));
- FREENONNULL(setConfigurationString("FILES",
- "gnunet.conf",
- "check.conf"));
- while (1) {
- int option_index = 0;
- static struct GNoption long_options[] = {
- { "config", 1, 0, 'c' },
- { 0,0,0,0 }
- };
-
- c = GNgetopt_long(argc,
- argv,
- "c:",
- long_options,
- &option_index);
-
- if (c == -1)
- break; /* No more flags to process*/
-
- switch(c) {
- case 'c':
- FREENONNULL(setConfigurationString("FILES",
- "gnunet.conf",
- GNoptarg));
- break;
- } /* end of parsing commandline */
- }
- return OK;
-}
-
-int main(int argc, char * argv[]){
- int ret;
- cron_t start;
-
- if (OK != initUtil(argc, argv, &parseCommandLine))
- errexit("Error during initialization!\n");
- startCron();
- /* need to run each phase for more than 10s since
- statuscalls only refreshes that often... */
- cronTime(&start);
- while (start + 12 * cronSECONDS > cronTime(NULL))
- sleep(1);
- cronTime(&start);
- ret = getCPULoad();
- while (start + 12 * cronSECONDS > cronTime(NULL))
- sqrt(245.2523); /* do some processing to drive load up */
- if (ret > getCPULoad())
- printf("busy loop decreased CPU load: %d < %d.\n",
- ret,
- getCPULoad());
- stopCron();
- doneUtil();
-
- return 0;
-}
Deleted: GNUnet/src/util/storage.c
===================================================================
--- GNUnet/src/util/storage.c 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/storage.c 2006-06-22 17:50:56 UTC (rev 3024)
@@ -1,717 +0,0 @@
-/*
- This file is part of GNUnet.
- (C) 2001, 2002, 2005 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/storage.c
- * @brief IO convenience methods
- * @author Christian Grothoff
- */
-
-#include "platform.h"
-#include "gnunet_util.h"
-
-#if LINUX || CYGWIN
-#include <sys/vfs.h>
-#else
-#ifdef SOMEBSD
-#include <sys/param.h>
-#include <sys/mount.h>
-#else
-#ifdef OSX
-#include <sys/param.h>
-#include <sys/mount.h>
-#else
-#ifdef SOLARIS
-#include <sys/types.h>
-#include <sys/statvfs.h>
-#else
-#ifdef MINGW
-#define _IFMT 0170000 /* type of file */
-#define _IFLNK 0120000 /* symbolic link */
-#define S_ISLNK(m) (((m)&_IFMT) == _IFLNK)
-#else
-#error PORT-ME: need to port statfs (how much space is left on the drive?)
-#endif
-#endif
-#endif
-#endif
-#endif
-
-#ifndef SOMEBSD
- #ifndef WINDOWS
- #ifndef OSX
- #include <wordexp.h>
- #endif
- #endif
-#endif
-
-
-static int getSizeRec(const char * filename,
- const char * dirname,
- void * ptr) {
- unsigned long long * size = ptr;
-#ifdef HAVE_STAT64
- struct stat64 buf;
-#else
- struct stat buf;
-#endif
- char * fn;
-
- if (filename == NULL)
- return SYSERR;
- if ( (dirname != NULL) &&
- (strlen(dirname) > 0) ) {
- fn = MALLOC(strlen(filename) + strlen(dirname) + 3);
- if (strlen(dirname) > 0) {
- strcpy(fn, dirname);
- if (dirname[strlen(dirname)-1] != DIR_SEPARATOR)
- strcat(fn, DIR_SEPARATOR_STR); /* add tailing / if needed */
- }
- /* Windows paths don't start with / */
-#ifndef MINGW
- else
- strcpy(fn, DIR_SEPARATOR_STR);
-#endif
- if (filename[0] == DIR_SEPARATOR)
- /* if filename starts with a "/", don't copy it */
- strcat(fn, &filename[1]);
- else
- strcat(fn, filename);
- } else
- fn = STRDUP(filename);
-
-#ifdef HAVE_STAT64
- if (0 != STAT64(fn, &buf)) {
-#else
- if (0 != STAT(fn, &buf)) {
-#endif
- LOG_FILE_STRERROR(LOG_EVERYTHING,
- "stat",
- fn);
- FREE(fn);
- return SYSERR;
- }
- *size += buf.st_size;
- if ( (S_ISDIR(buf.st_mode)) &&
- (!S_ISLNK(buf.st_mode)) ) {
- if (SYSERR ==
- scanDirectory(fn,
- &getSizeRec,
- size)) {
- FREE(fn);
- return SYSERR;
- }
- }
- FREE(fn);
- return OK;
-}
-
-static int getSizeWithoutSymlinksRec(const char * filename,
- const char * dirname,
- void * ptr) {
- unsigned long long * size = ptr;
-#ifdef HAVE_STAT64
- struct stat64 buf;
-#else
- struct stat buf;
-#endif
- char * fn;
-
- if (filename == NULL)
- return SYSERR;
- if (dirname != NULL) {
- fn = MALLOC(strlen(filename) + strlen(dirname) + 2);
- fn[0] = '\0';
- if (strlen(dirname) > 0) {
- strcat(fn, dirname);
- if (dirname[strlen(dirname)-1] != DIR_SEPARATOR)
- strcat(fn, "/"); /* add tailing / if needed */
- }
- /* Windows paths don't start with / */
-#ifndef MINGW
- else
- strcat(fn, "/");
-#endif
- if (filename[0] == DIR_SEPARATOR) /* if filename starts with a "/", don't
copy it */
- strcat(fn, &filename[1]);
- else
- strcat(fn, filename);
- } else
- fn = STRDUP(filename);
-
-#ifdef HAVE_STAT64
- if (0 != STAT64(fn, &buf)) {
-#else
- if (0 != STAT(fn, &buf)) {
-#endif
- LOG_FILE_STRERROR(LOG_EVERYTHING,
- "stat",
- fn);
- FREE(fn);
- return SYSERR;
- }
- if (! S_ISLNK(buf.st_mode))
- *size += buf.st_size;
- if ( (S_ISDIR(buf.st_mode)) &&
- (!S_ISLNK(buf.st_mode)) ) {
- if (SYSERR ==
- scanDirectory(fn,
- &getSizeWithoutSymlinksRec,
- size)) {
- FREE(fn);
- return SYSERR;
- }
- }
- FREE(fn);
- return OK;
-}
-
-/**
- * Get the number of blocks that are left on the partition that
- * contains the given file (for normal users).
- *
- * @param part a file on the partition to check
- * @return -1 on errors, otherwise the number of free blocks
- */
-long getBlocksLeftOnDrive(const char * part) {
-#ifdef SOLARIS
- struct statvfs buf;
-
- if (0 == statvfs(part, &buf)) {
- return buf.f_bavail;
- } else {
- LOG_STRERROR(LOG_ERROR, "statfs");
- return -1;
- }
-#elif MINGW
- DWORD dwDummy, dwBlocks;
- char szDrive[4];
-
- memcpy(szDrive, part, 3);
- szDrive[3] = 0;
- if(!GetDiskFreeSpace(szDrive, &dwDummy, &dwDummy, &dwBlocks, &dwDummy))
- {
- LOG(LOG_ERROR,
- _("`%s' failed for drive %s: %u\n"),
- "GetDiskFreeSpace",
- szDrive, GetLastError());
-
- return -1;
- }
- else
- {
- return dwBlocks;
- }
-#else
- struct statfs s;
- if (0 == statfs(part, &s)) {
- return s.f_bavail;
- } else {
- LOG_STRERROR(LOG_ERROR, "statfs");
- return -1;
- }
-#endif
-}
-
-/**
- * Get the size of the file (or directory)
- * of the given file (in bytes).
- *
- * @return SYSERR on error, OK on success
- */
-int getFileSize(const char * filename,
- unsigned long long * size) {
- GNUNET_ASSERT(size != NULL);
- *size = 0;
- return getSizeRec(filename, "", size);
-}
-
-/**
- * Get the size of the file (or directory) without
- * counting symlinks.
- *
- * @return SYSERR on error, OK on success
- */
-int getFileSizeWithoutSymlinks(const char * filename,
- unsigned long long * size) {
- GNUNET_ASSERT(size != NULL);
- *size = 0;
-
- return getSizeWithoutSymlinksRec(filename, "", size);
-}
-
-
-/**
- * Convert string to value ('755' for chmod-call)
- */
-static int atoo(const char *s) {
- int n = 0;
-
- while ( ('0' <= *s) && (*s < '8') ) {
- n <<= 3;
- n += *s++ - '0';
- }
- return n;
-}
-
-/**
- * Test if fil is a directory.
- * @returns YES if yes, NO if not
- */
-int isDirectory(const char * fil) {
- struct stat filestat;
- int ret;
-
- ret = STAT(fil, &filestat);
- if (ret != 0) {
- LOG_FILE_STRERROR(LOG_EVERYTHING, "stat", fil);
- return NO;
- }
- if (S_ISDIR(filestat.st_mode))
- return YES;
- else
- return NO;
-}
-
-/**
- * Assert that fil corresponds to a filename
- * (of a file that exists and that is not a directory).
- * @returns 1 if yes, 0 if not (will print an error
- * message in that case, too).
- */
-int assertIsFile(const char * fil) {
- struct stat filestat;
- int ret;
-
- ret = STAT(fil, &filestat);
- if (ret != 0) {
- LOG_FILE_STRERROR(LOG_EVERYTHING, "stat", fil);
- return 0;
- }
- if (!S_ISREG(filestat.st_mode)) {
- LOG(LOG_WARNING,
- _("`%s' is not a regular file.\n"),
- fil);
- return 0;
- }
- if (ACCESS(fil, R_OK) < 0 ) {
- LOG_FILE_STRERROR(LOG_WARNING, "access", fil);
- return 0;
- }
- return 1;
-}
-
-/**
- * Complete filename (a la shell) from abbrevition.
- * @param fil the name of the file, may contain ~/ or
- * be relative to the current directory
- * @returns the full file name,
- * NULL is returned on error
- */
-char * expandFileName(const char * fil) {
- char buffer[512];
- char * fn;
-#ifndef MINGW
- size_t n;
- char * fm;
- const char *fil_ptr;
-#else
- long lRet;
-#endif
-
- if (fil == NULL)
- return NULL;
-
-#ifndef MINGW
- if (fil[0] == DIR_SEPARATOR) {
- /* absolute path, just copy */
- return(STRDUP(fil));
- }
- else if (fil[0] == '~') {
- fm = getenv("HOME");
- if (fm == NULL) {
- /* keep it symbolic to show error to user! */
- fm = "$HOME";
- }
-
- /* do not copy '~' */
- fil_ptr = fil + 1;
-
- /* skip over dir seperator to be consistent */
- if (fil_ptr[0] == DIR_SEPARATOR) {
- fil_ptr++;
- }
- } else {
- fil_ptr = fil;
- if (getcwd(buffer, 512) != NULL)
- fm = buffer;
- else
- fm = "$PWD";
- }
-
- n = strlen(fm) + 1 + strlen(fil_ptr) + 1;
- fn = MALLOC(n);
-
- SNPRINTF(fn, n,
- "%s/%s", fm, fil_ptr);
-#else
- fn = MALLOC(MAX_PATH + 1);
-
- if ((lRet = plibc_conv_to_win_path(fil, buffer)) != ERROR_SUCCESS)
- {
- SetErrnoFromWinError(lRet);
-
- return NULL;
- }
- /* is the path relative? */
- if ((strncmp(buffer + 1, ":\\", 2) != 0) &&
- (strncmp(buffer, "\\\\", 2) != 0))
- {
- char szCurDir[MAX_PATH + 1];
- lRet = GetCurrentDirectory(MAX_PATH + 1, szCurDir);
- if (lRet + strlen(fn) + 1 > (MAX_PATH + 1))
- {
- SetErrnoFromWinError(ERROR_BUFFER_OVERFLOW);
-
- return NULL;
- }
- SNPRINTF(fn,
- MAX_PATH+1,
- "%s\\%s", szCurDir, buffer);
- }
- else
- {
- strcpy(fn, buffer);
- }
-#endif
- return fn;
-}
-
-/**
- * Implementation of "mkdir -p"
- * @param dir the directory to create
- * @returns OK on success, SYSERR on failure
- */
-int mkdirp(const char * dir) {
- char * rdir;
- int len;
- int pos;
- int ret = OK;
-
- rdir = expandFileName(dir); /* expand directory */
- len = strlen(rdir);
-#ifndef MINGW
- pos = 1; /* skip heading '/' */
-#else
-
- /* Local or Network path? */
- if (strncmp(rdir, "\\\\", 2) == 0)
- {
- pos = 2;
- while (rdir[pos])
- {
- if (rdir[pos] == '\\')
- {
- pos ++;
-
- break;
- }
- pos ++;
- }
- }
- else
- {
- pos = 3; /* strlen("C:\\") */
- }
-#endif
- while (pos <= len) {
- if ( (rdir[pos] == DIR_SEPARATOR) ||
- (pos == len) ) {
- rdir[pos] = '\0';
- if (! isDirectory(rdir))
-#ifndef MINGW
- if (0 != mkdir(rdir,
- S_IRUSR | S_IWUSR |
- S_IXUSR | S_IRGRP |
- S_IXGRP | S_IROTH |
- S_IXOTH)) { /* 755 */
-#else
- if (0 != mkdir(rdir)) {
-#endif
- if (errno != EEXIST) {
- LOG_FILE_STRERROR(LOG_ERROR, "mkdir", rdir);
- ret = SYSERR;
- }
- }
- rdir[pos] = DIR_SEPARATOR;
- }
- pos++;
- }
- FREE(rdir);
- return ret;
-}
-
-/**
- * Read the contents of a binary file into a buffer.
- * @param fileName the name of the file, not freed,
- * must already be expanded!
- * @param len the maximum number of bytes to read
- * @param result the buffer to write the result to
- * @return the number of bytes read on success, -1 on failure
- */
-int readFile(const char * fileName,
- int len,
- void * result) {
- /* open file, must exist, open read only */
- int handle;
- int size;
-
- if ((fileName == NULL) || (result == NULL))
- return -1;
- handle = fileopen(fileName,O_RDONLY,S_IRUSR);
- if (handle < 0)
- return -1;
- size = READ(handle, result, len);
- closefile(handle);
- return size;
-}
-
-/**
- * Write a buffer to a file.
- * @param fileName the name of the file, NOT freed!
- * @param buffer the data to write
- * @param n number of bytes to write
- * @param mode permissions to set on the file
- * @return OK on success, SYSERR on error
- */
-int writeFile(const char * fileName,
- const void * buffer,
- unsigned int n,
- const char *mode) {
- int handle;
- /* open file, open with 600, create if not
- present, otherwise overwrite */
- if ( (fileName == NULL) ||
- (buffer == NULL) )
- return SYSERR;
- handle = fileopen(fileName,
- O_CREAT | O_WRONLY,
- S_IRUSR | S_IWUSR);
- if (handle == -1) {
- LOG_FILE_STRERROR(LOG_WARNING,
- "open",
- fileName);
- return SYSERR;
- }
- /* write the buffer take length from the beginning */
- if (n != WRITE(handle, buffer, n)) {
- LOG_FILE_STRERROR(LOG_WARNING,
- "write",
- fileName);
- closefile(handle);
- return SYSERR;
- }
- CHMOD(fileName,
- atoo(mode));
- closefile(handle);
- return OK;
-}
-
-/**
- * Scan a directory for files. The name of the directory
- * must be expanded first (!).
- * @param dirName the name of the directory
- * @param callback the method to call for each file,
- * can be NULL, in that case, we only count
- * @param data argument to pass to callback
- * @return the number of files found, SYSERR on error
- */
-int scanDirectory(const char * dirName,
- DirectoryEntryCallback callback,
- void * data) {
- DIR * dinfo;
- struct dirent *finfo;
- struct stat istat;
- int count = 0;
-
- if (dirName == NULL)
- return SYSERR;
- if (0 != STAT(dirName, &istat)) {
- LOG_FILE_STRERROR(LOG_WARNING,
- "stat",
- dirName);
- return SYSERR;
- }
- if (!S_ISDIR(istat.st_mode)) {
- LOG(LOG_ERROR,
- _("`%s' expected `%s' to be a directory!\n"),
- __FUNCTION__,
- dirName);
- return SYSERR;
- }
- errno = 0;
- dinfo = OPENDIR(dirName);
- if ((errno == EACCES) || (dinfo == NULL)) {
- LOG_FILE_STRERROR(LOG_WARNING,
- "opendir",
- dirName);
- return SYSERR;
- }
- while ((finfo = readdir(dinfo)) != NULL) {
- if (finfo->d_name[0] == '.')
- continue;
- if (callback != NULL) {
- if (OK != callback(finfo->d_name,
- dirName,
- data)) {
- closedir(dinfo);
- return SYSERR;
- }
- }
- count++;
- }
- closedir(dinfo);
- return count;
-}
-
-/**
- * Callback for rm_minus_rf.
- */
-static int rmHelper(const char * fil,
- const char * dir,
- void * unused) {
- char * fn;
- size_t n;
-
- n = strlen(dir) + strlen(fil) + 2;
- fn = MALLOC(n);
- SNPRINTF(fn,
- n,
- "%s/%s",
- dir,
- fil);
- if (SYSERR == rm_minus_rf(fn)) {
- FREE(fn);
- return SYSERR;
- }
- FREE(fn);
- return OK;
-}
-
-/**
- * Remove all files in a directory (rm -rf). Call with
- * caution.
- *
- *
- * @param fileName the file to remove
- * @return OK on success, SYSERR on error
- */
-int rm_minus_rf(const char * fileName) {
- if (UNLINK(fileName) == 0)
- return 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" */
- (YES == isDirectory(fileName)) ) {
- if (OK == scanDirectory(fileName,
- &rmHelper,
- NULL)) {
- if (0 != RMDIR(fileName)) {
- LOG_FILE_STRERROR(LOG_WARNING,
- "rmdir",
- fileName);
- return SYSERR;
- }
- return OK;
- }
- return SYSERR;
- } else {
- LOG_FILE_STRERROR(LOG_WARNING,
- "unlink",
- fileName);
- return SYSERR;
- }
-}
-
-void close_(int fd,
- const char * filename,
- int linenumber) {
- if (0 != CLOSE(fd)) {
- LOG(LOG_INFO,
- _("`%s' failed at %s:%d with error: %s\n"),
- "close",
- filename,
- linenumber, STRERROR(errno));
- }
-}
-
-#define COPY_BLK_SIZE 65536
-
-/**
- * Copy a file.
- * @return OK on success, SYSERR on error
- */
-int copyFile(const char * src,
- const char * dst) {
- char * buf;
- unsigned long long pos;
- unsigned long long size;
- unsigned long long len;
- int in;
- int out;
-
- buf = MALLOC(COPY_BLK_SIZE);
- pos = 0;
- in = fileopen(src, O_RDONLY | O_LARGEFILE);
- if (in == -1)
- return SYSERR;
- out = fileopen(dst,
- O_LARGEFILE | O_WRONLY | O_CREAT | O_EXCL,
- S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
- if (out == -1) {
- closefile(in);
- return SYSERR;
- }
- if (OK != getFileSize(src,
- &size)) {
- closefile(in);
- return SYSERR;
- }
- while (pos < size) {
- len = COPY_BLK_SIZE;
- if (len > size - pos)
- len = size - pos;
- if (len != READ(in, buf, len))
- goto FAIL;
- if (len != WRITE(out, buf, len))
- goto FAIL;
- pos += len;
- }
- closefile(in);
- closefile(out);
- return OK;
- FAIL:
- closefile(in);
- closefile(out);
- return SYSERR;
-}
-
-/* end of storage.c */
Deleted: GNUnet/src/util/storagetest.c
===================================================================
--- GNUnet/src/util/storagetest.c 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/storagetest.c 2006-06-22 17:50:56 UTC (rev 3024)
@@ -1,54 +0,0 @@
-/**
- * @file test/storagetest.c
- * @brief testcase for the storage module
- * @author Christian Grothoff
- */
-
-#include "gnunet_util.h"
-#include "platform.h"
-
-#define TESTSTRING "Hello World\0"
-
-/**
- * Perform option parsing from the command line.
- */
-static int parseCommandLine(int argc,
- char * argv[]) {
- return OK;
-}
-
-static int testReadWrite() {
- HashCode512 ha;
- EncName filename;
- char tmp[100];
-
- hash(TESTSTRING,
- strlen(TESTSTRING),
- &ha);
- hash2enc(&ha, &filename);
- writeFile((char*)&filename, TESTSTRING, strlen(TESTSTRING), "644");
- tmp[readFile((char*)&filename, 100, tmp)] = '\0';
- if (memcmp(tmp,TESTSTRING,strlen(TESTSTRING)+1) == 0)
- return 0;
- else {
- fprintf(stderr,
- "Error in testReadWrite: *%s* != *%s* for file %s\n",
- tmp,TESTSTRING,(char*)&filename);
- return 1;
- }
-}
-
-int main(int argc, char * argv[]) {
- int failureCount = 0;
-
- initUtil(argc, argv, &parseCommandLine);
- failureCount += testReadWrite();
- doneUtil();
- if (failureCount == 0)
- return 0;
- else {
- fprintf(stderr,
- "\n\n%d TESTS FAILED!\n\n",failureCount);
- return -1;
- }
-} /* end of main */
Modified: GNUnet/src/util/string/string.c
===================================================================
--- GNUnet/src/util/string/string.c 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/string/string.c 2006-06-22 17:50:56 UTC (rev 3024)
@@ -97,7 +97,7 @@
* Give relative time in human-readable fancy format.
* @param delta time in milli seconds
*/
-char * timeIntervalToFancyString(unsigned long long delta) {
+char * string_get_fancy_time_interval(unsigned long long delta) {
const char * unit = _(/* time unit */ "ms");
char * ret;
@@ -129,7 +129,7 @@
/**
* Convert a given filesize into a fancy human-readable format.
*/
-char * fileSizeToFancyString(unsigned long long size) {
+char * string_get_fancy_byte_size(unsigned long long size) {
const char * unit = _(/* size unit */ "b");
char * ret;
@@ -169,9 +169,10 @@
* if conversion fails, a copy of the orignal
* string is returned.
*/
-char * convertToUtf8(const char * input,
- size_t len,
- const char * charset) {
+char * string_convertToUtf8(struct GE_Context * ectx,
+ const char * input,
+ size_t len,
+ const char * charset) {
char * ret;
#if ENABLE_NLS
size_t tmpSize;
@@ -182,6 +183,9 @@
cd = iconv_open("UTF-8", charset);
if (cd == (iconv_t) -1) {
+ GE_LOG_STRERROR(ectx,
+ GE_USER | GE_ADMIN | GE_WARNING | GE_BULK,
+ "iconv_open");
ret = MALLOC(len+1);
memcpy(ret, input, len);
ret[len] = '\0';
@@ -196,6 +200,9 @@
&len,
&itmp,
&finSize) == (size_t)-1) {
+ GE_LOG_STRERROR(ectx,
+ GE_USER | GE_WARNING | GE_BULK,
+ "iconv");
iconv_close(cd);
FREE(tmp);
ret = MALLOC(len+1);
@@ -209,7 +216,10 @@
tmpSize - finSize);
ret[tmpSize - finSize] = '\0';
FREE(tmp);
- iconv_close(cd);
+ if (0 != iconv_close(cd))
+ GE_LOG_STRERROR(ectx,
+ GE_ADMIN | GE_WARNING | GE_REQUEST,
+ "iconv_close");
return ret;
#else
ret = MALLOC(len+1);
@@ -219,4 +229,110 @@
#endif
}
+
+
+
+/**
+ * Complete filename (a la shell) from abbrevition.
+ * @param fil the name of the file, may contain ~/ or
+ * be relative to the current directory
+ * @returns the full file name,
+ * NULL is returned on error
+ */
+char * string_expandFileName(struct GE_Context * ectx,
+ const char * fil) {
+ char * buffer;
+ char * fn;
+#ifndef MINGW
+ size_t len;
+ size_t n;
+ char * fm;
+ const char * fil_ptr;
+#else
+ long lRet;
+#endif
+
+ if (fil == NULL)
+ return NULL;
+
+#ifndef MINGW
+ if (fil[0] == DIR_SEPARATOR)
+ /* absolute path, just copy */
+ return(STRDUP(fil));
+ if (fil[0] == '~') {
+ fm = getenv("HOME");
+ if (fm == NULL) {
+ GE_LOG(ectx,
+ GE_USER | GE_ADMIN | GE_WARNING | GE_IMMEDIATE,
+ _("Failed to expand `$HOME': environment variable `HOME' not
set"));
+ return NULL;
+ }
+ fm = STRDUP(fm);
+ /* do not copy '~' */
+ fil_ptr = fil + 1;
+
+ /* skip over dir seperator to be consistent */
+ if (fil_ptr[0] == DIR_SEPARATOR)
+ fil_ptr++;
+ } else {
+ /* relative path */
+ fil_ptr = fil;
+ len = 512;
+ errno = ERANGE;
+ while (errno == ERANGE) {
+ buffer = MALLOC(len);
+ if (getcwd(buffer, len) != NULL) {
+ fm = buffer;
+ break;
+ } else {
+ GE_LOG_STRERROR(ectx,
+ GE_USER | GE_WARNING | GE_IMMEDIATE,
+ "getcwd");
+ FREE(buffer);
+ buffer = getenv("PWD"); /* alternative */
+ if (buffer == NULL)
+ return NULL; /* fatal */
+ fm = STRDUP(buffer);
+ }
+ }
+ }
+ n = strlen(fm) + 1 + strlen(fil_ptr) + 1;
+ buffer = MALLOC(n);
+ SNPRINTF(fn, n,
+ "%s/%s", fm, fil_ptr);
+ FREE(fm);
+#else
+ fn = MALLOC(MAX_PATH + 1);
+
+ if ((lRet = plibc_conv_to_win_path(fil, buffer)) != ERROR_SUCCESS) {
+ SetErrnoFromWinError(lRet);
+ GE_LOG_STRERROR(ectx,
+ GE_USER | GE_WARNING | GE_IMMEDIATE,
+ "plibc_conv_to_win_path");
+ return NULL;
+ }
+ /* is the path relative? */
+ if ( (strncmp(buffer + 1, ":\\", 2) != 0) &&
+ (strncmp(buffer, "\\\\", 2) != 0)) {
+ char szCurDir[MAX_PATH + 1];
+ lRet = GetCurrentDirectory(MAX_PATH + 1, szCurDir);
+ if (lRet + strlen(fn) + 1 > (MAX_PATH + 1)) {
+ SetErrnoFromWinError(ERROR_BUFFER_OVERFLOW);
+ GE_LOG_STRERROR(ectx,
+ GE_USER | GE_WARNING | GE_IMMEDIATE,
+ "GetCurrentDirectory");
+ return NULL;
+ }
+ SNPRINTF(fn,
+ MAX_PATH+1,
+ "%s\\%s", szCurDir, buffer);
+ } else {
+ strcpy(fn, buffer);
+ }
+#endif
+ return fn;
+}
+
+
+
/* end of string.c */
Deleted: GNUnet/src/util/tcp_return.c
===================================================================
--- GNUnet/src/util/tcp_return.c 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/tcp_return.c 2006-06-22 17:50:56 UTC (rev 3024)
@@ -1,94 +0,0 @@
-/*
- This file is part of GNUnet.
- (C) 2001, 2002, 2004 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/tcp_return.c
- * @brief code to communicate simple (int) return values via reliable
- * TCP stream
- * @author Christian Grothoff
- *
- * Helper methods to send and receive return values over a TCP stream
- * that has tcpio (see util/tcpio.c) semantics.
- */
-
-#include "gnunet_util.h"
-#include "gnunet_protocols.h"
-#include "platform.h"
-
-/**
- * Obtain a return value from a remote call from TCP.
- *
- * @param sock the TCP socket
- * @param ret the return value from TCP
- * @return SYSERR on error, OK if the return value was read
- * successfully
- */
-int readTCPResult(GNUNET_TCP_SOCKET * sock,
- int * ret) {
- CS_returnvalue_MESSAGE * rv;
-
- rv = NULL;
- if (SYSERR == readFromSocket(sock,
- (CS_MESSAGE_HEADER **) &rv)) {
- LOG(LOG_WARNING,
- _("`%s' failed, other side closed connection.\n"),
- __FUNCTION__);
- return SYSERR;
- }
- if ( (ntohs(rv->header.size) != sizeof(CS_returnvalue_MESSAGE)) ||
- (ntohs(rv->header.type) != CS_PROTO_RETURN_VALUE) ) {
- LOG(LOG_WARNING,
- _("`%s' failed, reply invalid!\n"),
- __FUNCTION__);
- FREE(rv);
- return SYSERR;
- }
- *ret = ntohl(rv->return_value);
- FREE(rv);
- return OK;
-}
-
-/**
- * Send a return value to the caller of a remote call via
- * TCP.
- * @param sock the TCP socket
- * @param ret the return value to send via TCP
- * @return SYSERR on error, OK if the return value was
- * send successfully
- */
-int sendTCPResult(GNUNET_TCP_SOCKET * sock,
- int ret) {
- CS_returnvalue_MESSAGE rv;
-
- rv.header.size
- = htons(sizeof(CS_returnvalue_MESSAGE));
- rv.header.type
- = htons(CS_PROTO_RETURN_VALUE);
- rv.return_value
- = htonl(ret);
- return writeToSocket(sock,
- &rv.header);
-}
-
-
-
-
-
-/* end of tcp_return.c */
Deleted: GNUnet/src/util/tcpio.c
===================================================================
--- GNUnet/src/util/tcpio.c 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/tcpio.c 2006-06-22 17:50:56 UTC (rev 3024)
@@ -1,463 +0,0 @@
-/*
- This file is part of GNUnet.
- (C) 2001, 2002 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/tcpio.c
- * @brief code for synchronized access to TCP streams
- * @author Christian Grothoff
- *
- * Generic TCP code for reliable, mostly blocking, record-oriented TCP
- * connections. GNUnet uses the "tcpio" code for trusted client-server
- * (e.g. gnunet-gtk to gnunetd via loopback) communications. Note
- * that an unblocking write is also provided since if both client and
- * server use blocking IO, both may block on a write and cause a
- * mutual inter-process deadlock.
- *
- * Since we do not want other peers (!) to be able to block a peer by
- * not reading from the TCP stream, the peer-to-peer TCP transport
- * uses unreliable, buffered, non-blocking, record-oriented TCP code
- * with a select call to reduce the number of threads which is
- * provided in transports/tcp.c.
- */
-
-#include "gnunet_util.h"
-#include "platform.h"
-
-#define DEBUG_TCPIO NO
-
-/**
- * Initialize a GNUnet client socket.
- * @param port the portnumber in host byte order
- * @param ip IP of the host to connect to, in network byte order
- * @param result the SOCKET (filled in)
- * @return OK if successful, SYSERR on failure
- */
-int initGNUnetClientSocketIP(unsigned short port,
- IPaddr ip,
- GNUNET_TCP_SOCKET * result) {
- result->ip = ip;
- result->port = port;
- result->socket = -1; /* closed */
- result->outBufLen = 0;
- result->outBufPending = NULL;
- MUTEX_CREATE(&result->readlock);
- MUTEX_CREATE(&result->writelock);
- return OK;
-}
-
-/**
- * Initialize a GNUnet client socket.
- * @param port the portnumber in host byte order
- * @param hostname the name of the host to connect to
- * @param result the SOCKET (filled in)
- * @return OK if successful, SYSERR on failure
- */
-int initGNUnetClientSocket(unsigned short port,
- const char * hostname,
- GNUNET_TCP_SOCKET * result) {
- GNUNET_ASSERT(hostname != NULL);
-#if DEBUG_TCPIO
- LOG(LOG_DEBUG,
- "Connecting to host '%s:%d'.\n",
- hostname,
- port);
-#endif
- if (OK != GN_getHostByName(hostname,
- &result->ip))
- return SYSERR;
- result->port = port;
- result->socket = -1; /* closed */
- result->outBufLen = 0;
- result->outBufPending = NULL;
- MUTEX_CREATE(&result->readlock);
- MUTEX_CREATE(&result->writelock);
- return OK;
-}
-
-/**
- * Initialize a GNUnet server socket.
- * @param sock the open socket
- * @param result the SOCKET (filled in)
- * @return OK (always successful)
- */
-int initGNUnetServerSocket(int sock,
- GNUNET_TCP_SOCKET * result) {
- result->ip.addr = 0;
- result->port = 0;
- result->socket = sock;
- result->outBufLen = 0;
- result->outBufPending = NULL;
- MUTEX_CREATE(&result->readlock);
- MUTEX_CREATE(&result->writelock);
- return OK;
-}
-
-/**
- * Check if a socket is open. Will ALWAYS return 'true'
- * for a valid client socket (even if the connection is
- * closed), but will return false for a closed server socket.
- * @return 1 if open, 0 if closed
- */
-int isOpenConnection(GNUNET_TCP_SOCKET * sock) {
- return (sock->socket != -1);
-}
-
-/**
- * Check a socket, open and connect if it is closed and it is a client-socket.
- */
-int checkSocket(GNUNET_TCP_SOCKET * sock) {
- int res;
- struct sockaddr_in soaddr;
- fd_set rset;
- fd_set wset;
- fd_set eset;
- struct timeval timeout;
- int ret;
- int wasSockBlocking;
-
- if (sock->socket != -1)
- return OK;
- sock->socket = SOCKET(PF_INET, SOCK_STREAM, 6); /* 6: TCP */
- if (sock->socket == -1) {
- LOG_STRERROR(LOG_FAILURE, "socket");
- return SYSERR;
- }
-
- wasSockBlocking = isSocketBlocking(sock->socket);
- setBlocking(sock->socket, NO);
-
- soaddr.sin_family = AF_INET;
- GNUNET_ASSERT(sizeof(struct in_addr) == sizeof(sock->ip.addr));
- memcpy(&soaddr.sin_addr,
- &sock->ip.addr,
- sizeof(struct in_addr));
- soaddr.sin_port = htons(sock->port);
- res = CONNECT(sock->socket,
- (struct sockaddr*)&soaddr,
- sizeof(soaddr));
- if ( (res < 0) &&
- (errno != EINPROGRESS) ) {
- LOG(LOG_INFO,
- _("Cannot connect to %u.%u.%u.%u:%u: %s\n"),
- PRIP(ntohl(*(int*)&sock->ip.addr)),
- sock->port,
- STRERROR(errno));
- closefile(sock->socket);
- sock->socket = -1;
- return SYSERR;
- }
-
- /* we call select() first with a timeout of 5s to
- avoid blocking on a later write indefinitely;
- this is mostly needed for gnunet-testbed to keep
- working if an advertised testbed-client is behind
- a firewall and unreachable. But it is also nice
- if a local firewall decides to just drop the TCP
- handshake...*/
- FD_ZERO(&rset);
- FD_ZERO(&wset);
- FD_ZERO(&eset);
- if (sock->socket < 0)
- return SYSERR;
- FD_SET(sock->socket, &wset);
- timeout.tv_sec = 5;
- timeout.tv_usec = 0;
- ret = SELECT(sock->socket+1, &rset, &wset, &eset, &timeout);
- if ( (ret == -1) ||
- (sock->socket == -1) ||
- (! FD_ISSET(sock->socket,
- &wset)) ) {
- LOG(LOG_INFO,
- _("Cannot connect to %u.%u.%u.%u:%u: %s\n"),
- PRIP(ntohl(*(int*)&sock->ip.addr)),
- sock->port,
- STRERROR(errno));
- setBlocking(sock->socket, wasSockBlocking);
- return SYSERR;
- }
- setBlocking(sock->socket, wasSockBlocking);
-
- return OK;
-}
-
-/**
- * Write to a GNUnet TCP socket. Will also potentially complete the
- * sending of a previous non-blocking writeToSocket call.
- *
- * @param sock the socket to write to
- * @param buffer the buffer to write
- * @return OK if the write was sucessful, otherwise SYSERR.
- */
-int writeToSocket(GNUNET_TCP_SOCKET * sock,
- const CS_MESSAGE_HEADER * buffer) {
- int res;
- int size;
-
- if (SYSERR == checkSocket(sock))
- return SYSERR;
- size = ntohs(buffer->size);
- MUTEX_LOCK(&sock->writelock);
-
- /* write pending data from prior non-blocking call
- -- but this time use blocking IO! */
- if (sock->outBufLen > 0) {
- res = SEND_BLOCKING_ALL(sock->socket,
- sock->outBufPending,
- sock->outBufLen);
- if (res < 0) {
- if (errno == EAGAIN) {
- MUTEX_UNLOCK(&sock->writelock);
- return SYSERR; /* can not send right now;
- but do NOT close socket in this case! */
- }
- LOG_STRERROR(LOG_INFO, "send");
- closeSocketTemporarily(sock);
- MUTEX_UNLOCK(&sock->writelock);
- return SYSERR;
- }
- FREE(sock->outBufPending);
- sock->outBufPending = NULL;
- sock->outBufLen = 0;
- }
-
- res = SEND_BLOCKING_ALL(sock->socket,
- buffer,
- size);
- if (res < 0) {
- if (errno == EAGAIN) {
- MUTEX_UNLOCK(&sock->writelock);
- return SYSERR; /* would block, can not send right now;
- but do NOT close socket in this case! */
- }
- LOG_STRERROR(LOG_INFO, "send");
- closeSocketTemporarily(sock);
- MUTEX_UNLOCK(&sock->writelock);
- return SYSERR;
- }
- MUTEX_UNLOCK(&sock->writelock);
- return OK;
-}
-
-
-/**
- * Write to a GNUnet TCP socket non-blocking. Note that it is
- * possible that only a part of the message is send and that tcpio
- * buffers the rest until the next writeToSocket operation. If that
- * buffer is full or if send did not transmit any byte of the message,
- * NO is returned to indicate that the write failed (would have
- * blocked).
- *
- * @param sock the socket to write to
- * @param buffer the buffer to write
- * @return OK if the write was sucessful, NO if it would have blocked and was
not performed,
- * otherwise SYSERR.
- */
-int writeToSocketNonBlocking(GNUNET_TCP_SOCKET * sock,
- const CS_MESSAGE_HEADER * buffer) {
- size_t res;
- size_t size;
-
- if (SYSERR == checkSocket(sock))
- return SYSERR;
- MUTEX_LOCK(&sock->writelock);
- if (sock->outBufLen > 0) {
- SEND_NONBLOCKING(sock->socket,
- sock->outBufPending,
- sock->outBufLen,
- &res);
- if (res == (size_t)-1) {
- if ( (errno == EWOULDBLOCK) ||
- (errno == EAGAIN) ) {
- MUTEX_UNLOCK(&sock->writelock);
- return NO;
- }
- LOG_STRERROR(LOG_INFO, "write");
- closeSocketTemporarily(sock);
- MUTEX_UNLOCK(&sock->writelock);
- return SYSERR;
- }
- if (res < sock->outBufLen) {
- memcpy(sock->outBufPending,
- &((char*)sock->outBufPending)[res],
- sock->outBufLen - res);
- sock->outBufLen -= res;
- MUTEX_UNLOCK(&sock->writelock);
- return SYSERR;
- }
- /* completely send out deferred buffer, so
- we can in fact continue! */
- FREENONNULL(sock->outBufPending);
- sock->outBufPending = NULL;
- sock->outBufLen = 0;
- }
-
- size = ntohs(buffer->size);
-
- SEND_NONBLOCKING(sock->socket,
- (const char*)buffer,
- size,
- &res);
- if (res == (size_t) -1) {
- if ( (errno == EWOULDBLOCK) ||
- (errno == EAGAIN) ) {
- MUTEX_UNLOCK(&sock->writelock);
- return NO; /* would block, can not send right now;
- but do NOT close socket in this case;
- do not use SYSERR as return value
- since this is not an error! */
- }
- LOG_STRERROR(LOG_INFO, "send");
- closeSocketTemporarily(sock);
- MUTEX_UNLOCK(&sock->writelock);
- return SYSERR;
- }
- GNUNET_ASSERT(res <= size);
- if (res != size) {
- sock->outBufPending = MALLOC(size - res);
- memcpy(sock->outBufPending,
- &((const char*)buffer)[res],
- size - res);
- sock->outBufLen = size - res;
- MUTEX_UNLOCK(&sock->writelock);
- return OK; /* return OK here means that the message will be transmitted,
- though it may be a bit later (on the next call, in fact). */
- }
- MUTEX_UNLOCK(&sock->writelock);
- return OK;
-}
-
-/**
- * Read from a GNUnet TCP socket.
- * @param sock the socket
- * @param buffer the buffer to write data to
- * @return OK if the read was successful, SYSERR if the socket
- * was closed by the other side (if the socket is a
- * client socket and is used again, tcpio will attempt
- * to re-establish the connection [temporary error]).
- */
-int readFromSocket(GNUNET_TCP_SOCKET * sock,
- CS_MESSAGE_HEADER ** buffer) {
- int res;
- unsigned int pos;
- char * buf;
- unsigned short size;
-
- if (SYSERR == checkSocket(sock))
- return SYSERR;
-
- MUTEX_LOCK(&sock->readlock);
- pos = 0;
- res = 0;
-
- pos = RECV_BLOCKING_ALL(sock->socket,
- &size,
- sizeof(unsigned short));
- if (pos != sizeof(unsigned short)) {
-#if DEBUG_TCPIO
- LOG_STRERROR(LOG_INFO, "recv");
-#endif
- closeSocketTemporarily(sock);
- MUTEX_UNLOCK(&sock->readlock);
- return SYSERR; /* other side closed socket or invalid header */
- }
- size = ntohs(size);
- if (size < sizeof(CS_MESSAGE_HEADER)) {
-#if DEBUG_TCPIO
- LOG_STRERROR(LOG_INFO, "recv");
-#endif
- closeSocketTemporarily(sock);
- MUTEX_UNLOCK(&sock->readlock);
- return SYSERR; /* invalid header */
- }
-
- buf = (char*) *buffer;
- if (buf == NULL)
- buf = MALLOC(size);
-
- res = RECV_BLOCKING_ALL(sock->socket,
- &buf[pos],
- size - pos);
-
- if (res != (int)(size - pos)) { /* error, abort */
- if (sock->socket != -1)
- LOG_STRERROR(LOG_INFO, "recv");
- closeSocketTemporarily(sock);
- if (*buffer == NULL)
- FREE(buf);
- MUTEX_UNLOCK(&sock->readlock);
- return SYSERR;
- }
-#if DEBUG_TCPIO
- LOG(LOG_DEBUG,
- "Successfully received %d bytes from TCP socket.\n",
- size);
-#endif
- MUTEX_UNLOCK(&sock->readlock);
- *buffer = (CS_MESSAGE_HEADER*) buf;
- (*buffer)->size = htons(size);
- return OK; /* success */
-}
-
-/**
- * Close a GNUnet TCP socket for now (use to temporarily close
- * a TCP connection that will probably not be used for a long
- * time; the socket will still be auto-reopened by the
- * readFromSocket/writeToSocket methods if it is a client-socket).
- */
-void closeSocketTemporarily(GNUNET_TCP_SOCKET * sock) {
- if (sock == NULL)
- return;
- if (sock->socket != -1) {
- int i;
-
- i = sock->socket;
-#if DEBUG_TCPIO
- LOG(LOG_DEBUG,
- "TCP: closing socket %d.\n",
- sock->socket);
-#endif
- sock->socket = -1;
- if (0 != SHUTDOWN(i, SHUT_RDWR))
- LOG_STRERROR(LOG_DEBUG, "shutdown");
- closefile(i);
- }
- sock->outBufLen = 0;
- FREENONNULL(sock->outBufPending);
- sock->outBufPending = NULL;
-}
-
-/**
- * Destroy a socket for good. If you use this socket afterwards,
- * you must first invoke initializeSocket, otherwise the operation
- * will fail.
- */
-void destroySocket(GNUNET_TCP_SOCKET * sock) {
- closeSocketTemporarily(sock);
- sock->ip.addr = 0;
- sock->port = 0;
- sock->outBufLen = 0;
- FREENONNULL(sock->outBufPending);
- sock->outBufPending = NULL;
- MUTEX_DESTROY(&sock->readlock);
- MUTEX_DESTROY(&sock->writelock);
-}
-
-
-/* end of tcpio.c */
Deleted: GNUnet/src/util/tcpiotest.c
===================================================================
--- GNUnet/src/util/tcpiotest.c 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/tcpiotest.c 2006-06-22 17:50:56 UTC (rev 3024)
@@ -1,261 +0,0 @@
-/**
- * @file test/tcpiotest.c
- * @brief testcase for util/tcpiotest.c
- */
-
-#include "gnunet_util.h"
-#include "platform.h"
-
-static int openServerSocket() {
- int listenerFD;
- int listenerPort;
- struct sockaddr_in serverAddr;
- const int on = 1;
-
- listenerPort = getGNUnetPort();
- /* create the socket */
- while ( (listenerFD = SOCKET(PF_INET, SOCK_STREAM, 0)) < 0) {
- LOG(LOG_ERROR,
- "ERROR opening socket (%s). "
- "No client service started. "
- "Trying again in 30 seconds.\n",
- STRERROR(errno));
- sleep(30);
- }
-
- /* fill in the inet address structure */
- memset((char *) &serverAddr,
- 0,
- sizeof(serverAddr));
- serverAddr.sin_family = AF_INET;
- serverAddr.sin_addr.s_addr=htonl(INADDR_ANY);
- serverAddr.sin_port=htons(listenerPort);
-
- if ( SETSOCKOPT(listenerFD,
- SOL_SOCKET,
- SO_REUSEADDR,
- &on, sizeof(on)) < 0 )
- perror("setsockopt");
-
- /* bind the socket */
- if (BIND (listenerFD,
- (struct sockaddr *) &serverAddr,
- sizeof(serverAddr)) < 0) {
- LOG(LOG_ERROR,
- "ERROR (%s) binding the TCP listener to port %d. "
- "Test failed. Is gnunetd running?\n",
- STRERROR(errno),
- listenerPort);
- return -1;
- }
-
- /* start listening for new connections */
- if (0 != LISTEN(listenerFD, 5)) {
- LOG(LOG_ERROR,
- " listen failed: %s\n",
- STRERROR(errno));
- return -1;
- }
- return listenerFD;
-}
-
-static int doAccept(int serverSocket) {
- int incomingFD;
- int lenOfIncomingAddr;
- struct sockaddr_in clientAddr;
-
- incomingFD = -1;
- while (incomingFD < 0) {
- lenOfIncomingAddr = sizeof(clientAddr);
- incomingFD = ACCEPT(serverSocket,
- (struct sockaddr *)&clientAddr,
- &lenOfIncomingAddr);
- if (incomingFD < 0) {
- LOG(LOG_ERROR,
- "ERROR accepting new connection (%s).\n",
- STRERROR(errno));
- continue;
- }
- }
- return incomingFD;
-}
-
-/**
- * Perform option parsing from the command line.
- */
-static int parseCommandLine(int argc,
- char * argv[]) {
- char c;
-
- while (1) {
- int option_index = 0;
- static struct GNoption long_options[] = {
- { "config", 1, 0, 'c' },
- { 0,0,0,0 }
- };
-
- c = GNgetopt_long(argc,
- argv,
- "c:",
- long_options,
- &option_index);
-
- if (c == -1)
- break; /* No more flags to process */
-
- switch(c) {
- case 'c':
- FREENONNULL(setConfigurationString("FILES",
- "gnunet.conf",
- GNoptarg));
- break;
- } /* end of parsing commandline */
- }
- FREENONNULL(setConfigurationString("GNUNETD",
- "LOGFILE",
- NULL));
- FREENONNULL(setConfigurationString("GNUNETD",
- "LOGLEVEL",
- "DEBUG"));
- return OK;
-}
-
-static int testTransmission(GNUNET_TCP_SOCKET * a,
- GNUNET_TCP_SOCKET * b) {
- CS_MESSAGE_HEADER * hdr;
- CS_MESSAGE_HEADER * buf;
- int i;
- int j;
-
- hdr = MALLOC(1024);
- for (i=0;i<1024-sizeof(CS_MESSAGE_HEADER);i+=7) {
- fprintf(stderr, ".");
- for (j=0;j<i;j++)
- ((char*)&hdr[1])[j] = (char)i+j;
- hdr->size = htons(i+sizeof(CS_MESSAGE_HEADER));
- hdr->type = 0;
- if (OK != writeToSocket(a, hdr)) {
- FREE(hdr);
- return 1;
- }
- buf = NULL;
- if (OK != readFromSocket(b, &buf)) {
- FREE(hdr);
- return 2;
- }
- if (0 != memcmp(buf, hdr, i+sizeof(CS_MESSAGE_HEADER))) {
- FREE(buf);
- FREE(hdr);
- return 4;
- }
- FREE(buf);
- }
- FREE(hdr);
- return 0;
-}
-
-static int testNonblocking(GNUNET_TCP_SOCKET * a,
- GNUNET_TCP_SOCKET * b) {
- CS_MESSAGE_HEADER * hdr;
- CS_MESSAGE_HEADER * buf;
- int i;
- int cnt;
-
- hdr = MALLOC(1024);
- for (i=0;i<1024-sizeof(CS_MESSAGE_HEADER);i+=11)
- ((char*)&hdr[1])[i] = (char)i;
- hdr->size = htons(64+sizeof(CS_MESSAGE_HEADER));
- hdr->type = 0;
- while (OK == writeToSocketNonBlocking(a,
- hdr))
- hdr->type++;
- i = 0;
- cnt = hdr->type;
- /* printf("Reading %u messages.\n", cnt); */
- if (cnt < 2)
- return 8; /* could not write ANY data non-blocking!? */
- for (i=0;i<cnt;i++) {
- hdr->type = i;
- buf = NULL;
- if (OK != readFromSocket(b, &buf)) {
- FREE(hdr);
- return 16;
- }
- if (0 != memcmp(buf, hdr, 64+sizeof(CS_MESSAGE_HEADER))) {
- printf("Failure in message %u. Headers: %d ? %d\n",
- i,
- buf->type,
- hdr->type);
- FREE(buf);
- FREE(hdr);
- return 32;
- }
- FREE(buf);
- if (i == cnt - 2) {
- /* printf("Blocking write to flush last non-blocking message.\n"); */
- hdr->type = cnt;
- if (OK != writeToSocket(a,
- hdr)) {
- FREE(hdr);
- return 64;
- }
- }
- }
- hdr->type = i;
- buf = NULL;
- if (OK != readFromSocket(b, &buf)) {
- FREE(hdr);
- return 128;
- }
- if (0 != memcmp(buf, hdr, 64+sizeof(CS_MESSAGE_HEADER))) {
- FREE(buf);
- FREE(hdr);
- return 256;
- }
- FREE(buf);
- FREE(hdr);
- return 0;
-}
-
-int main(int argc, char * argv[]){
- int i;
- int ret;
- int serverSocket;
- GNUNET_TCP_SOCKET * clientSocket;
- GNUNET_TCP_SOCKET acceptSocket;
-
- ret = 0;
- initUtil(argc, argv, &parseCommandLine);
- serverSocket = openServerSocket();
- clientSocket = getClientSocket();
- if (serverSocket == -1) {
- releaseClientSocket(clientSocket);
- doneUtil();
- return 1;
- }
- for (i=0;i<2;i++) {
- if (OK == checkSocket(clientSocket)) {
- if (OK == initGNUnetServerSocket(doAccept(serverSocket),
- &acceptSocket)) {
- ret = ret | testTransmission(clientSocket, &acceptSocket);
- ret = ret | testTransmission(&acceptSocket, clientSocket);
- ret = ret | testNonblocking(clientSocket, &acceptSocket);
- ret = ret | testNonblocking(&acceptSocket, clientSocket);
- closeSocketTemporarily(clientSocket);
- destroySocket(&acceptSocket);
- fprintf(stderr, "\n");
- } else {
- fprintf(stderr, "initGNUnetServerSocket failed.\n");
- ret = -1;
- }
- } else {
- fprintf(stderr, "checkSocket faild.\n");
- ret = -1;
- }
- }
- releaseClientSocket(clientSocket);
- doneUtil();
- if (ret > 0)
- fprintf(stderr, "Error %d\n", ret);
- return ret;
-}
Added: GNUnet/src/util/threads/Makefile.am
===================================================================
--- GNUnet/src/util/threads/Makefile.am 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/threads/Makefile.am 2006-06-22 17:50:56 UTC (rev 3024)
@@ -0,0 +1,34 @@
+INCLUDES = -I$(top_srcdir)/src/include
+
+SUBDIRS = .
+
+noinst_LTLIBRARIES = \
+ libthreads.la
+
+libthreads_la_SOURCES = \
+ mutex.c \
+ pthread.c \
+ semaphore.c \
+ shutdown.c
+
+check_PROGRAMS = \
+ semaphoretest \
+ shutdowntest \
+ timertest
+
+TESTS = $(check_PROGRAMS)
+
+semaphoretest_SOURCES = \
+ semaphoretest.c
+semaphoretest_LDADD = \
+ $(top_builddir)/src/util/libgnunetutil.la
+
+shutdowntest_SOURCES = \
+ shutdowntest.c
+shutdowntest_LDADD = \
+ $(top_builddir)/src/util/libgnunetutil.la
+
+timertest_SOURCES = \
+ timertest.c
+timertest_LDADD = \
+ $(top_builddir)/src/util/libgnunetutil.la
Added: GNUnet/src/util/threads/mutex.c
===================================================================
--- GNUnet/src/util/threads/mutex.c 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/threads/mutex.c 2006-06-22 17:50:56 UTC (rev 3024)
@@ -0,0 +1,162 @@
+/*
+ This file is part of GNUnet.
+ (C) 2001, 2002, 2003, 2004 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/threads/mutex.c
+ * @brief implementation of mutual exclusion
+ */
+
+#include "gnunet_util_threads.h"
+#include "gnunet_util_error.h"
+#include "gnunet_util_string.h"
+#include "platform.h"
+
+#if SOLARIS || FREEBSD || OSX
+#include <semaphore.h>
+#endif
+#if SOMEBSD
+# include <pthread_np.h>
+# include <sys/file.h>
+#endif
+#if LINUX
+# include <sys/sem.h>
+#endif
+#ifdef _MSC_VER
+#include <pthread.h>
+#include <semaphore.h>
+#endif
+
+#ifndef PTHREAD_MUTEX_NORMAL
+#ifdef PTHREAD_MUTEX_TIMED_NP
+#define PTHREAD_MUTEX_NORMAL PTHREAD_MUTEX_TIMED_NP
+#else
+#define PTHREAD_MUTEX_NORMAL NULL
+#endif
+#endif
+
+/**
+ * This prototype is somehow missing in various Linux pthread
+ * include files. But we need it and it seems to be available
+ * on all pthread-systems so far. Odd.
+ */
+#ifndef _MSC_VER
+extern int pthread_mutexattr_setkind_np(pthread_mutexattr_t *attr,
+ int kind);
+#endif
+
+
+typedef struct MUTEX {
+ pthread_mutex_t pt;
+} Mutex;
+
+Mutex * MUTEX_CREATE(int isRecursive) {
+ pthread_mutexattr_t attr;
+ Mutex * mut;
+#if WINDOWS
+ attr = NULL;
+#endif
+
+ pthread_mutexattr_init(&attr);
+ if (isRecursive) {
+#if LINUX
+ GE_ASSERT(NULL,
+ 0 == pthread_mutexattr_setkind_np
+ (&attr,
+ PTHREAD_MUTEX_RECURSIVE_NP));
+#elif SOMEBSD || FREEBSD || FREEBSD5
+ GE_ASSERT(NULL,
+ 0 == pthread_mutexattr_setkind_np
+ (&attr,
+ PTHREAD_MUTEX_RECURSIVE));
+#elif SOLARIS || OSX || WINDOWS
+ GE_ASSERT(NULL,
+ 0 == pthread_mutexattr_settype
+ (&attr,
+ PTHREAD_MUTEX_RECURSIVE));
+#endif
+ } else {
+#if LINUX
+ GE_ASSERT(NULL,
+ 0 == pthread_mutexattr_setkind_np
+ (&attr,
+ PTHREAD_MUTEX_ERRORCHECK_NP));
+#else
+ GE_ASSERT(NULL,
+ 0 == pthread_mutexattr_settype
+ (&attr,
+ PTHREAD_MUTEX_ERRORCHECK));
+#endif
+ }
+ mut = MALLOC(sizeof(Mutex));
+ GE_ASSERT(NULL,
+ 0 == pthread_mutex_init(&mut->pt,
+ &attr));
+ return mut;
+}
+
+void MUTEX_DESTROY(Mutex * mutex) {
+ GE_ASSERT(NULL, mutex != NULL);
+ errno = 0;
+ GE_ASSERT(NULL,
+ 0 == pthread_mutex_destroy(&mutex->pt));
+ FREE(mutex);
+}
+
+void MUTEX_LOCK(Mutex * mutex) {
+ int ret;
+
+ GE_ASSERT(NULL, mutex != NULL);
+ ret = pthread_mutex_lock(&mutex->pt);
+ if (ret != 0) {
+ if (ret == EINVAL)
+ GE_LOG(NULL,
+ GE_FATAL | GE_DEVELOPER | GE_USER | GE_IMMEDIATE,
+ _("Invalid argument for `%s'.\n"),
+ "pthread_mutex_lock");
+ if (ret == EDEADLK)
+ GE_LOG(NULL,
+ GE_FATAL | GE_DEVELOPER | GE_USER | GE_IMMEDIATE,
+ _("Deadlock due to `%s'.\n"),
+ "pthread_mutex_lock");
+ GE_ASSERT(NULL, 0);
+ }
+}
+
+void MUTEX_UNLOCK(Mutex * mutex) {
+ int ret;
+
+ GE_ASSERT(NULL, mutex != NULL);
+ ret = pthread_mutex_unlock(&mutex->pt);
+ if (ret != 0) {
+ if (ret == EINVAL)
+ GE_LOG(NULL,
+ GE_FATAL | GE_DEVELOPER | GE_USER | GE_IMMEDIATE,
+ _("Invalid argument for `%s'.\n"),
+ "pthread_mutex_lock");
+ if (ret == EPERM)
+ GE_LOG(NULL,
+ GE_FATAL | GE_DEVELOPER | GE_USER | GE_IMMEDIATE,
+ _("Permission denied for `%s'.\n"),
+ "pthread_mutex_unlock");
+ GE_ASSERT(NULL, 0);
+ }
+}
+
+/* end of mutex.c */
Added: GNUnet/src/util/threads/pthread.c
===================================================================
--- GNUnet/src/util/threads/pthread.c 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/threads/pthread.c 2006-06-22 17:50:56 UTC (rev 3024)
@@ -0,0 +1,292 @@
+/*
+ This file is part of GNUnet.
+ (C) 2001, 2002, 2003, 2004, 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/threads/pthread.c
+ * @brief implementation of pthread start/join/sleep
+ */
+
+#include "gnunet_util_threads.h"
+#include "gnunet_util_error.h"
+#include "gnunet_util_string.h"
+#include "platform.h"
+
+#if SOLARIS || FREEBSD || OSX
+#include <semaphore.h>
+#endif
+#if SOMEBSD
+# include <pthread_np.h>
+# include <sys/file.h>
+#endif
+#if LINUX
+# include <sys/sem.h>
+#endif
+#ifdef _MSC_VER
+#include <pthread.h>
+#endif
+
+typedef struct PTHREAD {
+ pthread_t pt;
+} PThread;
+
+/**
+ * Returns YES if pt is the handle for THIS thread.
+ */
+int PTHREAD_TEST_SELF(PThread * handle) {
+ GE_ASSERT(NULL, handle != NULL);
+#if pthread_equal
+ if (pthread_equal(pthread_self(), handle->pt))
+#else
+#if HAVE_NEW_PTHREAD_T
+ if (handle->pt->p == pthread_self().p)
+#else
+ if (handle->pt == pthread_self())
+#endif
+#endif
+ return YES;
+ else
+ return NO;
+}
+
+/**
+ * Get the handle for THIS thread.
+ */
+PThread * PTHREAD_GET_SELF() {
+ PThread * ret;
+ ret = MALLOC(sizeof(PThread));
+ ret->pt = pthread_self();
+ return ret;
+}
+
+/**
+ * Release handle for a thread.
+ */
+void PTHREAD_REL_SELF(PThread * handle) {
+ FREE(handle);
+}
+
+/**
+ * Create a thread. Use this method instead of pthread_create since
+ * BSD may only give a 1k stack otherwise.
+ *
+ * @param handle handle to the pthread (for detaching, join)
+ * @param main the main method of the thread
+ * @param arg the argument to main
+ * @param stackSize the size of the stack of the thread in bytes.
+ * Note that if the stack overflows, some OSes (seen under BSD)
+ * will just segfault and gdb will give a messed-up stacktrace.
+ * @return see pthread_create
+ */
+PThread * PTHREAD_CREATE(PThreadMain main,
+ void * arg,
+ unsigned int stackSize) {
+ PThread * handle;
+ pthread_attr_t stack_size_custom_attr;
+ int ret;
+
+ handle = MALLOC(sizeof(PThread));
+#ifdef MINGW
+ memset(handle, 0, sizeof(PThread));
+#endif
+ pthread_attr_init(&stack_size_custom_attr);
+ pthread_attr_setstacksize(&stack_size_custom_attr,
+ stackSize);
+ ret = pthread_create(&handle->pt,
+ &stack_size_custom_attr,
+ main,
+ arg);
+
+ if (ret != 0) {
+ FREE(handle);
+ return NULL;
+ }
+ return handle;
+}
+
+void PTHREAD_JOIN(PThread * handle,
+ void ** ret) {
+ int k;
+
+ GE_ASSERT(NULL,
+ handle != NULL);
+ GE_ASSERT(NULL,
+ NO == PTHREAD_TEST_SELF(handle));
+ k = pthread_join(handle->pt, ret);
+ FREE(handle);
+ switch (k) {
+ case 0:
+ return;
+ case ESRCH:
+ GE_LOG(NULL,
+ GE_FATAL | GE_USER | GE_DEVELOPER | GE_IMMEDIATE,
+ _("`%s' failed with error code %s: %s\n"),
+ "pthread_join",
+ "ESRCH",
+ STRERROR(errno));
+ break;
+ case EINVAL:
+ GE_LOG(NULL,
+ GE_FATAL | GE_USER | GE_DEVELOPER | GE_IMMEDIATE,
+ _("`%s' failed with error code %s: %s\n"),
+ "pthread_join",
+ "EINVAL",
+ STRERROR(errno));
+ case EDEADLK:
+ GE_LOG(NULL,
+ GE_FATAL | GE_USER | GE_DEVELOPER | GE_IMMEDIATE,
+ _("`%s' failed with error code %s: %s\n"),
+ "pthread_join",
+ "EDEADLK",
+ STRERROR(errno));
+ default:
+ GE_LOG(NULL,
+ GE_FATAL | GE_USER | GE_DEVELOPER | GE_IMMEDIATE,
+ _("`%s' failed with error code %d: %s\n"),
+ "pthread_join",
+ k,
+ STRERROR(errno));
+ }
+ GE_ASSERT(NULL, 0);
+}
+
+#ifdef WINDOWS
+/**
+ * @brief Called if a sleeping thread is interrupted
+ */
+static void CALLBACK __PTHREAD_SIGNALED(DWORD sig) {
+}
+#else
+static void sigalrmHandler(int sig) {
+}
+#endif
+
+
+/**
+ * Sleep for the specified time interval. Use PTHREAD_STOP_SLEEP to
+ * wake the thread up early. Caller is responsible to check that the
+ * sleep was long enough.
+ */
+void PTHREAD_SLEEP(unsigned long long delay) {
+#ifndef MINGW
+ static struct sigaction sig;
+ static struct sigaction old;
+#endif
+#if LINUX || SOLARIS || SOMEBSD || OSX
+ struct timespec req;
+ struct timespec rem;
+#elif WINDOWS
+#else
+ int ret;
+ struct timeval timeout;
+#endif
+
+ /* make sure SIGALRM does not kill us */
+#ifndef MINGW
+ memset(&sig, 0, sizeof(struct sigaction));
+ memset(&old, 0, sizeof(struct sigaction));
+ sig.sa_flags = SA_NODEFER;
+ sig.sa_handler = &sigalrmHandler;
+ if (0 != sigaction(SIGALRM, &sig, &old))
+ GE_LOG_STRERROR(NULL,
+ GE_WARNING | GE_ADMIN | GE_BULK,
+ "sigaction");
+#endif
+
+ /* actual sleep */
+#if LINUX || SOLARIS || SOMEBSD || OSX
+ req.tv_sec
+ = delay / 1000; /* ms -> seconds */
+ req.tv_nsec
+ = (delay - req.tv_sec * 1000) * 1000 * 1000; /* ms -> ns */
+ rem.tv_sec = 0;
+ rem.tv_nsec = 0;
+ if ( (0 != nanosleep(&req, &rem)) &&
+ (errno != EINTR) )
+ GE_LOG_STRERROR(NULL,
+ GE_WARNING | GE_USER | GE_BULK,
+ "nanosleep");
+#elif WINDOWS
+ SleepEx(delay, TRUE);
+#else
+ /* fall back to select */
+ timeout.tv_sec
+ = delay / CRON_UNIT_TO_SECONDS;
+ timeout.tv_usec
+ = (delay - timeout.tv_sec * CRON_UNIT_TO_SECONDS)
+ * MICROSEC_TO_CRON_UNIT;
+ ret = SELECT(0, NULL, NULL, NULL, &timeout);
+ if ( (ret == -1) &&
+ (errno != EINTR) )
+ GE_LOG_STRERROR(NULL,
+ GE_WARNING | GE_USER | GE_BULK,
+ "select");
+#endif
+
+ /* restore signal handler */
+#ifndef MINGW
+ if (0 != sigaction(SIGALRM, &old, &sig))
+ GE_LOG_STRERROR(NULL,
+ GE_WARNING | GE_ADMIN | GE_BULK,
+ "sigaction");
+#endif
+}
+
+void PTHREAD_STOP_SLEEP(PThread * handle) {
+ int ret;
+
+ GE_ASSERT(NULL, handle != NULL);
+#ifdef WINDOWS
+ ret = QueueUserAPC((PAPCFUNC) __PTHREAD_SIGNALED,
+ pthread_getw32threadhandle_np(handle->pt),
+ 0) != 0 ? 0 : EINVAL;
+#else
+ ret = pthread_kill(handle->pt, SIGALRM);
+#endif
+ switch (ret) {
+ case 0:
+ break; /* ok */
+ case EINVAL:
+ GE_LOG(NULL,
+ GE_ERROR | GE_USER | GE_DEVELOPER | GE_BULK,
+ _("`%s' failed with error code %s: %s\n"),
+ "pthread_kill",
+ "EINVAL",
+ STRERROR(ret));
+ break;
+ case ESRCH:
+ GE_LOG(NULL,
+ GE_ERROR | GE_USER | GE_DEVELOPER | GE_BULK,
+ _("`%s' failed with error code %s: %s\n"),
+ "pthread_kill",
+ "ESRCH",
+ STRERROR(ret));
+ break;
+ default:
+ GE_LOG(NULL,
+ GE_ERROR | GE_USER | GE_DEVELOPER | GE_BULK,
+ _("`%s' failed with error code %d: %s\n"),
+ "pthread_kill",
+ ret,
+ STRERROR(ret));
+ break;
+ }
+}
+
+/* end of semaphore.c */
Added: GNUnet/src/util/threads/semaphore.c
===================================================================
--- GNUnet/src/util/threads/semaphore.c 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/threads/semaphore.c 2006-06-22 17:50:56 UTC (rev 3024)
@@ -0,0 +1,165 @@
+/*
+ This file is part of GNUnet.
+ (C) 2001, 2002, 2003, 2004, 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/pthreads/semaphore.c
+ * @brief functions related to threading and synchronization
+ *
+ * In particular, functions for mutexes, semaphores
+ * and thread creation are provided.
+ */
+
+#include "gnunet_util_threads.h"
+#include "gnunet_util_error.h"
+#include "gnunet_util_string.h"
+#include "platform.h"
+
+#if SOLARIS || FREEBSD || OSX
+#include <semaphore.h>
+#include <sys/file.h>
+#endif
+#if SOMEBSD
+#include <pthread_np.h>
+#endif
+#if LINUX
+#include <sys/sem.h>
+#endif
+#ifdef _MSC_VER
+#include <pthread.h>
+#include <semaphore.h>
+#endif
+
+/**
+ * @brief Internal state of a semaphore.
+ */
+typedef struct SEMAPHORE {
+ /**
+ * Counter
+ */
+ int v;
+
+ /**
+ * Mutex
+ */
+ pthread_mutex_t mutex;
+
+ /**
+ * Wrapper for pthread condition variable.
+ */
+ pthread_cond_t cond;
+} Semaphore;
+
+#ifndef PTHREAD_MUTEX_NORMAL
+#ifdef PTHREAD_MUTEX_TIMED_NP
+#define PTHREAD_MUTEX_NORMAL PTHREAD_MUTEX_TIMED_NP
+#else
+#define PTHREAD_MUTEX_NORMAL NULL
+#endif
+#endif
+
+/**
+ * This prototype is somehow missing in various Linux pthread
+ * include files. But we need it and it seems to be available
+ * on all pthread-systems so far. Odd.
+ */
+#ifndef _MSC_VER
+extern int pthread_mutexattr_setkind_np(pthread_mutexattr_t *attr,
+ int kind);
+#endif
+
+/**
+ * function must be called prior to semaphore use -- handles
+ * setup and initialization. semaphore destroy (below) should
+ * be called when the semaphore is no longer needed.
+ */
+Semaphore * SEMAPHORE_CREATE(int value) {
+ Semaphore * s;
+ pthread_mutexattr_t attr;
+#if WINDOWS
+ attr = NULL;
+#endif
+
+ pthread_mutexattr_init(&attr);
+#if LINUX
+ GE_ASSERT(NULL,
+ 0 == pthread_mutexattr_setkind_np
+ (&attr,
+ PTHREAD_MUTEX_ERRORCHECK_NP));
+#else
+ GE_ASSERT(NULL,
+ 0 == pthread_mutexattr_settype
+ (&attr,
+ PTHREAD_MUTEX_ERRORCHECK));
+#endif
+ s = MALLOC(sizeof(Semaphore));
+ s->v = value;
+ GE_ASSERT(NULL,
+ 0 == pthread_mutex_init(&s->mutex,
+ &attr));
+ GE_ASSERT(NULL,
+ 0 == pthread_cond_init(&s->cond,
+ NULL));
+ return s;
+}
+
+void SEMAPHORE_DESTROY(Semaphore * s) {
+ GE_ASSERT(NULL, s != NULL);
+ GE_ASSERT(NULL,
+ 0 == pthread_cond_destroy(&s->cond));
+ GE_ASSERT(NULL,
+ 0 == pthread_mutex_destroy(&s->mutex));
+ FREE(s);
+}
+
+int SEMAPHORE_UP(Semaphore * s) {
+ int ret;
+
+ GE_ASSERT(NULL, s != NULL);
+ GE_ASSERT(NULL,
+ 0 == pthread_mutex_lock(&s->mutex));
+ ret = ++(s->v);
+ GE_ASSERT(NULL,
+ 0 == pthread_cond_signal(&s->cond));
+ GE_ASSERT(NULL,
+ 0 == pthread_mutex_unlock(&s->mutex));
+ return ret;
+}
+
+int SEMAPHORE_DOWN(Semaphore * s,
+ int mayblock) {
+ int ret;
+
+ GE_ASSERT(NULL, s != NULL);
+ GE_ASSERT(NULL,
+ 0 == pthread_mutex_lock(&s->mutex));
+ while ( (s->v <= 0) && mayblock)
+ GE_ASSERT(NULL,
+ 0 == pthread_cond_wait(&s->cond,
+ &s->mutex));
+ if (s->v > 0)
+ ret = --(s->v);
+ else
+ ret = SYSERR;
+ GE_ASSERT(NULL,
+ 0 == pthread_mutex_unlock(&s->mutex));
+ return ret;
+}
+
+/* end of semaphore.c */
Added: GNUnet/src/util/threads/semaphoretest.c
===================================================================
--- GNUnet/src/util/threads/semaphoretest.c 2006-06-22 17:39:19 UTC (rev
3023)
+++ GNUnet/src/util/threads/semaphoretest.c 2006-06-22 17:50:56 UTC (rev
3024)
@@ -0,0 +1,255 @@
+/*
+ This file is part of GNUnet.
+ (C) 2001, 2002, 2003, 2004 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 test/semaphore.c
+ * @brief testcase for util/threads/semaphore.c
+ */
+
+#include "gnunet_util.h"
+#include "platform.h"
+
+#include <sys/types.h>
+#ifndef MINGW /* PORT-ME MINGW */
+
+
+static Mutex lock;
+
+static Semaphore * sem;
+
+static volatile int sv;
+
+static volatile int tv;
+
+static void lockIt() {
+ sv = 0;
+ fprintf(stderr, ".");
+ while (sv == 0)
+ gnunet_util_sleep(50 * cronMILLIS); /* busy waiting may not always work */
+ MUTEX_LOCK(&lock);
+ sv = 1;
+ MUTEX_UNLOCK(&lock);
+ sv = 2;
+ tv = 2;
+}
+
+static void bigStack() {
+ int i;
+ char big[1024 * 100];
+
+ fprintf(stderr, ".");
+ for (i=0;i<1024*100;i++)
+ big[i] = (char) i;
+}
+
+static int testPTHREAD_CREATE() {
+ PTHREAD_T pt;
+ void * unused;
+
+ sv = -1; tv = 0;
+ fprintf(stderr, ".");
+ MUTEX_CREATE(&lock);
+ PTHREAD_CREATE(&pt,
+ (PThreadMain)&lockIt,
+ NULL,
+ 1024);
+ PTHREAD_DETACH(&pt);
+ while (tv != 2) {
+ sv = 1;
+ gnunet_util_sleep(50 * cronMILLIS); /* busy waiting may not always work */
+ }
+ MUTEX_DESTROY(&lock);
+ PTHREAD_CREATE(&pt,
+ (PThreadMain)&bigStack,
+ NULL,
+ 1024*100 + 25000); /* fails by segfault */
+ PTHREAD_JOIN(&pt, &unused);
+ return 0;
+}
+
+static int testMutex() {
+ PTHREAD_T pt;
+ void * unused;
+ MUTEX_CREATE(&lock);
+
+ sv = 1;
+ tv = 0;
+ PTHREAD_CREATE(&pt,
+ (PThreadMain)&lockIt,
+ NULL,
+ 1024);
+ while (sv == 1)
+ gnunet_util_sleep(50 * cronMILLIS); /* busy waiting may not always work */
+ MUTEX_LOCK(&lock);
+ sv = 5; /* release lockIt from while sv==0 loop,
+ blocks it on lock */
+ fprintf(stderr, ".");
+
+ if (sv != 5) {
+ MUTEX_UNLOCK(&lock);
+ while (tv != 2)
+ gnunet_util_sleep(50 * cronMILLIS); /* busy waiting may not always work
*/
+ MUTEX_DESTROY(&lock);
+ printf("MUTEX test failed at %s:%u\n",
+ __FILE__, __LINE__);
+ return 1; /* error */
+ } else {
+ MUTEX_UNLOCK(&lock);
+ while (tv != 2)
+ gnunet_util_sleep(50 * cronMILLIS); /* busy waiting may not always work
*/
+ PTHREAD_JOIN(&pt, &unused);
+ MUTEX_DESTROY(&lock);
+ return 0; /* ok */
+ }
+}
+
+static int testRecursiveMutex() {
+ int i;
+
+ fprintf(stderr, ".");
+ MUTEX_CREATE_RECURSIVE(&lock);
+ for (i=0;i<50;i++)
+ MUTEX_LOCK(&lock);
+ for (i=0;i<50;i++)
+ MUTEX_UNLOCK(&lock);
+ MUTEX_DESTROY(&lock);
+ return 0; /* ok -- fails by hanging!*/
+}
+
+static void semUpDown() {
+ int i;
+
+ fprintf(stderr, ".");
+ for (i=0;i<42;i++)
+ SEMAPHORE_DOWN(sem); /* fails by blocking */
+ if (SEMAPHORE_DOWN_NONBLOCKING(sem) != SYSERR) {
+ SEMAPHORE_FREE(sem);
+ printf("SEMAPHORE_DOWN_NONBLOCKING failed at %s:%u\n"
+ "Testcase deadlocked.\n",
+ __FILE__, __LINE__);
+ return; /* will halt testcase! */
+ }
+ for (i=0;i<42;i++)
+ SEMAPHORE_UP(sem);
+}
+
+static int testSemaphore() {
+ int i;
+ PTHREAD_T pt;
+ void * unused;
+
+ sem = SEMAPHORE_NEW(42);
+ fprintf(stderr, ".");
+ for (i=0;i<42;i++)
+ SEMAPHORE_DOWN(sem); /* fails by blocking */
+ if (SEMAPHORE_DOWN_NONBLOCKING(sem) != SYSERR) {
+ SEMAPHORE_FREE(sem);
+ printf("SEMAPHORE_DOWN_NONBLOCKING failed at %s:%u\n",
+ __FILE__, __LINE__);
+ return 1;
+ }
+ for (i=0;i<42;i++)
+ SEMAPHORE_UP(sem);
+ for (i=0;i<42;i++)
+ if (OK != SEMAPHORE_DOWN_NONBLOCKING(sem)) {
+ SEMAPHORE_FREE(sem);
+ printf("SEMAPHORE_DOWN_NONBLOCKING failed at %s:%u\n",
+ __FILE__, __LINE__);
+ return 1;
+ }
+ if (SEMAPHORE_DOWN_NONBLOCKING(sem) != SYSERR) {
+ SEMAPHORE_FREE(sem);
+ printf("SEMAPHORE_DOWN_NONBLOCKING failed at %s:%u\n",
+ __FILE__, __LINE__);
+ return 1;
+ }
+ fprintf(stderr, ".");
+ PTHREAD_CREATE(&pt,
+ (PThreadMain)&semUpDown,
+ NULL,
+ 1024);
+ for (i=0;i<42;i++)
+ SEMAPHORE_UP(sem);
+ PTHREAD_JOIN(&pt, &unused);
+ for (i=0;i<42;i++)
+ SEMAPHORE_DOWN(sem);
+ if (SEMAPHORE_DOWN_NONBLOCKING(sem) != SYSERR) {
+ SEMAPHORE_FREE(sem);
+ printf("SEMAPHORE_DOWN_NONBLOCKING failed at %s:%u\n",
+ __FILE__, __LINE__);
+ return 1;
+ }
+ return 0;
+}
+
+/**
+ * Perform option parsing from the command line.
+ */
+static int parseCommandLine(int argc,
+ char * argv[]) {
+ char c;
+
+ while (1) {
+ int option_index = 0;
+ static struct GNoption long_options[] = {
+ { "loglevel",1, 0, 'L' },
+ { "config", 1, 0, 'c' },
+ { 0,0,0,0 }
+ };
+
+ c = GNgetopt_long(argc,
+ argv,
+ "c:L:",
+ long_options,
+ &option_index);
+
+ if (c == -1)
+ break; /* No more flags to process */
+
+ switch(c) {
+ case 'L':
+ FREENONNULL(setConfigurationString("GNUNET",
+ "LOGLEVEL",
+ GNoptarg));
+ break;
+ case 'c':
+ FREENONNULL(setConfigurationString("FILES",
+ "gnunet.conf",
+ GNoptarg));
+ break;
+ } /* end of parsing commandline */
+ }
+ return OK;
+}
+#endif /* PORT-ME MINGW */
+
+int main(int argc, char * argv[]){
+ int ret = 0;
+
+#ifndef MINGW
+ initUtil(argc, argv, &parseCommandLine);
+ ret += testPTHREAD_CREATE();
+ ret += testMutex();
+ ret += testRecursiveMutex();
+ ret += testSemaphore();
+ fprintf(stderr, "\n");
+ doneUtil();
+#endif
+ return ret;
+}
Added: GNUnet/src/util/threads/shutdown.c
===================================================================
--- GNUnet/src/util/threads/shutdown.c 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/threads/shutdown.c 2006-06-22 17:50:56 UTC (rev 3024)
@@ -0,0 +1,123 @@
+/*
+ This file is part of GNUnet.
+ (C) 2001, 2002, 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/threads/shutdown.c
+ * @brief code to allow clean shutdown of application with signals
+ * @author Christian Grothoff
+ *
+ * Helper code for writing proper termination code when an application
+ * receives a SIGTERM/SIGHUP etc.
+ */
+
+#include "gnunet_util_threads.h"
+#include "gnunet_util_error.h"
+#include "gnunet_util_string.h"
+#include "platform.h"
+
+/**
+ * Semaphore used to signal "shutdown"
+ */
+static struct SEMAPHORE * shutdown_signal;
+
+static int shutdown_active;
+
+void GNUNET_SHUTDOWN_INITIATE() {
+ GE_ASSERT(NULL, shutdown_signal != NULL);
+ shutdown_active = YES;
+ SEMAPHORE_UP(shutdown_signal);
+}
+
+int GNUNET_SHUTDOWN_TEST() {
+ return shutdown_active;
+}
+
+void GNUNET_SHUTDOWN_WAITFOR() {
+ SEMAPHORE_DOWN(shutdown_signal, YES);
+}
+
+#ifdef MINGW
+BOOL WINAPI run_shutdown_win(DWORD dwCtrlType) {
+ switch(dwCtrlType) {
+ case CTRL_C_EVENT:
+ case CTRL_CLOSE_EVENT:
+ case CTRL_SHUTDOWN_EVENT:
+ case CTRL_LOGOFF_EVENT:
+ GNUNET_SHUTDOWN_INITIATE();
+ }
+ return TRUE;
+}
+#else
+static void run_shutdown(int signum) {
+ GNUNET_SHUTDOWN_INITIATE();
+}
+#endif
+
+/**
+ * Initialize the signal handlers, etc.
+ */
+void __attribute__ ((constructor)) shutdown_handlers_ltdl_init() {
+#ifndef MINGW
+ struct sigaction sig;
+ struct sigaction oldsig;
+#endif
+
+ GE_ASSERT(NULL, shutdown_signal == NULL);
+ GE_ASSERT(NULL, shutdown_active == NO);
+ shutdown_signal = SEMAPHORE_CREATE(0);
+#ifndef MINGW
+ sig.sa_handler = &run_shutdown;
+ sigemptyset(&sig.sa_mask);
+#ifdef SA_INTERRUPT
+ sig.sa_flags = SA_INTERRUPT; /* SunOS */
+#else
+ sig.sa_flags = SA_RESTART;
+#endif
+ sigaction(SIGINT, &sig, &oldsig);
+ sigaction(SIGTERM, &sig, &oldsig);
+ sigaction(SIGQUIT, &sig, &oldsig);
+#else
+ SetConsoleCtrlHandler(&run_shutdown_win, TRUE);
+#endif
+}
+
+void __attribute__ ((destructor)) shutdown_handlers_ltdl_fini() {
+#ifndef MINGW
+ struct sigaction sig;
+ struct sigaction oldsig;
+
+ sig.sa_handler = SIG_DFL;
+ sigemptyset(&sig.sa_mask);
+#ifdef SA_INTERRUPT
+ sig.sa_flags = SA_INTERRUPT; /* SunOS */
+#else
+ sig.sa_flags = SA_RESTART;
+#endif
+ sigaction(SIGINT, &sig, &oldsig);
+ sigaction(SIGTERM, &sig, &oldsig);
+ sigaction(SIGQUIT, &sig, &oldsig);
+#else
+ SetConsoleCtrlHandler(&run_shutdown_win, FALSE);
+#endif
+ SEMAPHORE_DESTROY(shutdown_signal);
+ shutdown_signal = NULL;
+}
+
+/* end of shutdown.c */
Added: GNUnet/src/util/threads/shutdowntest.c
===================================================================
--- GNUnet/src/util/threads/shutdowntest.c 2006-06-22 17:39:19 UTC (rev
3023)
+++ GNUnet/src/util/threads/shutdowntest.c 2006-06-22 17:50:56 UTC (rev
3024)
@@ -0,0 +1,95 @@
+/**
+ * @file test/shutdowntest.c
+ * @brief testcase for util/shutdown.c
+ */
+
+#include "gnunet_util.h"
+#include "platform.h"
+
+static pid_t myPID;
+
+static int check() {
+ /* first, test / SIGINT (simulated) */
+ initializeShutdownHandlers();
+ if (testShutdown() != NO)
+ return 1;
+#ifndef MINGW
+ kill(myPID, SIGINT);
+#else
+ GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0);
+#endif
+ if (testShutdown() != YES)
+ return 2;
+ wait_for_shutdown();
+ doneShutdownHandlers();
+
+ /* now, test "run_shutdown" */
+ initializeShutdownHandlers();
+ if (testShutdown() != NO)
+ return 3;
+ run_shutdown(42);
+ if (testShutdown() != YES)
+ return 4;
+ wait_for_shutdown();
+ doneShutdownHandlers();
+
+ return 0;
+}
+
+
+/**
+ * Perform option parsing from the command line.
+ */
+static int parseCommandLine(int argc,
+ char * argv[]) {
+ char c;
+
+ while (1) {
+ int option_index = 0;
+ static struct GNoption long_options[] = {
+ { "config", 1, 0, 'c' },
+ { 0,0,0,0 }
+ };
+
+ c = GNgetopt_long(argc,
+ argv,
+ "c:",
+ long_options,
+ &option_index);
+
+ if (c == -1)
+ break; /* No more flags to process */
+
+ switch(c) {
+ case 'c':
+ FREENONNULL(setConfigurationString("FILES",
+ "gnunet.conf",
+ GNoptarg));
+ break;
+ } /* end of parsing commandline */
+ }
+ FREENONNULL(setConfigurationString("GNUNETD",
+ "LOGFILE",
+ NULL));
+ FREENONNULL(setConfigurationString("GNUNETD",
+ "LOGLEVEL",
+ "WARNING"));
+ return OK;
+}
+
+int main(int argc,
+ char * argv[]){
+ int ret;
+
+ myPID = getpid();
+ initUtil(argc, argv, &parseCommandLine);
+
+ ret = check();
+ if (ret != 0)
+ fprintf(stderr,
+ "ERROR %d\n", ret);
+ doneUtil();
+ return ret;
+}
+
+/* end of shutdowntest.c */
Added: GNUnet/src/util/threads/timertest.c
===================================================================
--- GNUnet/src/util/threads/timertest.c 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/threads/timertest.c 2006-06-22 17:50:56 UTC (rev 3024)
@@ -0,0 +1,182 @@
+/**
+ * @file test/timertest.c
+ * @brief testcase for util/timer.c; also measures how
+ * precise the timers are. Expect values between 10 and 20 ms on
+ * modern machines.
+ */
+
+#include "gnunet_util.h"
+#include "platform.h"
+
+#define VERBOSE NO
+
+static void semaphore_up(Semaphore * sem) {
+ SEMAPHORE_UP(sem);
+}
+
+static int check() {
+ cron_t now;
+ cron_t last;
+ TIME_T tnow;
+ TIME_T tlast;
+ int i;
+ unsigned long long cumDelta;
+ Semaphore * sem;
+
+ /* test that time/cronTime are monotonically
+ increasing;
+ measure precision of sleep and report;
+ test that sleep is interrupted by signals; */
+ last = cronTime(&now);
+ if (last != now)
+ return 1;
+ tlast = TIME(&tnow);
+ if (tlast != tnow)
+ return 2;
+ while (now == last)
+ now = cronTime(NULL);
+ while (tnow == tlast)
+ tnow = TIME(NULL);
+ if (now < last)
+ return 3;
+ if (tnow < tlast)
+ return 4;
+ cumDelta = 0;
+#define INCR 47
+#define MAXV 1500
+ for (i=0;i<MAXV;i+=INCR) {
+ cronTime(&last);
+ if (0 != gnunet_util_sleep(cronMILLIS * i))
+ return 5;
+ cronTime(&now);
+#if VERBOSE
+ fprintf(stderr,
+ "%4u ms requested, got: %4lld ms\n",
+ i / cronMILLIS,
+ (now - last) / cronMILLIS);
+#endif
+ if (last + cronMILLIS * i < now)
+ cumDelta += (now - (last+cronMILLIS*i));
+ else
+ cumDelta += ((last+cronMILLIS*i) - now);
+ }
+ FPRINTF(stdout,
+ "Sleep precision: %llu ms. ",
+ cumDelta / cronMILLIS / (MAXV/INCR));
+ if (cumDelta <= 10 * cronMILLIS * MAXV / INCR)
+ fprintf(stdout,
+ "Timer precision is excellent.\n");
+ else if (cumDelta <= 50 * cronMILLIS * MAXV / INCR) /* 50 ms average
deviation */
+ fprintf(stdout,
+ "Timer precision is good.\n");
+ else if (cumDelta > 250 * cronMILLIS * MAXV / INCR)
+ fprintf(stdout,
+ "Timer precision is awful.\n");
+ else
+ fprintf(stdout,
+ "Timer precision is acceptable.\n");
+
+ sem = SEMAPHORE_NEW(0);
+
+ startCron();
+ cumDelta = 0;
+
+#define MAXV2 1500
+#define INCR2 113
+ for (i=50;i<MAXV2+50;i+=INCR2) {
+ cronTime(&last);
+ addCronJob((CronJob) &semaphore_up,
+ i * cronMILLIS,
+ 0,
+ sem);
+ SEMAPHORE_DOWN(sem);
+ cronTime(&now);
+ if (now < last + i)
+ now = last + i - now;
+ else
+ now = now - (last + i);
+ cumDelta += now;
+#if VERBOSE
+ FPRINTF(stderr,
+ "Sleep interrupted by signal within %llu ms of deadline (intended
delay: %d ms).\n",
+ now,
+ i);
+#endif
+ }
+ FPRINTF(stdout,
+ "Sleep interrupt precision is %llums. ",
+ cumDelta / (MAXV2/INCR2) );
+ if (cumDelta <= 10 * cronMILLIS * MAXV2 / INCR2)
+ fprintf(stdout,
+ "Timer precision is excellent.\n");
+ else if (cumDelta <= 50 * cronMILLIS * MAXV2 / INCR2) /* 50ms average
deviation */
+ fprintf(stdout,
+ "Timer precision is good.\n");
+ else if (cumDelta > 250 * cronMILLIS * MAXV2 / INCR2)
+ fprintf(stdout,
+ "Timer precision is awful.\n");
+ else
+ fprintf(stdout,
+ "Timer precision is acceptable.\n");
+
+ stopCron();
+ SEMAPHORE_FREE(sem);
+
+ return 0;
+}
+
+
+/**
+ * Perform option parsing from the command line.
+ */
+static int parseCommandLine(int argc,
+ char * argv[]) {
+ char c;
+
+ while (1) {
+ int option_index = 0;
+ static struct GNoption long_options[] = {
+ { "config", 1, 0, 'c' },
+ { 0,0,0,0 }
+ };
+
+ c = GNgetopt_long(argc,
+ argv,
+ "c:",
+ long_options,
+ &option_index);
+
+ if (c == -1)
+ break; /* No more flags to process */
+
+ switch(c) {
+ case 'c':
+ FREENONNULL(setConfigurationString("FILES",
+ "gnunet.conf",
+ GNoptarg));
+ break;
+ } /* end of parsing commandline */
+ }
+ FREENONNULL(setConfigurationString("GNUNETD",
+ "LOGFILE",
+ NULL));
+ FREENONNULL(setConfigurationString("GNUNETD",
+ "LOGLEVEL",
+ "WARNING"));
+ return OK;
+}
+
+int main(int argc,
+ char * argv[]){
+ int ret;
+ initUtil(argc, argv, &parseCommandLine);
+
+ ret = check();
+ if (ret != 0)
+ fprintf(stderr,
+ "ERROR %d\n", ret);
+ doneUtil();
+ return ret;
+}
+
+/* end of timertest.c */
Added: GNUnet/src/util/time.c
===================================================================
--- GNUnet/src/util/time.c 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/time.c 2006-06-22 17:50:56 UTC (rev 3024)
@@ -0,0 +1,30 @@
+/**
+ * TIME prototype. "man time".
+ */
+TIME_T TIME(TIME_T * t) {
+ TIME_T now;
+
+ now = (TIME_T) time(NULL); /* potential 64-bit to 32-bit conversion!*/
+ if (t != NULL)
+ *t = now;
+ return now;
+}
+
+/**
+ * "man ctime_r". Automagically expands the 32-bit
+ * GNUnet time value to a 64-bit value of the current
+ * epoc if needed.
+ */
+char * GN_CTIME(const TIME_T * t) {
+ TIME_T now;
+ time_t tnow;
+
+ tnow = time(NULL);
+ now = (TIME_T) tnow;
+ tnow = tnow - now + *t;
+#ifdef ctime_r
+ return ctime_r(&tnow, MALLOC(32));
+#else
+ return STRDUP(ctime(&tnow));
+#endif
+}
Deleted: GNUnet/src/util/timer.c
===================================================================
--- GNUnet/src/util/timer.c 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/timer.c 2006-06-22 17:50:56 UTC (rev 3024)
@@ -1,187 +0,0 @@
-/*
- This file is part of GNUnet.
- (C) 2003, 2004 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/timer.c
- * @brief abstraction of the time and sleep functions
- * @author Christian Grothoff
- *
- * GNUnet uses both 32-bit and 64-bit timer values.
- *
- * 32-bit timers are measured in seconds and are used
- * for some of the messages exchanged over
- * the network. We don't really care if they overrun
- * in 2037, as long as the relative times are correct.<p>
- * The type used for these values is TIME_T since
- * some architectures use 64-bit time_t values.
- * We wrap all time() calls into "TIME()" calls and
- * replace time_t with a GNUnet internal, 32-bit
- * TIME_T type.
- *
- * <p>
- * GNUnet also uses 64-bit cron_t timer values.
- * This is a milli-second precision timer that is
- * mostly used for internal timers. Some
- * network messages also use milli-second precision,
- * but these are so far always relative times which
- * are again represented as 32-bit (int) values.
- * <p>
- *
- * Consequently, whenever handling times in GNUnet,
- * watch out for the types and units involved.
- */
-
-#include "gnunet_util.h"
-#include "platform.h"
-
-/* change this value to artificially speed up all
- GNUnet cron timers by this factor. E.g. with 10,
- a cron-job scheduled after 1 minute in the code
- will occur after 6 seconds. This is useful for
- testing bugs that would otherwise occur only after
- a long time.
-
- For releases, this value should always be 1 */
-#define SPEED_UP 1
-
-/** number of cron units (ms) in a second */
-#define CRON_UNIT_TO_SECONDS (1000 / SPEED_UP)
-
-/** number of ns [usec] in a cron-unit (1000000) */
-#define NANOSEC_TO_CRON_UNIT (1000 * 1000 * SPEED_UP)
-
-/** number of us [usec] in a cron-unit (1000) */
-#define MICROSEC_TO_CRON_UNIT (1000 * SPEED_UP)
-
-
-/**
- * Sleep for the specified time interval. A signal interrupts the
- * sleep. Caller is responsible to check that the sleep was long
- * enough.
- *
- * @return 0 if there was no interrupt, 1 if there was, -1 on error.
- */
-int gnunet_util_sleep(cron_t delay) {
-#if LINUX || SOLARIS || SOMEBSD || OSX
- struct timespec req;
- struct timespec rem;
- req.tv_sec
- = delay / CRON_UNIT_TO_SECONDS;
- req.tv_nsec
- = (delay - req.tv_sec * CRON_UNIT_TO_SECONDS)
- * NANOSEC_TO_CRON_UNIT;
- rem.tv_sec = 0;
- rem.tv_nsec = 0;
- if (0 != nanosleep(&req, &rem)) {
- if (errno == EINTR) {
- return 1;
- } else {
- LOG_STRERROR(LOG_WARNING, "nanosleep");
- return -1;
- }
- } else
- return 0;
-#elif WINDOWS
- SleepEx(delay, TRUE);
- return 0; /* interrupt information is just an information, but
- not strict; error handling is, well, lacking,
- but this is Win32... */
-#else
- /* fall back to select */
- int ret;
- struct timeval timeout;
-
- timeout.tv_sec
- = delay / CRON_UNIT_TO_SECONDS;
- timeout.tv_usec
- = (delay - timeout.tv_sec * CRON_UNIT_TO_SECONDS)
- * MICROSEC_TO_CRON_UNIT;
- ret = SELECT(0, NULL, NULL, NULL, &timeout);
- if (ret == -1) {
- if (errno == EINTR) {
- return 1;
- } else {
- LOG_STRERROR(LOG_WARNING, "select");
- return -1;
- }
- }
- return 0;
-#endif
-}
-
-/**
- * Get the current time (works just as "time", just that we use the
- * unit of time that the cron-jobs use (and is 64 bit)).
- *
- * @param setme will set the current time if non-null
- * @return the current time
- */
-cron_t cronTime(cron_t * setme) {
- cron_t res;
- struct timeval tv;
-#ifndef WINDOWS
- struct timezone tz; /* man page says it's obsolete, but
- I'd rather not pass a NULL pointer */
-
- gettimeofday(&tv, &tz);
-#else
- gettimeofday(&tv, NULL);
-#endif
- res =
- (((cron_t)tv.tv_sec) * CRON_UNIT_TO_SECONDS) +
- (tv.tv_usec / MICROSEC_TO_CRON_UNIT);
- if (setme != NULL)
- *setme = res;
- return res;
-}
-
-/**
- * TIME prototype. "man time".
- */
-TIME_T TIME(TIME_T * t) {
- TIME_T now;
-
- now = (TIME_T) time(NULL); /* potential 64-bit to 32-bit conversion!*/
- if (t != NULL)
- *t = now;
- return now;
-}
-
-/**
- * "man ctime_r". Automagically expands the 32-bit
- * GNUnet time value to a 64-bit value of the current
- * epoc if needed.
- */
-char * GN_CTIME(const TIME_T * t) {
- TIME_T now;
- time_t tnow;
-
- tnow = time(NULL);
- now = (TIME_T) tnow;
- tnow = tnow - now + *t;
-#ifdef ctime_r
- return ctime_r(&tnow, MALLOC(32));
-#else
- return STRDUP(ctime(&tnow));
-#endif
-}
-
-
-/* end of timer.c */
Deleted: GNUnet/src/util/timertest.c
===================================================================
--- GNUnet/src/util/timertest.c 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/src/util/timertest.c 2006-06-22 17:50:56 UTC (rev 3024)
@@ -1,182 +0,0 @@
-/**
- * @file test/timertest.c
- * @brief testcase for util/timer.c; also measures how
- * precise the timers are. Expect values between 10 and 20 ms on
- * modern machines.
- */
-
-#include "gnunet_util.h"
-#include "platform.h"
-
-#define VERBOSE NO
-
-static void semaphore_up(Semaphore * sem) {
- SEMAPHORE_UP(sem);
-}
-
-static int check() {
- cron_t now;
- cron_t last;
- TIME_T tnow;
- TIME_T tlast;
- int i;
- unsigned long long cumDelta;
- Semaphore * sem;
-
- /* test that time/cronTime are monotonically
- increasing;
- measure precision of sleep and report;
- test that sleep is interrupted by signals; */
- last = cronTime(&now);
- if (last != now)
- return 1;
- tlast = TIME(&tnow);
- if (tlast != tnow)
- return 2;
- while (now == last)
- now = cronTime(NULL);
- while (tnow == tlast)
- tnow = TIME(NULL);
- if (now < last)
- return 3;
- if (tnow < tlast)
- return 4;
- cumDelta = 0;
-#define INCR 47
-#define MAXV 1500
- for (i=0;i<MAXV;i+=INCR) {
- cronTime(&last);
- if (0 != gnunet_util_sleep(cronMILLIS * i))
- return 5;
- cronTime(&now);
-#if VERBOSE
- fprintf(stderr,
- "%4u ms requested, got: %4lld ms\n",
- i / cronMILLIS,
- (now - last) / cronMILLIS);
-#endif
- if (last + cronMILLIS * i < now)
- cumDelta += (now - (last+cronMILLIS*i));
- else
- cumDelta += ((last+cronMILLIS*i) - now);
- }
- FPRINTF(stdout,
- "Sleep precision: %llu ms. ",
- cumDelta / cronMILLIS / (MAXV/INCR));
- if (cumDelta <= 10 * cronMILLIS * MAXV / INCR)
- fprintf(stdout,
- "Timer precision is excellent.\n");
- else if (cumDelta <= 50 * cronMILLIS * MAXV / INCR) /* 50 ms average
deviation */
- fprintf(stdout,
- "Timer precision is good.\n");
- else if (cumDelta > 250 * cronMILLIS * MAXV / INCR)
- fprintf(stdout,
- "Timer precision is awful.\n");
- else
- fprintf(stdout,
- "Timer precision is acceptable.\n");
-
- sem = SEMAPHORE_NEW(0);
-
- startCron();
- cumDelta = 0;
-
-#define MAXV2 1500
-#define INCR2 113
- for (i=50;i<MAXV2+50;i+=INCR2) {
- cronTime(&last);
- addCronJob((CronJob) &semaphore_up,
- i * cronMILLIS,
- 0,
- sem);
- SEMAPHORE_DOWN(sem);
- cronTime(&now);
- if (now < last + i)
- now = last + i - now;
- else
- now = now - (last + i);
- cumDelta += now;
-#if VERBOSE
- FPRINTF(stderr,
- "Sleep interrupted by signal within %llu ms of deadline (intended
delay: %d ms).\n",
- now,
- i);
-#endif
- }
- FPRINTF(stdout,
- "Sleep interrupt precision is %llums. ",
- cumDelta / (MAXV2/INCR2) );
- if (cumDelta <= 10 * cronMILLIS * MAXV2 / INCR2)
- fprintf(stdout,
- "Timer precision is excellent.\n");
- else if (cumDelta <= 50 * cronMILLIS * MAXV2 / INCR2) /* 50ms average
deviation */
- fprintf(stdout,
- "Timer precision is good.\n");
- else if (cumDelta > 250 * cronMILLIS * MAXV2 / INCR2)
- fprintf(stdout,
- "Timer precision is awful.\n");
- else
- fprintf(stdout,
- "Timer precision is acceptable.\n");
-
- stopCron();
- SEMAPHORE_FREE(sem);
-
- return 0;
-}
-
-
-/**
- * Perform option parsing from the command line.
- */
-static int parseCommandLine(int argc,
- char * argv[]) {
- char c;
-
- while (1) {
- int option_index = 0;
- static struct GNoption long_options[] = {
- { "config", 1, 0, 'c' },
- { 0,0,0,0 }
- };
-
- c = GNgetopt_long(argc,
- argv,
- "c:",
- long_options,
- &option_index);
-
- if (c == -1)
- break; /* No more flags to process */
-
- switch(c) {
- case 'c':
- FREENONNULL(setConfigurationString("FILES",
- "gnunet.conf",
- GNoptarg));
- break;
- } /* end of parsing commandline */
- }
- FREENONNULL(setConfigurationString("GNUNETD",
- "LOGFILE",
- NULL));
- FREENONNULL(setConfigurationString("GNUNETD",
- "LOGLEVEL",
- "WARNING"));
- return OK;
-}
-
-int main(int argc,
- char * argv[]){
- int ret;
- initUtil(argc, argv, &parseCommandLine);
-
- ret = check();
- if (ret != 0)
- fprintf(stderr,
- "ERROR %d\n", ret);
- doneUtil();
- return ret;
-}
-
-/* end of timertest.c */
Modified: GNUnet/todo
===================================================================
--- GNUnet/todo 2006-06-22 17:39:19 UTC (rev 3023)
+++ GNUnet/todo 2006-06-22 17:50:56 UTC (rev 3024)
@@ -12,7 +12,11 @@
0.7.1 ['06] (aka "stabilization")
-- known bugs (see Mantis for updates):
+- finish util refactoring
+- adapt util testcases and main GNUnet codebase
+- use new util to improve error handling capabilities
+- use new util to clean up gnunet-setup
+- fix known bugs (see Mantis for updates):
* gnunet-setup memory leaks (#878)
* gnunet-setup category switch update bug (#892) [ RC ]
* file/socket leak (#955)
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r3024 - in GNUnet: . src/applications src/applications/state src/include src/util src/util/crypto src/util/disk src/util/getopt src/util/loggers src/util/network src/util/os src/util/string src/util/threads,
grothoff <=