From 9a10e9c06a3b08c8ab73edb7d2093a6d452ecc05 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Fri, 21 Aug 2009 08:41:21 +0000 Subject: fixes --- src/fs/Makefile.am | 46 ++- src/fs/fs_collection.c | 704 +++++++++++++++++++++++++++++++++++++++++++ src/fs/fs_directory.c | 461 ++++++++++++++++++++++++++++ src/fs/test_fs_collection.c | 103 +++++++ src/fs/test_fs_directory.c | 167 ++++++++++ src/fs/test_fs_uri.c | 170 ++++++----- src/fs/test_fs_uri_data.conf | 9 + 7 files changed, 1561 insertions(+), 99 deletions(-) create mode 100644 src/fs/fs_collection.c create mode 100644 src/fs/fs_directory.c create mode 100644 src/fs/test_fs_collection.c create mode 100644 src/fs/test_fs_directory.c create mode 100644 src/fs/test_fs_uri_data.conf (limited to 'src/fs') diff --git a/src/fs/Makefile.am b/src/fs/Makefile.am index 266baa836..99b631668 100644 --- a/src/fs/Makefile.am +++ b/src/fs/Makefile.am @@ -27,39 +27,53 @@ libgnunetfs_la_LDFLAGS = \ -version-info 0:0:0 -#bin_PROGRAMS = \ -# gnunet-directory \ -# gnunet-download \ -# gnunet-pseudonym \ -# gnunet-search \ -# gnunet-share \ +#bin_PROGRAMS = +# gnunet-directory +# gnunet-download +# gnunet-pseudonym +# gnunet-search +# gnunet-share # gnunet-unindex -#gnunet_directory_SOURCES = \ +#gnunet_directory_SOURCES = # gnunet-directory.c -#gnunet_directory_LDADD = \ -# $(top_builddir)/src/fs/libgnunetfs.la \ -# $(top_builddir)/src/util/libgnunetutil.la \ +#gnunet_directory_LDADD = +# $(top_builddir)/src/fs/libgnunetfs.la +# $(top_builddir)/src/util/libgnunetutil.la # $(GN_LIBINTL) check_PROGRAMS = \ + test_fs_collection \ + test_fs_directory \ test_fs_getopt \ test_fs_uri TESTS = $(check_PROGRAMS) -test_fs_uri_SOURCES = \ - test_fs_uri.c -test_fs_LDADD = \ +test_fs_collection_SOURCES = \ + test_fs_collection.c +test_fs_collection_LDADD = \ + $(top_builddir)/src/fs/libgnunetfs.la \ + $(top_builddir)/src/util/libgnunetutil.la + +test_fs_directory_SOURCES = \ + test_fs_directory.c +test_fs_directory_LDADD = \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la test_fs_getopt_SOURCES = \ test_fs_getopt.c -test_fs_LDADD = \ +test_fs_getopt_LDADD = \ + $(top_builddir)/src/fs/libgnunetfs.la \ + $(top_builddir)/src/util/libgnunetutil.la + +test_fs_uri_SOURCES = \ + test_fs_uri.c +test_fs_uri_LDADD = \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la -#EXTRA_DIST = \ -# test_fs_data.conf +EXTRA_DIST = \ + test_fs_uri_data.conf diff --git a/src/fs/fs_collection.c b/src/fs/fs_collection.c new file mode 100644 index 000000000..01c7e3298 --- /dev/null +++ b/src/fs/fs_collection.c @@ -0,0 +1,704 @@ +/* + This file is part of GNUnet. + (C) 2004, 2005, 2006, 2008 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 fs/fs_collection.c + * @brief Helper functions for building a collection + * @author Christian Grothoff + * + * A collection is a special kind of namespace. A collection is the + * set of files provided by the same user, but unlike namespaces it is + * automatically managed by the GNUnet UI. A collection is a single + * directory in a namespace that is automatically updated each time + * the user updates or deletes a file. That is, once the user starts + * a collection the gnunet-tools will always keep the corresponding + * directory and namespace entries up-to-date. + * + * A good way of thinking about a collection is a lazy user's + * namespace. + */ + +#include "platform.h" +#include "gnunet_directories.h" +#include "gnunet_fs_service.h" + + +/** + * Initialize collection. + * + * @param h handle to the file sharing subsystem + * @param namespace namespace to use for the collection + * @return GNUNET_OK on success, GNUNET_SYSERR if another + * namespace is already set for our collection + */ +int +GNUNET_FS_collection_start (struct GNUNET_FS_Handle *h, + struct GNUNET_FS_Namespace *namespace) +{ + return GNUNET_SYSERR; +} + + +/** + * Stop collection. + * + * @param h handle to the file sharing subsystem + * @return GNUNET_OK on success, GNUNET_SYSERR if no collection is active + */ +int +GNUNET_FS_collection_stop (struct GNUNET_FS_Handle *h) +{ + return GNUNET_SYSERR; +} + + +/** + * Are we using a collection? + * + * @param h handle to the file sharing subsystem + * @return NULL if there is no collection, + */ +struct GNUNET_FS_Namespace * +GNUNET_FS_collection_get(struct GNUNET_FS_Handle *h) +{ + return NULL; +} + + +/** + * Publish an update of the current collection information to the + * network now. The function has no effect if the collection has not + * changed since the last publication. If we are currently not + * collecting, this function does nothing. + * + * @param h handle to the file sharing subsystem + */ +void GNUNET_FS_collection_publish (struct GNUNET_FS_Handle *h) +{ +} + + +/** + * If we are currently building a collection, publish the given file + * information in that collection. If we are currently not + * collecting, this function does nothing. + * + * @param h handle to the file sharing subsystem + * @param uri uri to add to the collection + * @param meta metadata for the uri + */ +void GNUNET_FS_collection_add (const struct GNUNET_FS_Handle *h, + const struct GNUNET_FS_Uri *uri, + const struct GNUNET_CONTAINER_MetaData *meta) +{ +} + + +#if 0 + +/** + * Filename used to store collection information + */ +#define COLLECTION "collection" + +#define COLLECTION_ROOT "root" + +/** + * How long does a collection advertisement live? + */ +#define COLLECTION_ADV_LIFETIME (12 * GNUNET_CRON_MONTHS) + +/** + * @brief information about a collection + */ +typedef struct CollectionData +{ + + /** + * What is the pseudonym ID for the publication? + */ + GNUNET_HashCode pid; + + /** + * Anonymity level for the collection. (NBO) + */ + unsigned int anonymityLevel; + + /** + * Priority of the collection (NBO). + */ + unsigned int priority; + + /** + * Has this collection changed since the last publication? + */ + int changed; + + /** + * Revision counter + */ + unsigned int revision; + +} CollectionData; + + +typedef struct +{ + + CollectionData data; + + /** + * Metadata describing the collection + */ + struct GNUNET_MetaData *meta; + + /** + * Files in the collection. + */ + GNUNET_ECRS_FileInfo *files; + + /** + * How many files are in files? + */ + unsigned int file_count; + + +} CollectionInfo; + +static CollectionInfo *collectionData; + +static struct GNUNET_Mutex *lock; + +static struct GNUNET_GE_Context *ectx; + +static struct GNUNET_GC_Configuration *cfg; + +static char * +getCollectionFileName () +{ + return GNUNET_get_home_filename (ectx, cfg, GNUNET_NO, COLLECTION, NULL); +} + +/** + * Initialize collection module. + */ +void +GNUNET_CO_init (struct GNUNET_GE_Context *e, + struct GNUNET_GC_Configuration *c) +{ + char *fn; + int len; + unsigned int mlen; + unsigned long long size; + char *buf; + int fd; + const char *pos; + size_t rsize; + unsigned int i; + char *tmp; + + cfg = c; + ectx = e; + lock = GNUNET_mutex_create (GNUNET_YES); + fn = getCollectionFileName (); + if (!GNUNET_disk_file_test (ectx, fn)) + { + GNUNET_free (fn); + return; + } + /* read collection data */ + if (GNUNET_OK != GNUNET_disk_file_size (ectx, fn, &size, GNUNET_YES)) + { + GNUNET_free (fn); + return; + } + if ((size > 0x7FFFFFFF) || + (size < sizeof (CollectionData) + 2 * sizeof (int))) + { + GNUNET_GE_BREAK (ectx, 0); + UNLINK (fn); + GNUNET_free (fn); + return; + } + fd = OPEN (fn, O_RDONLY | O_LARGEFILE); + if (fd == -1) + { + GNUNET_GE_BREAK (ectx, 0); + UNLINK (fn); + GNUNET_free (fn); + return; + } + rsize = (size_t) size; + buf = MMAP (NULL, rsize, PROT_READ, MAP_SHARED, fd, 0); + if (buf == MAP_FAILED) + { + GNUNET_GE_LOG_STRERROR_FILE (ectx, + GNUNET_GE_ERROR | GNUNET_GE_ADMIN | + GNUNET_GE_USER | GNUNET_GE_BULK, "mmap", + fn); + CLOSE (fd); + GNUNET_free (fn); + return; + } + collectionData = GNUNET_malloc (sizeof (CollectionInfo)); + memset (collectionData, 0, sizeof (CollectionInfo)); + memcpy (&collectionData->data, buf, sizeof (CollectionData)); + pos = &buf[sizeof (CollectionData)]; + rsize -= sizeof (CollectionData); + len = ntohl (*(int *) pos); + if (len > 1024 * 1024 * 4) + goto ERR; + pos += sizeof (int); + mlen = ntohl (*(unsigned int *) pos); + pos += sizeof (unsigned int); + rsize -= 2 * sizeof (int); + if (mlen > rsize) + goto ERR; + GNUNET_array_grow (collectionData->files, collectionData->file_count, len); + collectionData->meta = GNUNET_meta_data_deserialize (ectx, pos, mlen); + rsize -= mlen; + pos += mlen; + GNUNET_GE_BREAK (ectx, collectionData->meta != NULL); + for (i = 0; i < collectionData->file_count; i++) + { + if (rsize < 2 * sizeof (int)) + { + GNUNET_GE_BREAK (ectx, 0); + break; + } + len = ntohl (*(int *) pos); + pos += sizeof (int); + mlen = ntohl (*(int *) pos); + pos += sizeof (int); + rsize -= 2 * sizeof (int); + if (rsize < mlen + len) + { + GNUNET_GE_BREAK (ectx, 0); + break; + } + if (len > 1024 * 16) + { + GNUNET_GE_BREAK (ectx, 0); + len = 1024 * 16; + } + tmp = GNUNET_malloc (len + 1); + tmp[len] = '\0'; + memcpy (tmp, pos, len); + pos += len; + rsize -= len; + collectionData->files[i].uri = GNUNET_ECRS_string_to_uri (ectx, tmp); + GNUNET_GE_ASSERT (ectx, collectionData->files[i].uri != NULL); + GNUNET_free (tmp); + collectionData->files[i].meta + = GNUNET_meta_data_deserialize (ectx, pos, mlen); + GNUNET_GE_ASSERT (ectx, collectionData->files[i].meta != NULL); + pos += mlen; + rsize -= mlen; + } + GNUNET_GE_ASSERT (ectx, rsize == 0); + MUNMAP (buf, (size_t) size); + CLOSE (fd); + GNUNET_free (fn); + /* kill invalid entries (meta or uri == NULL) */ + for (i = 0; i < collectionData->file_count; i++) + { + if ((collectionData->files[i].uri != NULL) && + (collectionData->files[i].meta != NULL)) + continue; + if (collectionData->files[i].uri != NULL) + GNUNET_ECRS_uri_destroy (collectionData->files[i].uri); + if (collectionData->files[i].meta != NULL) + GNUNET_meta_data_destroy (collectionData->files[i].meta); + collectionData->files[i] + = collectionData->files[collectionData->file_count - 1]; + GNUNET_array_grow (collectionData->files, + collectionData->file_count, + collectionData->file_count - 1); + } + return; +ERR: + MUNMAP (buf, (size_t) size); + CLOSE (fd); + GNUNET_free (fn); + GNUNET_free (collectionData); + collectionData = NULL; +} + +static void +WRITEINT (int fd, int val) +{ + int bval; + + bval = htonl (val); + WRITE (fd, &bval, sizeof (int)); +} + +static void +writeCO () +{ + char *fn; + unsigned int mlen; + char *buf; + int fd; + unsigned int i; + char *tmp; + + if (collectionData == NULL) + return; + + /* write collection data */ + mlen = + GNUNET_meta_data_get_serialized_size (collectionData->meta, GNUNET_NO); + buf = GNUNET_malloc (mlen); + if (mlen != GNUNET_meta_data_serialize (ectx, + collectionData->meta, buf, + mlen, GNUNET_NO)) + { + GNUNET_GE_BREAK (ectx, 0); + GNUNET_free (buf); + return; + } + + fn = getCollectionFileName (); + fd = OPEN (fn, + O_CREAT | O_LARGEFILE | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR); + if (fd == -1) + { + GNUNET_GE_LOG_STRERROR_FILE (ectx, + GNUNET_GE_USER | GNUNET_GE_ADMIN | + GNUNET_GE_ERROR | GNUNET_GE_BULK, "open", + fn); + GNUNET_free (fn); + GNUNET_free (buf); + return; + } + GNUNET_GE_BREAK (ectx, collectionData->file_count <= 1024 * 1024 * 4); + WRITE (fd, collectionData, sizeof (CollectionData)); + WRITEINT (fd, collectionData->file_count); + WRITEINT (fd, mlen); + WRITE (fd, buf, mlen); + GNUNET_free (buf); + for (i = 0; i < collectionData->file_count; i++) + { + mlen = + GNUNET_meta_data_get_serialized_size (collectionData->files[i].meta, + GNUNET_NO); + buf = GNUNET_malloc (mlen); + if (mlen != GNUNET_meta_data_serialize (ectx, + collectionData->files[i].meta, + buf, mlen, GNUNET_NO)) + { + GNUNET_GE_BREAK (ectx, 0); + GNUNET_free (buf); + break; + } + tmp = GNUNET_ECRS_uri_to_string (collectionData->files[i].uri); + WRITEINT (fd, strlen (tmp)); + WRITEINT (fd, mlen); + GNUNET_GE_BREAK (ectx, strlen (tmp) < 16 * 1024); + WRITE (fd, tmp, strlen (tmp)); + GNUNET_free (tmp); + WRITE (fd, buf, mlen); + GNUNET_free (buf); + } + CLOSE (fd); + GNUNET_free (fn); +} + +static void +free_collection_data () +{ + unsigned int i; + + if (collectionData == NULL) + return; + GNUNET_meta_data_destroy (collectionData->meta); + for (i = 0; i < collectionData->file_count; i++) + { + GNUNET_meta_data_destroy (collectionData->files[i].meta); + GNUNET_ECRS_uri_destroy (collectionData->files[i].uri); + } + GNUNET_array_grow (collectionData->files, collectionData->file_count, 0); + GNUNET_free (collectionData); + collectionData = NULL; +} + +/** + * Shutdown collection module. + */ +void +GNUNET_CO_done () +{ + writeCO (); + free_collection_data (); + GNUNET_mutex_destroy (lock); + lock = NULL; + ectx = NULL; + cfg = NULL; +} + + +/** + * Start collection. + * + * @param updateInterval of GNUNET_ECRS_SBLOCK_UPDATE_NONE + * means to update _immediately_ on any change, + * wherease GNUNET_ECRS_SBLOCK_UPDATE_SPORADIC means + * to publish updates when the CO_Context + * is destroyed (i.e. on exit from the UI). + */ +int +GNUNET_CO_collection_start (unsigned int anonymityLevel, + unsigned int prio, + const struct GNUNET_MetaData *meta) +{ + struct GNUNET_ECRS_URI *advertisement; + struct GNUNET_ECRS_URI *rootURI; + const char *root = COLLECTION_ROOT; + + GNUNET_mutex_lock (lock); + GNUNET_CO_collection_stop (); /* cancel old collection */ + advertisement = GNUNET_ECRS_keyword_string_to_uri (ectx, COLLECTION); + GNUNET_GE_ASSERT (ectx, advertisement != NULL); + rootURI = GNUNET_ECRS_namespace_create (ectx, + cfg, + meta, + anonymityLevel, + prio, + GNUNET_get_time () + + COLLECTION_ADV_LIFETIME, + advertisement, root); + GNUNET_ECRS_uri_destroy (advertisement); + if (rootURI == NULL) + { + GNUNET_mutex_unlock (lock); + return GNUNET_SYSERR; + } + collectionData = GNUNET_malloc (sizeof (CollectionInfo)); + memset (collectionData, 0, sizeof (CollectionInfo)); + GNUNET_ECRS_uri_get_namespace_from_sks (rootURI, &collectionData->data.pid); + GNUNET_ECRS_uri_destroy (rootURI); + collectionData->data.priority = htonl (prio); + collectionData->data.anonymityLevel = htonl (anonymityLevel); + collectionData->meta = GNUNET_meta_data_duplicate (meta); + GNUNET_mutex_unlock (lock); + return GNUNET_OK; +} + +/** + * Stop collection. + * + * @return GNUNET_OK on success, GNUNET_SYSERR if no collection is active + */ +int +GNUNET_CO_collection_stop () +{ + GNUNET_mutex_lock (lock); + if (collectionData == NULL) + { + GNUNET_mutex_unlock (lock); + return GNUNET_SYSERR; + } + GNUNET_ECRS_namespace_delete (ectx, cfg, &collectionData->data.pid); + free_collection_data (); + GNUNET_mutex_unlock (lock); + return GNUNET_OK; +} + +/** + * Are we using a collection? + * + * @return NULL if there is no collection, otherwise its metadata + */ +struct GNUNET_MetaData * +GNUNET_CO_collection_get_name () +{ + struct GNUNET_MetaData *meta; + + GNUNET_mutex_lock (lock); + if (collectionData == NULL) + { + GNUNET_mutex_unlock (lock); + return NULL; + } + meta = GNUNET_meta_data_duplicate (collectionData->meta); + GNUNET_mutex_unlock (lock); + return meta; +} + +/** + * Publish an update of the current collection information to the + * network now. The function has no effect if the collection has not + * changed since the last publication. If we are currently not + * collecting, this function does nothing. + */ +void +GNUNET_CO_collection_publish_now () +{ + struct GNUNET_ECRS_URI *uri; + struct GNUNET_ECRS_URI *directoryURI; + unsigned long long dirLen; + char *tmpName; + int fd; + char *dirData; + char this_revision_string[128]; + char next_revision_string[128]; + const char *tmpdir; + + GNUNET_mutex_lock (lock); + if ((collectionData == NULL) || + (ntohl (collectionData->data.changed) == GNUNET_NO)) + { + GNUNET_mutex_unlock (lock); + return; + } + + tmpdir = getenv ("TMPDIR"); + tmpdir = tmpdir ? tmpdir : "/tmp"; + +#define TEMPLATE "/gnunet-collectionXXXXXX" + tmpName = GNUNET_malloc (strlen (tmpdir) + sizeof (TEMPLATE) + 1); + strcpy (tmpName, tmpdir); + strcat (tmpName, TEMPLATE); +#undef TEMPLATE + fd = mkstemp (tmpName); + if (fd == -1) + { + GNUNET_GE_LOG_STRERROR (ectx, + GNUNET_GE_ERROR | GNUNET_GE_ADMIN | + GNUNET_GE_BULK, "mkstemp"); + GNUNET_free (tmpName); + GNUNET_mutex_unlock (lock); + return; + } + dirData = NULL; + GNUNET_GE_ASSERT (ectx, + GNUNET_OK == GNUNET_ECRS_directory_create (ectx, + &dirData, + &dirLen, + collectionData->file_count, + collectionData->files, + collectionData->meta)); + if (-1 == WRITE (fd, dirData, dirLen)) + { + GNUNET_GE_LOG_STRERROR (ectx, + GNUNET_GE_ERROR | GNUNET_GE_ADMIN | + GNUNET_GE_BULK, "write"); + GNUNET_free (tmpName); + GNUNET_free (dirData); + GNUNET_mutex_unlock (lock); + return; + } + GNUNET_free (dirData); + CLOSE (fd); + if (GNUNET_OK != GNUNET_ECRS_file_upload (ectx, cfg, tmpName, GNUNET_NO, /* indexing */ + ntohl (collectionData-> + data.anonymityLevel), + ntohl (collectionData-> + data.priority), + GNUNET_get_time () + + COLLECTION_ADV_LIFETIME, NULL, + NULL, NULL, NULL, &directoryURI)) + { + UNLINK (tmpName); + GNUNET_free (tmpName); + GNUNET_mutex_unlock (lock); + return; + } + UNLINK (tmpName); + GNUNET_free (tmpName); + if (ntohl (collectionData->data.revision) == 0) + strcpy (this_revision_string, COLLECTION_ROOT); + else + GNUNET_snprintf (this_revision_string, + sizeof (this_revision_string), + _("Revision %u"), ntohl (collectionData->data.revision)); + GNUNET_snprintf (next_revision_string, + sizeof (next_revision_string), + _("Revision %u"), + ntohl (collectionData->data.revision) + 1); + uri = GNUNET_ECRS_namespace_add_content (ectx, + cfg, + &collectionData->data.pid, + ntohl (collectionData-> + data.anonymityLevel), + ntohl (collectionData-> + data.priority), + GNUNET_get_time () + + COLLECTION_ADV_LIFETIME, + this_revision_string, + next_revision_string, directoryURI, + collectionData->meta); + if (uri != NULL) + { + collectionData->data.revision = + htonl (ntohl (collectionData->data.revision) + 1); + collectionData->data.changed = htonl (GNUNET_NO); + GNUNET_ECRS_uri_destroy (uri); + } + GNUNET_mutex_unlock (lock); +} + +/** + * If we are currently building a collection, publish + * the given file information in that collection. + * If we are currently not collecting, this function + * does nothing. + */ +void +GNUNET_CO_collection_add_item (const GNUNET_ECRS_FileInfo * fi) +{ + unsigned int i; + GNUNET_ECRS_FileInfo fc; + + if ((GNUNET_ECRS_uri_test_ksk (fi->uri))) + { + GNUNET_GE_BREAK (ectx, 0); + return; + } + if (lock == NULL) + { + GNUNET_GE_BREAK (ectx, 0); + return; + } + GNUNET_mutex_lock (lock); + if (collectionData == NULL) + { + GNUNET_mutex_unlock (lock); + return; + } + for (i = 0; i < collectionData->file_count; i++) + { + if (GNUNET_ECRS_uri_test_equal (fi->uri, collectionData->files[i].uri)) + { + GNUNET_mutex_unlock (lock); + return; + } + } + fc.uri = GNUNET_ECRS_uri_duplicate (fi->uri); + fc.meta = GNUNET_meta_data_duplicate (fi->meta); + GNUNET_array_append (collectionData->files, collectionData->file_count, fc); + collectionData->data.changed = htonl (GNUNET_YES); + GNUNET_mutex_unlock (lock); +} + +#endif + +/* end of fs_collection.c */ diff --git a/src/fs/fs_directory.c b/src/fs/fs_directory.c new file mode 100644 index 000000000..1ee707cd1 --- /dev/null +++ b/src/fs/fs_directory.c @@ -0,0 +1,461 @@ +/* + This file is part of GNUnet. + (C) 2003, 2004, 2006, 2009 Christian Grothoff (and other contributing authors) + + GNUnet is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 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 fs/fs_directory.c + * @brief Helper functions for building directories. + * @author Christian Grothoff + * + * TODO: + * - add support for embedded file data (use padding room!) + * - add directory builder API to gnunet_fs_service + * - modify directory builder API to support incremental + * generation of directories (to allow directories that + * would not fit into memory to be created) + * - modify directory processor API to support incremental + * iteration over FULL directories (without missing entries) + * to allow access to directories that do not fit entirely + * into memory + */ +#include "platform.h" +#include "gnunet_fs_service.h" +#include "fs.h" + + +/** + * Does the meta-data claim that this is a directory? + * Checks if the mime-type is that of a GNUnet directory. + * + * @return GNUNET_YES if it is, GNUNET_NO if it is not, GNUNET_SYSERR if + * we have no mime-type information (treat as 'GNUNET_NO') + */ +int +GNUNET_FS_meta_data_test_for_directory (const struct GNUNET_CONTAINER_MetaData *md) +{ + char *mime; + int ret; + + mime = GNUNET_CONTAINER_meta_data_get_by_type (md, EXTRACTOR_MIMETYPE); + if (mime == NULL) + return GNUNET_SYSERR; + ret = (0 == strcmp (mime, GNUNET_FS_DIRECTORY_MIME)) ? GNUNET_YES : GNUNET_NO; + GNUNET_free (mime); + return ret; +} + + +/** + * Set the MIMETYPE information for the given + * metadata to "application/gnunet-directory". + * + * @param md metadata to add mimetype to + */ +void +GNUNET_FS_meta_data_make_directory (struct GNUNET_CONTAINER_MetaData *md) +{ + char *mime; + + mime = GNUNET_CONTAINER_meta_data_get_by_type (md, EXTRACTOR_MIMETYPE); + if (mime != NULL) + { + GNUNET_break (0 == strcmp (mime, + GNUNET_FS_DIRECTORY_MIME)); + GNUNET_free (mime); + return; + } + GNUNET_CONTAINER_meta_data_insert (md, + EXTRACTOR_MIMETYPE, + GNUNET_FS_DIRECTORY_MIME); +} + + +/** + * Iterate over all entries in a directory. Note that directories + * are structured such that it is possible to iterate over the + * individual blocks as well as over the entire directory. Thus + * a client can call this function on the buffer in the + * GNUNET_FS_ProgressCallback. Also, directories can optionally + * include the contents of (small) files embedded in the directory + * itself; for those files, the processor may be given the + * contents of the file directly by this function. + *

+ * + * Note that this function maybe called on parts of directories. Thus + * parser errors should not be reported _at all_ (with GNUNET_break). + * Still, if some entries can be recovered despite these parsing + * errors, the function should try to do this. + * + * @param size number of bytes in data + * @param data pointer to the beginning of the directory + * @param offset offset of data in the directory + * @param dep function to call on each entry + * @param dep_cls closure for dep + */ +void +GNUNET_FS_directory_list_contents (size_t size, + const void *data, + uint64_t offset, + GNUNET_FS_DirectoryEntryProcessor dep, + void *dep_cls) +{ + const char *cdata = data; + char *emsg; + uint64_t pos; + uint64_t align; + uint32_t mdSize; + uint64_t epos; + struct GNUNET_FS_Uri *uri; + struct GNUNET_CONTAINER_MetaData *md; + char *filename; + + pos = offset; + if ( (pos == 0) && + (size >= 8 + sizeof (uint32_t)) && + (0 == memcmp (cdata, GNUNET_FS_DIRECTORY_MAGIC, 8)) ) + { + memcpy (&mdSize, &cdata[8], sizeof (uint32_t)); + mdSize = ntohl (mdSize); + if (mdSize > size - 8 - sizeof (uint32_t)) + { + /* invalid size */ + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + _("Not a GNUnet directory.\n")); + return; + } + md = GNUNET_CONTAINER_meta_data_deserialize (&cdata[8 + + sizeof (uint32_t)], + mdSize); + if (md == NULL) + { + GNUNET_break (0); + return; /* malformed ! */ + } + dep (dep_cls, + NULL, + NULL, + md, + 0, + NULL); + GNUNET_CONTAINER_meta_data_destroy (md); + pos = 8 + sizeof (uint32_t) + mdSize; + } + while (pos < size) + { + /* find end of URI */ + if (cdata[pos] == '\0') + { + /* URI is never empty, must be end of block, + skip to next alignment */ + align = + ((pos / GNUNET_FS_DBLOCK_SIZE) + 1) * GNUNET_FS_DBLOCK_SIZE; + if (align == pos) + { + /* if we were already aligned, still skip a block! */ + align += GNUNET_FS_DBLOCK_SIZE; + } + pos = align; + if (pos >= size) + { + /* malformed - or partial download... */ + break; + } + } + epos = pos; + while ((epos < size) && (cdata[epos] != '\0')) + epos++; + if (epos >= size) + return; /* malformed - or partial download */ + + uri = GNUNET_FS_uri_parse (&cdata[pos], &emsg); + pos = epos + 1; + if (uri == NULL) + { + GNUNET_free (emsg); + pos--; /* go back to '\0' to force going to next alignment */ + continue; + } + if (GNUNET_FS_uri_test_ksk (uri)) + { + GNUNET_FS_uri_destroy (uri); + GNUNET_break (0); + return; /* illegal in directory! */ + } + + memcpy (&mdSize, &cdata[pos], sizeof (uint32_t)); + mdSize = ntohl (mdSize); + pos += sizeof (uint32_t); + if (pos + mdSize > size) + { + GNUNET_FS_uri_destroy (uri); + return; /* malformed - or partial download */ + } + + md = GNUNET_CONTAINER_meta_data_deserialize (&cdata[pos], mdSize); + if (md == NULL) + { + GNUNET_FS_uri_destroy (uri); + GNUNET_break (0); + return; /* malformed ! */ + } + pos += mdSize; + /* FIXME: add support for embedded data */ + filename = GNUNET_CONTAINER_meta_data_get_by_type (md, + EXTRACTOR_FILENAME); + if (dep != NULL) + dep (dep_cls, + filename, + uri, + md, + 0, + NULL); + GNUNET_free_non_null (filename); + GNUNET_CONTAINER_meta_data_destroy (md); + GNUNET_FS_uri_destroy (uri); + } +} + +#if 0 + + +/** + * Given the start and end position of a block of + * data, return the end position of that data + * after alignment to the GNUNET_FS_DBLOCK_SIZE. + */ +static uint64_t +do_align (uint64_t start_position, + uint64_t end_position) +{ + uint64_t align; + + align = (end_position / GNUNET_FS_DBLOCK_SIZE) * GNUNET_FS_DBLOCK_SIZE; + if ((start_position < align) && (end_position > align)) + return align + end_position - start_position; + return end_position; +} + + +/** + * Compute a permuation of the blocks to + * minimize the cost of alignment. Greedy packer. + * + * @param start starting position for the first block + * @param count size of the two arrays + * @param sizes the sizes of the individual blocks + * @param perm the permutation of the blocks (updated) + */ +static void +block_align (uint64_t start, + unsigned int count, + const uint64_t *sizes, + unsigned int *perm) +{ + unsigned int i; + unsigned int j; + unsigned int tmp; + unsigned int best; + int64_t badness; + uint64_t cpos; + uint64_t cend; + int64_t cbad; + unsigned int cval; + + cpos = start; + for (i = 0; i < count; i++) + { + start = cpos; + badness = 0x7FFFFFFF; + best = -1; + for (j = i; j < count; j++) + { + cval = perm[j]; + cend = cpos + sizes[cval]; + if (cpos % GNUNET_FS_DBLOCK_SIZE == 0) + { + /* prefer placing the largest blocks first */ + cbad = -(cend % GNUNET_FS_DBLOCK_SIZE); + } + else + { + if (cpos / GNUNET_FS_DBLOCK_SIZE == + cend / GNUNET_FS_DBLOCK_SIZE) + { + /* Data fits into the same block! Prefer small left-overs! */ + cbad = + GNUNET_FS_DBLOCK_SIZE - cend % GNUNET_FS_DBLOCK_SIZE; + } + else + { + /* Would have to waste space to re-align, add big factor, this + case is a real loss (proportional to space wasted)! */ + cbad = + GNUNET_FS_DBLOCK_SIZE * (GNUNET_FS_DBLOCK_SIZE - + cpos % + GNUNET_FS_DBLOCK_SIZE); + } + } + if (cbad < badness) + { + best = j; + badness = cbad; + } + } + tmp = perm[i]; + perm[i] = perm[best]; + perm[best] = tmp; + cpos += sizes[perm[i]]; + cpos = do_align (start, cpos); + } +} + + +/** + * Create a directory. We allow packing more than one variable + * size entry into one block (and an entry could also span more + * than one block), but an entry that is smaller than a single + * block will never cross the block boundary. This is done to + * allow processing entries of a directory already even if the + * download is still partial.

+ * + * The first block begins with the directories MAGIC signature, + * followed by the meta-data about the directory itself.

+ * + * After that, the directory consists of block-aligned pairs + * of URIs (0-terminated strings) and serialized meta-data. + * + * @param data pointer set to the beginning of the directory + * @param len set to number of bytes in data + * @param count number of entries in uris and mds + * @param uris URIs of the files in the directory + * @param mds meta-data for the files (must match + * respective values at same offset in in uris) + * @param mdir meta-data for the directory + * @return GNUNET_OK on success, GNUNET_SYSERR on error + */ +int +GNUNET_FS_directory_create (char **data, + size_t *len, + unsigned int count, + const struct GNUNET_FS_Uri **uris, + const struct GNUNET_CONTAINER_MetaData **mds, + const struct GNUNET_CONTAINER_MetaData *mdir) +{ + unsigned int i; + unsigned int j; + uint64_t psize; + uint64_t size; + uint64_t pos; + char **ucs; + int ret; + uint64_t *sizes; + unsigned int *perm; + + for (i = 0; i < count; i++) + { + if (GNUNET_FS_uri_test_ksk (fis[i].uri)) + { + GNUNET_break (0); + return GNUNET_SYSERR; /* illegal in directory! */ + } + } + ucs = GNUNET_malloc (sizeof (char *) * count); + size = 8 + sizeof (unsigned int); + size += GNUNET_meta_data_get_serialized_size (meta, GNUNET_SERIALIZE_FULL); + sizes = GNUNET_malloc (count * sizeof (unsigned long long)); + perm = GNUNET_malloc (count * sizeof (int)); + for (i = 0; i < count; i++) + { + perm[i] = i; + ucs[i] = GNUNET_FS_uri_to_string (fis[i].uri); + GNUNET_assert (ucs[i] != NULL); + psize = + GNUNET_meta_data_get_serialized_size (fis[i].meta, + GNUNET_SERIALIZE_FULL); + if (psize == -1) + { + GNUNET_break (0); + GNUNET_free (sizes); + GNUNET_free (perm); + while (i >= 0) + GNUNET_free (ucs[i--]); + GNUNET_free (ucs); + return GNUNET_SYSERR; + } + sizes[i] = psize + sizeof (unsigned int) + strlen (ucs[i]) + 1; + } + /* permutate entries to minimize alignment cost */ + block_align (size, count, sizes, perm); + + /* compute final size with alignment */ + for (i = 0; i < count; i++) + { + psize = size; + size += sizes[perm[i]]; + size = do_align (psize, size); + } + *len = size; + *data = GNUNET_malloc (size); + memset (*data, 0, size); + + pos = 8; + memcpy (*data, GNUNET_DIRECTORY_MAGIC, 8); + + ret = GNUNET_CONTAINER_meta_data_serialize (meta, + &(*data)[pos + + sizeof (unsigned int)], + size - pos - sizeof (unsigned int), + GNUNET_SERIALIZE_FULL); + GNUNET_assert (ret != GNUNET_SYSERR); + ret = htonl (ret); + memcpy (&(*data)[pos], &ret, sizeof (unsigned int)); + pos += ntohl (ret) + sizeof (unsigned int); + + for (j = 0; j < count; j++) + { + i = perm[j]; + psize = pos; + pos += sizes[i]; + pos = do_align (psize, pos); + pos -= sizes[i]; /* go back to beginning */ + memcpy (&(*data)[pos], ucs[i], strlen (ucs[i]) + 1); + pos += strlen (ucs[i]) + 1; + GNUNET_free (ucs[i]); + ret = GNUNET_CONTAINER_meta_data_serialize (mds[i], + &(*data)[pos + + sizeof (unsigned int)], + size - pos - + sizeof (unsigned int), + GNUNET_SERIALIZE_FULL); + GNUNET_assert (ret != GNUNET_SYSERR); + ret = htonl (ret); + memcpy (&(*data)[pos], &ret, sizeof (unsigned int)); + pos += ntohl (ret) + sizeof (unsigned int); + } + GNUNET_free (sizes); + GNUNET_free (perm); + GNUNET_free (ucs); + GNUNET_assert (pos == size); + return GNUNET_OK; +} + + +#endif + +/* end of fs_directory.c */ diff --git a/src/fs/test_fs_collection.c b/src/fs/test_fs_collection.c new file mode 100644 index 000000000..421cb5060 --- /dev/null +++ b/src/fs/test_fs_collection.c @@ -0,0 +1,103 @@ +/* + This file is part of GNUnet. + (C) 2006, 2009 Christian Grothoff (and other contributing authors) + + GNUnet is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 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 fs/test_fs_collection.c + * @brief testcase for fs_collection.c + * @author Christian Grothoff + */ + +#include "platform.h" +#include "gnunet_util_lib.h" +#include "gnunet_fs_service.h" + +#define CHECK(a) if (!(a)) { ok = GNUNET_NO; GNUNET_break(0); goto FAILURE; } + +int +main (int argc, char *argv[]) +{ + struct GNUNET_CONFIGURATION_Handle *cfg; + int ok; + struct GNUNET_ClientServerConnection *sock; + struct GNUNET_CONTAINER_MetaData *meta; + struct GNUNET_CONTAINER_MetaData *have; + char *emsg; + struct GNUNET_FS_Uri *uri; + struct GNUNET_CONTAINER_MetaData *md; + struct GNUNET_FS_Handle *fsh; + + GNUNET_CRYPTO_random_disable_entropy_gathering (); + cfg = GNUNET_CONFIGURATION_create (); + if (GNUNET_SYSERR == GNUNET_CONFIGURATION_parse (cfg, "check.conf")) + { + GNUNET_CONFIGURATION_destroy (cfg); + return -1; + } + sock = NULL; + meta = NULL; + ok = GNUNET_YES; + meta = GNUNET_CONTAINER_meta_data_create (); + GNUNET_CONTAINER_meta_data_insert (meta, EXTRACTOR_MIMETYPE, "test/foo"); + + + fsh = GNUNET_FS_start (sched, + cfg, + "test-fs-collection", + &progress_cb, + NULL); + + /* ACTUAL TEST CODE */ + GNUNET_FS_collection_stop (fsh); + CHECK (NULL == GNUNET_FS_collection_get (fsh)); + CHECK (GNUNET_OK == GNUNET_FS_collection_start (fsh, + namespace)); + have = GNUNET_FS_collection_get (fsh); + CHECK (NULL != have); + CHECK (GNUNET_CONTAINER_meta_data_test_equal (have, meta)); + GNUNET_CONTAINER_meta_data_destroy (have); + md = meta; + uri = + GNUNET_FS_uri_parse ("gnunet://ecrs/chk/0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0", &emsg); + GNUNET_FS_collection_add (fsh, uri, md); + GNUNET_FS_uri_destroy (uri); + GNUNET_FS_stop (fsh); + fsh = GNUNET_FS_start (sched, cfg, + "test-fs-collection", + &progress_cb, + NULL); + have = GNUNET_FS_collection_get (fsh); + CHECK (NULL != have); + CHECK (GNUNET_CONTAINER_meta_data_test_equal (have, meta)); + GNUNET_CONTAINER_meta_data_destroy (have); + GNUNET_FS_collection_publish (fsh); + GNUNET_FS_collection_stop (fsh); + CHECK (NULL == GNUNET_FS_collection_get (fsh)); + GNUNET_FS_stop (fsh); + + /* END OF TEST CODE */ +FAILURE: + if (meta != NULL) + GNUNET_CONTAINER_meta_data_destroy (meta); + GNUNET_CONFIGURATION_destroy (cfg); + + return (ok == GNUNET_YES) ? 0 : 1; +} + +/* end of test_fs_collection.c */ diff --git a/src/fs/test_fs_directory.c b/src/fs/test_fs_directory.c new file mode 100644 index 000000000..d643e6ed9 --- /dev/null +++ b/src/fs/test_fs_directory.c @@ -0,0 +1,167 @@ +/* + This file is part of GNUnet. + (C) 2005, 2006, 2009 Christian Grothoff (and other contributing authors) + + GNUnet is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 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 fs/test_fs_directory.c + * @brief Test for fs_directory.c + * @author Christian Grothoff + */ + +#include "platform.h" +#include +#include "gnunet_util_lib.h" +#include "gnunet_fs_service.h" +#include "fs.h" + +#define ABORT() { fprintf(stderr, "Error at %s:%d\n", __FILE__, __LINE__); return 1; } + +struct PCLS +{ + struct GNUNET_FS_Uri **uri; + struct GNUNET_CONTAINER_MetaData **md; + unsigned int pos; + unsigned int max; +}; + +static void +processor (void *cls, + const char *filename, + const struct GNUNET_FS_Uri *uri, + const struct GNUNET_CONTAINER_MetaData *md, + size_t length, + const void *data) +{ + struct PCLS *p = cls; + int i; + + for (i = 0; i < p->max; i++) + { + if (GNUNET_CONTAINER_meta_data_test_equal (p->md[i], + md) && + GNUNET_FS_uri_test_equal (p->uri[i], uri)) + { + p->pos++; + return; + } + } + fprintf (stderr, "Error at %s:%d\n", __FILE__, __LINE__); +} + +static int +testDirectory (unsigned int i) +{ + char *data; + unsigned long long dlen; + struct GNUNET_FS_Uri **uris; + struct GNUNET_CONTAINER_MetaData **mds; + struct GNUNET_CONTAINER_MetaData *meta; + struct PCLS cls; + char *emsg; + int p; + int q; + char uri[512]; + char txt[128]; + int ret = 0; + + cls.max = i; + uris = GNUNET_malloc (sizeof (struct GNUNET_FS_Uri*) * i); + mds = GNUNET_malloc (sizeof (struct GNUNET_CONTAINER_MetaData*) * i); + for (p = 0; p < i; p++) + { + mds[p] = GNUNET_CONTAINER_meta_data_create (); + for (q = 0; q <= p; q++) + { + GNUNET_snprintf (txt, sizeof(txt), "%u -- %u\n", p, q); + GNUNET_CONTAINER_meta_data_insert (mds[p], + q % + EXTRACTOR_getHighestKeywordTypeNumber + (), txt); + } + GNUNET_snprintf (uri, + sizeof(uri), + "gnunet://ecrs/chk/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820.RNVVVVOOLCLK065B5D04HTNVNSIB2AI022RG8200HSLK1CO1000ATQ98824DMA2032LIMG50CG0K057NVUVG200000H000004400000.%u", + p); + uris[p] = GNUNET_FS_uri_parse (uri, &emsg); + if (uris[p] == NULL) + { + GNUNET_CONTAINER_meta_data_destroy (mds[p]); + while (--p > 0) + { + GNUNET_CONTAINER_meta_data_destroy (mds[p]); + GNUNET_FS_uri_destroy (uris[p]); + } + GNUNET_free (mds); + GNUNET_free (uris); + ABORT (); /* error in testcase */ + } + } + meta = GNUNET_CONTAINER_meta_data_create (); + GNUNET_CONTAINER_meta_data_insert (meta, EXTRACTOR_TITLE, "A title"); + GNUNET_CONTAINER_meta_data_insert (meta, EXTRACTOR_AUTHOR, "An author"); + if (GNUNET_OK != + GNUNET_FS_directory_create (&dlen, &data, i, uris, mds, meta)) + { + GNUNET_CONTAINER_meta_data_destroy (meta); + for (p = 0; p < i; p++) + { + GNUNET_CONTAINER_meta_data_destroy (mds[p]); + GNUNET_FS_uri_destroy (uris[p]); + } + GNUNET_free (uris); + GNUNET_free (mds); + ABORT (); + } + cls.pos = 0; + cls.uri = uris; + cls.md = mds; + GNUNET_FS_directory_list_contents (dlen, data, 0, + &processor, &cls); + GNUNET_assert (cls.pos == i); + GNUNET_free (data); + GNUNET_CONTAINER_meta_data_destroy (meta); + for (p = 0; p < i; p++) + { + GNUNET_CONTAINER_meta_data_destroy (mds[p]); + GNUNET_FS_uri_destroy (uris[p]); + } + GNUNET_free (uris); + GNUNET_free (mds); + return ret; +} + +int +main (int argc, char *argv[]) +{ + int failureCount = 0; + int i; + + for (i = 17; i < 2000; i *= 2) + { + fprintf (stderr, "."); + failureCount += testDirectory (i); + } + fprintf (stderr, "\n"); + + if (failureCount != 0) + return 1; + return 0; +} + +/* end of test_fs_directory.c */ diff --git a/src/fs/test_fs_uri.c b/src/fs/test_fs_uri.c index f07ba4179..6da56a742 100644 --- a/src/fs/test_fs_uri.c +++ b/src/fs/test_fs_uri.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - (C) 2003, 2004, 2006, 2007 Christian Grothoff (and other contributing authors) + (C) 2003, 2004, 2006, 2007, 2009 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published @@ -35,104 +35,110 @@ static int testKeyword () { char *uri; - struct GNUNET_ECRS_URI *ret; + struct GNUNET_FS_Uri *ret; + char *emsg; - if (NULL != GNUNET_ECRS_string_to_uri (NULL, "gnunet://ecrs/ksk/++")) + if (NULL != GNUNET_FS_uri_parse ("gnunet://ecrs/ksk/++", &emsg)) ABORT (); - ret = GNUNET_ECRS_string_to_uri (NULL, "gnunet://ecrs/ksk/foo+bar"); + GNUNET_free (emsg); + ret = GNUNET_FS_uri_parse ("gnunet://ecrs/ksk/foo+bar", &emsg); if (ret == NULL) ABORT (); - if (!GNUNET_ECRS_uri_test_ksk (ret)) + if (!GNUNET_FS_uri_test_ksk (ret)) { - GNUNET_ECRS_uri_destroy (ret); + GNUNET_FS_uri_destroy (ret); ABORT (); } if ((2 != ret->data.ksk.keywordCount) || (0 != strcmp (" foo", ret->data.ksk.keywords[0])) || (0 != strcmp (" bar", ret->data.ksk.keywords[1]))) { - GNUNET_ECRS_uri_destroy (ret); + GNUNET_FS_uri_destroy (ret); ABORT (); } - uri = GNUNET_ECRS_uri_to_string (ret); + uri = GNUNET_FS_uri_to_string (ret); if (0 != strcmp (uri, "gnunet://ecrs/ksk/foo+bar")) { GNUNET_free (uri); - GNUNET_ECRS_uri_destroy (ret); + GNUNET_FS_uri_destroy (ret); ABORT (); } GNUNET_free (uri); - GNUNET_ECRS_uri_destroy (ret); + GNUNET_FS_uri_destroy (ret); return 0; } static int testLocation () { - struct GNUNET_ECRS_URI *uri; + struct GNUNET_FS_Uri *uri; char *uric; - struct GNUNET_ECRS_URI *uri2; - GNUNET_RSA_PublicKey pk; - struct GNUNET_RSA_PrivateKey *hk; - struct GNUNET_ECRS_URI *baseURI; + struct GNUNET_FS_Uri *uri2; + struct GNUNET_FS_Uri *baseURI; + char *emsg; + struct GNUNET_CONFIGURATION_Handle *cfg; baseURI = - GNUNET_ECRS_string_to_uri (NULL, - "gnunet://ecrs/chk/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820.RNVVVVOOLCLK065B5D04HTNVNSIB2AI022RG8200HSLK1CO1000ATQ98824DMA2032LIMG50CG0K057NVUVG200000H000004400000.42"); - hk = GNUNET_RSA_create_key (); - GNUNET_RSA_get_public_key (hk, &pk); - uri = GNUNET_ECRS_location_to_uri (baseURI, - &pk, 43, - (GNUNET_ECRS_SignFunction) & - GNUNET_RSA_sign, hk); - GNUNET_RSA_free_key (hk); + GNUNET_FS_uri_parse ("gnunet://ecrs/chk/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820.RNVVVVOOLCLK065B5D04HTNVNSIB2AI022RG8200HSLK1CO1000ATQ98824DMA2032LIMG50CG0K057NVUVG200000H000004400000.42", &emsg); + GNUNET_assert (baseURI != NULL); + cfg = GNUNET_CONFIGURATION_create (); + if (GNUNET_OK != + GNUNET_CONFIGURATION_parse (cfg, "test_fs_uri_data.conf")) + { + fprintf (stderr, "Failed to parse configuration file\n"); + GNUNET_CONFIGURATION_destroy (cfg); + return 1; + } + uri = GNUNET_FS_uri_loc_create (baseURI, + cfg, + GNUNET_TIME_absolute_get ()); if (uri == NULL) { - GNUNET_GE_BREAK (NULL, 0); - GNUNET_ECRS_uri_destroy (baseURI); + GNUNET_break (0); + GNUNET_FS_uri_destroy (baseURI); return 1; } - if (!GNUNET_ECRS_uri_test_loc (uri)) + if (!GNUNET_FS_uri_test_loc (uri)) { - GNUNET_GE_BREAK (NULL, 0); - GNUNET_ECRS_uri_destroy (uri); - GNUNET_ECRS_uri_destroy (baseURI); + GNUNET_break (0); + GNUNET_FS_uri_destroy (uri); + GNUNET_FS_uri_destroy (baseURI); return 1; } - uri2 = GNUNET_ECRS_uri_get_content_uri_from_loc (uri); - if (!GNUNET_ECRS_uri_test_equal (baseURI, uri2)) + uri2 = GNUNET_FS_uri_loc_get_uri (uri); + if (!GNUNET_FS_uri_test_equal (baseURI, uri2)) { - GNUNET_GE_BREAK (NULL, 0); - GNUNET_ECRS_uri_destroy (uri); - GNUNET_ECRS_uri_destroy (uri2); - GNUNET_ECRS_uri_destroy (baseURI); + GNUNET_break (0); + GNUNET_FS_uri_destroy (uri); + GNUNET_FS_uri_destroy (uri2); + GNUNET_FS_uri_destroy (baseURI); return 1; } - GNUNET_ECRS_uri_destroy (uri2); - GNUNET_ECRS_uri_destroy (baseURI); - uric = GNUNET_ECRS_uri_to_string (uri); + GNUNET_FS_uri_destroy (uri2); + GNUNET_FS_uri_destroy (baseURI); + uric = GNUNET_FS_uri_to_string (uri); #if 0 /* not for the faint of heart: */ printf ("URI: `%s'\n", uric); #endif - uri2 = GNUNET_ECRS_string_to_uri (NULL, uric); + uri2 = GNUNET_FS_uri_parse (uric, &emsg); GNUNET_free (uric); if (uri2 == NULL) { - GNUNET_GE_BREAK (NULL, 0); - GNUNET_ECRS_uri_destroy (uri); + GNUNET_break (0); + GNUNET_FS_uri_destroy (uri); return 1; } - if (GNUNET_YES != GNUNET_ECRS_uri_test_equal (uri, uri2)) + if (GNUNET_YES != GNUNET_FS_uri_test_equal (uri, uri2)) { - GNUNET_GE_BREAK (NULL, 0); - GNUNET_ECRS_uri_destroy (uri); - GNUNET_ECRS_uri_destroy (uri2); + GNUNET_break (0); + GNUNET_FS_uri_destroy (uri); + GNUNET_FS_uri_destroy (uri2); return 1; } - GNUNET_ECRS_uri_destroy (uri2); - GNUNET_ECRS_uri_destroy (uri); + GNUNET_FS_uri_destroy (uri2); + GNUNET_FS_uri_destroy (uri); return 0; } @@ -140,44 +146,42 @@ static int testNamespace (int i) { char *uri; - struct GNUNET_ECRS_URI *ret; + struct GNUNET_FS_Uri *ret; + char *emsg; if (NULL != - GNUNET_ECRS_string_to_uri (NULL, - "gnunet://ecrs/sks/D1KJS9H2A82Q65VKQ0ML3RFU6U1D3VUK")) + GNUNET_FS_uri_parse ("gnunet://ecrs/sks/D1KJS9H2A82Q65VKQ0ML3RFU6U1D3VUK", &emsg)) ABORT (); if (NULL != - GNUNET_ECRS_string_to_uri (NULL, - "gnunet://ecrs/sks/D1KJS9H2A82Q65VKQ0ML3RFU6U1D3V/test")) + GNUNET_FS_uri_parse ("gnunet://ecrs/sks/D1KJS9H2A82Q65VKQ0ML3RFU6U1D3V/test", &emsg)) ABORT (); - if (NULL != GNUNET_ECRS_string_to_uri (NULL, "gnunet://ecrs/sks/test")) + if (NULL != GNUNET_FS_uri_parse ("gnunet://ecrs/sks/test", &emsg)) ABORT (); ret = - GNUNET_ECRS_string_to_uri (NULL, - "gnunet://ecrs/sks/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820/test"); + GNUNET_FS_uri_parse ("gnunet://ecrs/sks/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820/test", &emsg); if (ret == NULL) ABORT (); - if (GNUNET_ECRS_uri_test_ksk (ret)) + if (GNUNET_FS_uri_test_ksk (ret)) { - GNUNET_ECRS_uri_destroy (ret); + GNUNET_FS_uri_destroy (ret); ABORT (); } - if (!GNUNET_ECRS_uri_test_sks (ret)) + if (!GNUNET_FS_uri_test_sks (ret)) { - GNUNET_ECRS_uri_destroy (ret); + GNUNET_FS_uri_destroy (ret); ABORT (); } - uri = GNUNET_ECRS_uri_to_string (ret); + uri = GNUNET_FS_uri_to_string (ret); if (0 != strcmp (uri, "gnunet://ecrs/sks/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820/test")) { - GNUNET_ECRS_uri_destroy (ret); + GNUNET_FS_uri_destroy (ret); GNUNET_free (uri); ABORT (); } GNUNET_free (uri); - GNUNET_ECRS_uri_destroy (ret); + GNUNET_FS_uri_destroy (ret); return 0; } @@ -185,51 +189,51 @@ static int testFile (int i) { char *uri; - struct GNUNET_ECRS_URI *ret; + struct GNUNET_FS_Uri *ret; + char *emsg; if (NULL != - GNUNET_ECRS_string_to_uri (NULL, - "gnunet://ecrs/chk/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820.RNVVVVOOLCLK065B5D04HTNVNSIB2AI022RG8200HSLK1CO1000ATQ98824DMA2032LIMG50CG0K057NVUVG200000H00000440000.42")) + GNUNET_FS_uri_parse ("gnunet://ecrs/chk/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820.RNVVVVOOLCLK065B5D04HTNVNSIB2AI022RG8200HSLK1CO1000ATQ98824DMA2032LIMG50CG0K057NVUVG200000H00000440000.42", &emsg)) ABORT (); + GNUNET_free (emsg); if (NULL != - GNUNET_ECRS_string_to_uri (NULL, - "gnunet://ecrs/chk/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820.RNVVVVOOLCLK065B5D04HTNVNSIB2AI022RG8200HSLK1CO1000ATQ98824DMA2032LIMG50CG0K057NVUVG200000H000004400000")) + GNUNET_FS_uri_parse ("gnunet://ecrs/chk/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820.RNVVVVOOLCLK065B5D04HTNVNSIB2AI022RG8200HSLK1CO1000ATQ98824DMA2032LIMG50CG0K057NVUVG200000H000004400000", &emsg)) ABORT (); + GNUNET_free (emsg); if (NULL != - GNUNET_ECRS_string_to_uri (NULL, - "gnunet://ecrs/chk/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820.RNVVVVOOLCLK065B5D04HTNVNSIB2AI022RG8200HSLK1CO1000ATQ98824DMA2032LIMG50CG0K057NVUVG200000H000004400000.FGH")) + GNUNET_FS_uri_parse ("gnunet://ecrs/chk/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820.RNVVVVOOLCLK065B5D04HTNVNSIB2AI022RG8200HSLK1CO1000ATQ98824DMA2032LIMG50CG0K057NVUVG200000H000004400000.FGH", &emsg)) ABORT (); + GNUNET_free (emsg); ret = - GNUNET_ECRS_string_to_uri (NULL, - "gnunet://ecrs/chk/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820.RNVVVVOOLCLK065B5D04HTNVNSIB2AI022RG8200HSLK1CO1000ATQ98824DMA2032LIMG50CG0K057NVUVG200000H000004400000.42"); + GNUNET_FS_uri_parse ("gnunet://ecrs/chk/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820.RNVVVVOOLCLK065B5D04HTNVNSIB2AI022RG8200HSLK1CO1000ATQ98824DMA2032LIMG50CG0K057NVUVG200000H000004400000.42", &emsg); if (ret == NULL) ABORT (); - if (GNUNET_ECRS_uri_test_ksk (ret)) + if (GNUNET_FS_uri_test_ksk (ret)) { - GNUNET_ECRS_uri_destroy (ret); + GNUNET_FS_uri_destroy (ret); ABORT (); } - if (GNUNET_ECRS_uri_test_sks (ret)) + if (GNUNET_FS_uri_test_sks (ret)) { - GNUNET_ECRS_uri_destroy (ret); + GNUNET_FS_uri_destroy (ret); ABORT (); } - if (GNUNET_ntohll (ret->data.fi.file_length) != 42) + if (GNUNET_ntohll (ret->data.chk.file_length) != 42) { - GNUNET_ECRS_uri_destroy (ret); + GNUNET_FS_uri_destroy (ret); ABORT (); } - uri = GNUNET_ECRS_uri_to_string (ret); + uri = GNUNET_FS_uri_to_string (ret); if (0 != strcmp (uri, "gnunet://ecrs/chk/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820.RNVVVVOOLCLK065B5D04HTNVNSIB2AI022RG8200HSLK1CO1000ATQ98824DMA2032LIMG50CG0K057NVUVG200000H000004400000.42")) { GNUNET_free (uri); - GNUNET_ECRS_uri_destroy (ret); + GNUNET_FS_uri_destroy (ret); ABORT (); } GNUNET_free (uri); - GNUNET_ECRS_uri_destroy (ret); + GNUNET_FS_uri_destroy (ret); return 0; } @@ -239,7 +243,7 @@ main (int argc, char *argv[]) int failureCount = 0; int i; - GNUNET_disable_entropy_gathering (); + GNUNET_CRYPTO_random_disable_entropy_gathering (); failureCount += testKeyword (); failureCount += testLocation (); for (i = 0; i < 255; i++) @@ -252,4 +256,4 @@ main (int argc, char *argv[]) return 0; } -/* end of uritest.c */ +/* end of test_fs_uri.c */ diff --git a/src/fs/test_fs_uri_data.conf b/src/fs/test_fs_uri_data.conf new file mode 100644 index 000000000..12cf53b93 --- /dev/null +++ b/src/fs/test_fs_uri_data.conf @@ -0,0 +1,9 @@ +[PATHS] +SERVICEHOME = /tmp/gnunet-test-fs-uri/ +DEFAULTCONFIG = /etc/gnunetd.conf + +[gnunetd] +HOSTKEY = $SERVICEHOME/.hostkey + +[TESTING] +WEAKRANDOM = YES -- cgit v1.2.3