gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gnunet] branch master updated (338be6576 -> 09f221a81)


From: gnunet
Subject: [gnunet] branch master updated (338be6576 -> 09f221a81)
Date: Tue, 19 May 2020 02:47:04 +0200

This is an automated email from the git hooks/post-receive script.

grothoff pushed a change to branch master
in repository gnunet.

    from 338be6576 pow values should be nbo
     new 6a52ce5f9 fix ftbfs
     new f4771fcc1 Improved BIO API
     new 09f221a81 missing termination

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 src/fs/fs_api.c                                    |  448 ++++---
 src/fs/fs_namespace.c                              |   39 +-
 src/fs/gnunet-auto-share.c                         |   32 +-
 src/fs/gnunet-service-fs_indexing.c                |   11 +-
 src/hostlist/gnunet-daemon-hostlist_client.c       |   43 +-
 src/include/gnunet_bio_lib.h                       |  559 +++++++--
 src/include/gnunet_buffer_lib.h                    |   13 +
 src/nse/gnunet-service-nse.c                       |    6 +-
 src/statistics/gnunet-service-statistics.c         |   10 +-
 src/testbed-logger/gnunet-service-testbed-logger.c |    5 +-
 src/testbed/gnunet-service-testbed_cpustatus.c     |    6 +-
 src/util/bio.c                                     | 1219 +++++++++++++++++---
 src/util/buffer.c                                  |   23 +-
 src/util/perf_crypto_asymmetric.c                  |   18 +-
 src/util/test_bio.c                                |  601 +++++-----
 15 files changed, 2289 insertions(+), 744 deletions(-)

diff --git a/src/fs/fs_api.c b/src/fs/fs_api.c
index e04a93f9c..3d2ba3e99 100644
--- a/src/fs/fs_api.c
+++ b/src/fs/fs_api.c
@@ -676,7 +676,7 @@ get_read_handle (struct GNUNET_FS_Handle *h, const char 
*ext, const char *ent)
   fn = get_serialization_file_name (h, ext, ent);
   if (NULL == fn)
     return NULL;
-  ret = GNUNET_BIO_read_open (fn);
+  ret = GNUNET_BIO_read_open_file (fn);
   GNUNET_free (fn);
   return ret;
 }
@@ -699,7 +699,7 @@ get_write_handle (struct GNUNET_FS_Handle *h, const char 
*ext, const char *ent)
   fn = get_serialization_file_name (h, ext, ent);
   if (NULL == fn)
     return NULL;
-  ret = GNUNET_BIO_write_open (fn);
+  ret = GNUNET_BIO_write_open_file (fn);
   GNUNET_break (NULL != ret);
   GNUNET_free (fn);
   return ret;
@@ -727,7 +727,7 @@ get_write_handle_in_dir (struct GNUNET_FS_Handle *h,
   fn = get_serialization_file_name_in_dir (h, ext, uni, ent);
   if (NULL == fn)
     return NULL;
-  ret = GNUNET_BIO_write_open (fn);
+  ret = GNUNET_BIO_write_open_file (fn);
   GNUNET_free (fn);
   return ret;
 }
@@ -839,7 +839,7 @@ write_start_time (struct GNUNET_BIO_WriteHandle *wh,
   struct GNUNET_TIME_Relative dur;
 
   dur = GNUNET_TIME_absolute_get_duration (timestamp);
-  return GNUNET_BIO_write_int64 (wh, dur.rel_value_us);
+  return GNUNET_BIO_write_int64 (wh, "start time", dur.rel_value_us);
 }
 
 
@@ -863,7 +863,8 @@ read_start_time (struct GNUNET_BIO_ReadHandle *rh,
 {
   struct GNUNET_TIME_Relative dur;
 
-  if (GNUNET_OK != GNUNET_BIO_read_int64 (rh, &dur.rel_value_us))
+  if (GNUNET_OK != GNUNET_BIO_read_int64 (rh, "start time",
+                                          (int64_t *) &dur.rel_value_us))
     return GNUNET_SYSERR;
   *timestamp = GNUNET_TIME_absolute_subtract (GNUNET_TIME_absolute_get (), 
dur);
   return GNUNET_OK;
@@ -937,10 +938,22 @@ deserialize_fi_node (struct GNUNET_FS_Handle *h,
       (GNUNET_OK !=
        GNUNET_BIO_read_string (rh, "fn", &ret->filename, 16 * 1024)) ||
       (GNUNET_OK !=
-       GNUNET_BIO_read_int64 (rh, &ret->bo.expiration_time.abs_value_us)) ||
-      (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &ret->bo.anonymity_level)) ||
-      (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &ret->bo.content_priority)) ||
-      (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &ret->bo.replication_level)))
+       GNUNET_BIO_read_int64 (
+         rh,
+         "expiration time",
+         (int64_t *) &ret->bo.expiration_time.abs_value_us)) ||
+      (GNUNET_OK != GNUNET_BIO_read_int32 (
+         rh,
+         "anonymity level",
+         (int32_t *) &ret->bo.anonymity_level)) ||
+      (GNUNET_OK != GNUNET_BIO_read_int32 (
+         rh,
+         "content priority",
+         (int32_t *) &ret->bo.content_priority)) ||
+      (GNUNET_OK != GNUNET_BIO_read_int32 (
+         rh,
+         "replication level",
+         (int32_t *) &ret->bo.replication_level)))
   {
     GNUNET_break (0);
     goto cleanup;
@@ -948,7 +961,10 @@ deserialize_fi_node (struct GNUNET_FS_Handle *h,
   switch (b)
   {
   case 0:   /* file-insert */
-    if (GNUNET_OK != GNUNET_BIO_read_int64 (rh, &ret->data.file.file_size))
+    if (GNUNET_OK != GNUNET_BIO_read_int64 (
+          rh,
+          "file size",
+          (int64_t *) &ret->data.file.file_size))
     {
       GNUNET_break (0);
       goto cleanup;
@@ -990,7 +1006,10 @@ deserialize_fi_node (struct GNUNET_FS_Handle *h,
       GNUNET_break (0);
       goto cleanup;
     }
-    if (GNUNET_OK != GNUNET_BIO_read_int64 (rh, &ret->data.file.file_size))
+    if (GNUNET_OK != GNUNET_BIO_read_int64 (
+          rh,
+          "file size",
+          (int64_t *) &ret->data.file.file_size))
     {
       GNUNET_break (0);
       goto cleanup;
@@ -1010,7 +1029,10 @@ deserialize_fi_node (struct GNUNET_FS_Handle *h,
       GNUNET_break (0);
       goto cleanup;
     }
-    if ((GNUNET_OK != GNUNET_BIO_read_int64 (rh, &ret->data.file.file_size)) ||
+    if ((GNUNET_OK != GNUNET_BIO_read_int64 (
+           rh,
+           "file size",
+           (int64_t *) &ret->data.file.file_size)) ||
         (GNUNET_OK != GNUNET_BIO_read (rh,
                                        "fileid",
                                        &ret->data.file.file_id,
@@ -1034,7 +1056,10 @@ deserialize_fi_node (struct GNUNET_FS_Handle *h,
       GNUNET_break (0);
       goto cleanup;
     }
-    if ((GNUNET_OK != GNUNET_BIO_read_int64 (rh, &ret->data.file.file_size)) ||
+    if ((GNUNET_OK != GNUNET_BIO_read_int64 (
+           rh,
+           "file size",
+           (int64_t *) &ret->data.file.file_size)) ||
         (GNUNET_OK != GNUNET_BIO_read (rh,
                                        "fileid",
                                        &ret->data.file.file_id,
@@ -1054,11 +1079,18 @@ deserialize_fi_node (struct GNUNET_FS_Handle *h,
 
   case 4:   /* directory */
     ret->is_directory = GNUNET_YES;
-    if ((GNUNET_OK != GNUNET_BIO_read_int32 (rh, &dsize)) ||
+    if ((GNUNET_OK != GNUNET_BIO_read_int32 (rh, "dsize",
+                                             (int32_t *) &dsize)) ||
         (GNUNET_OK !=
-         GNUNET_BIO_read_int64 (rh, &ret->data.dir.contents_completed)) ||
+         GNUNET_BIO_read_int64 (
+           rh,
+           "contents completed",
+           (int64_t *) &ret->data.dir.contents_completed)) ||
         (GNUNET_OK !=
-         GNUNET_BIO_read_int64 (rh, &ret->data.dir.contents_size)) ||
+         GNUNET_BIO_read_int64 (
+           rh,
+           "contents size",
+           (int64_t *) &ret->data.dir.contents_size)) ||
         (NULL == (ret->data.dir.dir_data = GNUNET_malloc_large (dsize))) ||
         (GNUNET_OK !=
          GNUNET_BIO_read (rh, "dir-data", ret->data.dir.dir_data, dsize)) ||
@@ -1294,7 +1326,7 @@ copy_from_reader (struct GNUNET_BIO_WriteHandle *wh,
       GNUNET_free (emsg);
       return GNUNET_SYSERR;
     }
-    if (GNUNET_OK != GNUNET_BIO_write (wh, buf, ret))
+    if (GNUNET_OK != GNUNET_BIO_write (wh, "copied from reader", buf, ret))
       return GNUNET_SYSERR;
     off += ret;
   }
@@ -1353,19 +1385,34 @@ GNUNET_FS_file_information_sync_ (struct 
GNUNET_FS_FileInformation *fi)
     skss = GNUNET_FS_uri_to_string (fi->sks_uri);
   else
     skss = NULL;
-  if ((GNUNET_OK != GNUNET_BIO_write (wh, &b, sizeof(b))) ||
-      (GNUNET_OK != GNUNET_BIO_write_meta_data (wh, fi->meta)) ||
-      (GNUNET_OK != GNUNET_BIO_write_string (wh, ksks)) ||
-      (GNUNET_OK != GNUNET_BIO_write_string (wh, chks)) ||
-      (GNUNET_OK != GNUNET_BIO_write_string (wh, skss)) ||
+  struct GNUNET_BIO_WriteSpec ws1[] = {
+    GNUNET_BIO_write_spec_object ("b", &b, sizeof (b)),
+    GNUNET_BIO_write_spec_meta_data ("meta", fi->meta),
+    GNUNET_BIO_write_spec_string ("ksks", ksks),
+    GNUNET_BIO_write_spec_string ("chks", chks),
+    GNUNET_BIO_write_spec_string ("skss", skss),
+    GNUNET_BIO_write_spec_end (),
+  };
+  struct GNUNET_BIO_WriteSpec ws2[] = {
+    GNUNET_BIO_write_spec_string ("emsg", fi->emsg),
+    GNUNET_BIO_write_spec_string ("filename", fi->filename),
+    GNUNET_BIO_write_spec_int64 (
+      "expiration time",
+      (int64_t *) &fi->bo.expiration_time.abs_value_us),
+    GNUNET_BIO_write_spec_int32 (
+      "anonymity level",
+      (int32_t *) &fi->bo.anonymity_level),
+    GNUNET_BIO_write_spec_int32 (
+      "content priority",
+      (int32_t *) &fi->bo.content_priority),
+    GNUNET_BIO_write_spec_int32 (
+      "replication level",
+      (int32_t *) &fi->bo.replication_level),
+    GNUNET_BIO_write_spec_end (),
+  };
+  if ((GNUNET_OK != GNUNET_BIO_write_spec_commit (wh, ws1)) ||
       (GNUNET_OK != write_start_time (wh, fi->start_time)) ||
-      (GNUNET_OK != GNUNET_BIO_write_string (wh, fi->emsg)) ||
-      (GNUNET_OK != GNUNET_BIO_write_string (wh, fi->filename)) ||
-      (GNUNET_OK !=
-       GNUNET_BIO_write_int64 (wh, fi->bo.expiration_time.abs_value_us)) ||
-      (GNUNET_OK != GNUNET_BIO_write_int32 (wh, fi->bo.anonymity_level)) ||
-      (GNUNET_OK != GNUNET_BIO_write_int32 (wh, fi->bo.content_priority)) ||
-      (GNUNET_OK != GNUNET_BIO_write_int32 (wh, fi->bo.replication_level)))
+      (GNUNET_OK != GNUNET_BIO_write_spec_commit (wh, ws2)))
   {
     GNUNET_break (0);
     goto cleanup;
@@ -1380,7 +1427,8 @@ GNUNET_FS_file_information_sync_ (struct 
GNUNET_FS_FileInformation *fi)
   switch (b)
   {
   case 0:   /* file-insert */
-    if (GNUNET_OK != GNUNET_BIO_write_int64 (wh, fi->data.file.file_size))
+    if (GNUNET_OK != GNUNET_BIO_write_int64 (wh, "file size",
+                                             fi->data.file.file_size))
     {
       GNUNET_break (0);
       goto cleanup;
@@ -1399,7 +1447,8 @@ GNUNET_FS_file_information_sync_ (struct 
GNUNET_FS_FileInformation *fi)
       GNUNET_break (0);
       goto cleanup;
     }
-    if (GNUNET_OK != GNUNET_BIO_write_int64 (wh, fi->data.file.file_size))
+    if (GNUNET_OK != GNUNET_BIO_write_int64 (wh, "file size",
+                                             fi->data.file.file_size))
     {
       GNUNET_break (0);
       goto cleanup;
@@ -1413,8 +1462,10 @@ GNUNET_FS_file_information_sync_ (struct 
GNUNET_FS_FileInformation *fi)
       GNUNET_break (0);
       goto cleanup;
     }
-    if ((GNUNET_OK != GNUNET_BIO_write_int64 (wh, fi->data.file.file_size)) ||
+    if ((GNUNET_OK != GNUNET_BIO_write_int64 (wh, "file size",
+                                              fi->data.file.file_size)) ||
         (GNUNET_OK != GNUNET_BIO_write (wh,
+                                        "file id",
                                         &fi->data.file.file_id,
                                         sizeof(struct GNUNET_HashCode))))
     {
@@ -1427,19 +1478,24 @@ GNUNET_FS_file_information_sync_ (struct 
GNUNET_FS_FileInformation *fi)
     if ((NULL != fi->data.dir.entries) &&
         (NULL == fi->data.dir.entries->serialization))
       GNUNET_FS_file_information_sync_ (fi->data.dir.entries);
-    if ((GNUNET_OK != GNUNET_BIO_write_int32 (wh, fi->data.dir.dir_size)) ||
-        (GNUNET_OK !=
-         GNUNET_BIO_write_int64 (wh, fi->data.dir.contents_completed)) ||
-        (GNUNET_OK !=
-         GNUNET_BIO_write_int64 (wh, fi->data.dir.contents_size)) ||
-        (GNUNET_OK != GNUNET_BIO_write (wh,
-                                        fi->data.dir.dir_data,
-                                        (uint32_t) fi->data.dir.dir_size)) ||
-        (GNUNET_OK !=
-         GNUNET_BIO_write_string (wh,
-                                  (fi->data.dir.entries == NULL)
-                                  ? NULL
-                                  : fi->data.dir.entries->serialization)))
+    struct GNUNET_BIO_WriteSpec ws[] = {
+      GNUNET_BIO_write_spec_int32 ("dir size",
+                                   (int32_t *) &fi->data.dir.dir_size),
+      GNUNET_BIO_write_spec_int64 (
+        "contents completed",
+        (int64_t *) &fi->data.dir.contents_completed),
+      GNUNET_BIO_write_spec_int64 ("contents size",
+                                   (int64_t *) &fi->data.dir.contents_size),
+      GNUNET_BIO_write_spec_object ("dir data",
+                                    fi->data.dir.dir_data,
+                                    (uint32_t) fi->data.dir.dir_size),
+      GNUNET_BIO_write_spec_string ("dir entries",
+                                    (fi->data.dir.entries == NULL)
+                                    ? NULL
+                                    : fi->data.dir.entries->serialization),
+      GNUNET_BIO_write_spec_end (),
+    };
+    if ((GNUNET_OK != GNUNET_BIO_write_spec_commit (wh, ws)))
     {
       GNUNET_break (0);
       goto cleanup;
@@ -1453,6 +1509,7 @@ GNUNET_FS_file_information_sync_ (struct 
GNUNET_FS_FileInformation *fi)
   if ((NULL != fi->next) && (NULL == fi->next->serialization))
     GNUNET_FS_file_information_sync_ (fi->next);
   if (GNUNET_OK != GNUNET_BIO_write_string (wh,
+                                            "serialization",
                                             (fi->next != NULL)
                                             ? fi->next->serialization
                                             : NULL))
@@ -1460,7 +1517,7 @@ GNUNET_FS_file_information_sync_ (struct 
GNUNET_FS_FileInformation *fi)
     GNUNET_break (0);
     goto cleanup;
   }
-  if (GNUNET_OK != GNUNET_BIO_write_close (wh))
+  if (GNUNET_OK != GNUNET_BIO_write_close (wh, NULL))
   {
     wh = NULL;
     GNUNET_break (0);
@@ -1469,7 +1526,7 @@ GNUNET_FS_file_information_sync_ (struct 
GNUNET_FS_FileInformation *fi)
   return; /* done! */
 cleanup:
   if (NULL != wh)
-    (void) GNUNET_BIO_write_close (wh);
+    (void) GNUNET_BIO_write_close (wh, NULL);
   GNUNET_free_non_null (chks);
   GNUNET_free_non_null (ksks);
   GNUNET_free_non_null (skss);
@@ -1586,23 +1643,23 @@ deserialize_publish_file (void *cls, const char 
*filename)
   pc->serialization = get_serialization_short_name (filename);
   fi_root = NULL;
   fi_pos = NULL;
-  rh = GNUNET_BIO_read_open (filename);
+  rh = GNUNET_BIO_read_open_file (filename);
   if (NULL == rh)
   {
     GNUNET_break (0);
     goto cleanup;
   }
-  if ((GNUNET_OK !=
-       GNUNET_BIO_read_string (rh, "publish-nid", &pc->nid, 1024)) ||
-      (GNUNET_OK !=
-       GNUNET_BIO_read_string (rh, "publish-nuid", &pc->nuid, 1024)) ||
-      (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &options)) ||
-      (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &all_done)) ||
-      (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &have_ns)) ||
-      (GNUNET_OK !=
-       GNUNET_BIO_read_string (rh, "publish-firoot", &fi_root, 128)) ||
-      (GNUNET_OK !=
-       GNUNET_BIO_read_string (rh, "publish-fipos", &fi_pos, 128)) ||
+  struct GNUNET_BIO_ReadSpec rs[] = {
+    GNUNET_BIO_read_spec_string ("publish-nid", &pc->nid, 1024),
+    GNUNET_BIO_read_spec_string ("publish-nuid", &pc->nuid, 1024),
+    GNUNET_BIO_read_spec_int32 ("options", &options),
+    GNUNET_BIO_read_spec_int32 ("all done", &all_done),
+    GNUNET_BIO_read_spec_int32 ("have ns", &have_ns),
+    GNUNET_BIO_read_spec_string ("publish-firoot", &fi_root, 128),
+    GNUNET_BIO_read_spec_string ("publish-fipos", &fi_pos, 128),
+    GNUNET_BIO_read_spec_end (),
+  };
+  if ((GNUNET_OK != GNUNET_BIO_read_spec_commit (rh, rs)) ||
       ((GNUNET_YES == have_ns) &&
        (GNUNET_OK != GNUNET_BIO_read (rh, "publish-ns", &ns, sizeof(ns)))))
   {
@@ -1729,26 +1786,30 @@ GNUNET_FS_publish_sync_ (struct 
GNUNET_FS_PublishContext *pc)
     goto cleanup;
   }
   have_ns = (NULL != pc->ns) ? GNUNET_YES : GNUNET_NO;
-  if ((GNUNET_OK != GNUNET_BIO_write_string (wh, pc->nid)) ||
-      (GNUNET_OK != GNUNET_BIO_write_string (wh, pc->nuid)) ||
-      (GNUNET_OK != GNUNET_BIO_write_int32 (wh, pc->options)) ||
-      (GNUNET_OK != GNUNET_BIO_write_int32 (wh, pc->all_done)) ||
-      (GNUNET_OK != GNUNET_BIO_write_int32 (wh, have_ns)) ||
-      (GNUNET_OK != GNUNET_BIO_write_string (wh, pc->fi->serialization)) ||
-      (GNUNET_OK != GNUNET_BIO_write_string (wh,
-                                             (NULL == pc->fi_pos)
-                                             ? NULL
-                                             : pc->fi_pos->serialization)) ||
+  struct GNUNET_BIO_WriteSpec ws[] = {
+    GNUNET_BIO_write_spec_string ("nid", pc->nid),
+    GNUNET_BIO_write_spec_string ("nuid", pc->nuid),
+    GNUNET_BIO_write_spec_int32 ("options", (int32_t *) &pc->options),
+    GNUNET_BIO_write_spec_int32 ("all done", &pc->all_done),
+    GNUNET_BIO_write_spec_int32 ("have ns", &have_ns),
+    GNUNET_BIO_write_spec_string ("serialization", pc->fi->serialization),
+    GNUNET_BIO_write_spec_string ("pos serialization", (NULL == pc->fi_pos)
+                                  ? NULL
+                                  : pc->fi_pos->serialization),
+    GNUNET_BIO_read_spec_end ()
+  };
+  if ((GNUNET_OK != GNUNET_BIO_write_spec_commit (wh, ws)) ||
       ((NULL != pc->ns) &&
        (GNUNET_OK !=
         GNUNET_BIO_write (wh,
+                          "ns",
                           pc->ns,
                           sizeof(struct GNUNET_CRYPTO_EcdsaPrivateKey)))))
   {
     GNUNET_break (0);
     goto cleanup;
   }
-  if (GNUNET_OK != GNUNET_BIO_write_close (wh))
+  if (GNUNET_OK != GNUNET_BIO_write_close (wh, NULL))
   {
     wh = NULL;
     GNUNET_break (0);
@@ -1757,7 +1818,7 @@ GNUNET_FS_publish_sync_ (struct GNUNET_FS_PublishContext 
*pc)
   return;
 cleanup:
   if (NULL != wh)
-    (void) GNUNET_BIO_write_close (wh);
+    (void) GNUNET_BIO_write_close (wh, NULL);
   GNUNET_FS_remove_sync_file_ (pc->h,
                                GNUNET_FS_SYNC_PATH_MASTER_PUBLISH,
                                pc->serialization);
@@ -1797,25 +1858,34 @@ GNUNET_FS_unindex_sync_ (struct 
GNUNET_FS_UnindexContext *uc)
     uris = GNUNET_FS_uri_to_string (uc->ksk_uri);
   else
     uris = NULL;
-  if ((GNUNET_OK != GNUNET_BIO_write_string (wh, uc->filename)) ||
-      (GNUNET_OK != GNUNET_BIO_write_int64 (wh, uc->file_size)) ||
+  struct GNUNET_BIO_WriteSpec ws1[] = {
+    GNUNET_BIO_write_spec_string ("filename", uc->filename),
+    GNUNET_BIO_write_spec_int64 ("file size", (int64_t *) &uc->file_size),
+    GNUNET_BIO_write_spec_end (),
+  };
+  struct GNUNET_BIO_WriteSpec ws2[] = {
+    GNUNET_BIO_write_spec_int32 ("state", (int32_t *) &uc->state),
+    GNUNET_BIO_write_spec_object ("hashkey", &uc->chk,
+                                  sizeof (struct ContentHashKey)),
+    GNUNET_BIO_write_spec_string ("uris", uris),
+    GNUNET_BIO_write_spec_int32 ("ksk offset", (int32_t *) &uc->ksk_offset),
+    GNUNET_BIO_write_spec_end (),
+  };
+  if ((GNUNET_OK != GNUNET_BIO_write_spec_commit (wh, ws1)) ||
       (GNUNET_OK != write_start_time (wh, uc->start_time)) ||
-      (GNUNET_OK != GNUNET_BIO_write_int32 (wh, (uint32_t) uc->state)) ||
-      (GNUNET_OK !=
-       GNUNET_BIO_write (wh, &uc->chk, sizeof(struct ContentHashKey))) ||
-      (GNUNET_OK != GNUNET_BIO_write_string (wh, uris)) ||
-      (GNUNET_OK != GNUNET_BIO_write_int32 (wh, (uint32_t) uc->ksk_offset)) ||
+      (GNUNET_OK != GNUNET_BIO_write_spec_commit (wh, ws2)) ||
       ((uc->state == UNINDEX_STATE_FS_NOTIFY) &&
        (GNUNET_OK != GNUNET_BIO_write (wh,
+                                       "file id",
                                        &uc->file_id,
                                        sizeof(struct GNUNET_HashCode)))) ||
       ((uc->state == UNINDEX_STATE_ERROR) &&
-       (GNUNET_OK != GNUNET_BIO_write_string (wh, uc->emsg))))
+       (GNUNET_OK != GNUNET_BIO_write_string (wh, "emsg", uc->emsg))))
   {
     GNUNET_break (0);
     goto cleanup;
   }
-  if (GNUNET_OK != GNUNET_BIO_write_close (wh))
+  if (GNUNET_OK != GNUNET_BIO_write_close (wh, NULL))
   {
     wh = NULL;
     GNUNET_break (0);
@@ -1824,7 +1894,7 @@ GNUNET_FS_unindex_sync_ (struct GNUNET_FS_UnindexContext 
*uc)
   return;
 cleanup:
   if (NULL != wh)
-    (void) GNUNET_BIO_write_close (wh);
+    (void) GNUNET_BIO_write_close (wh, NULL);
   GNUNET_FS_remove_sync_file_ (uc->h,
                                GNUNET_FS_SYNC_PATH_MASTER_UNINDEX,
                                uc->serialization);
@@ -1845,15 +1915,20 @@ write_download_request (struct GNUNET_BIO_WriteHandle 
*wh,
                         struct DownloadRequest *dr)
 {
   unsigned int i;
-
-  if ((GNUNET_OK != GNUNET_BIO_write_int32 (wh, dr->state)) ||
-      (GNUNET_OK != GNUNET_BIO_write_int64 (wh, dr->offset)) ||
-      (GNUNET_OK != GNUNET_BIO_write_int32 (wh, dr->num_children)) ||
-      (GNUNET_OK != GNUNET_BIO_write_int32 (wh, dr->depth)))
+  struct GNUNET_BIO_WriteSpec ws[] = {
+    GNUNET_BIO_write_spec_int32 ("state", (int32_t *) &dr->state),
+    GNUNET_BIO_write_spec_int64 ("offset", (int64_t *) &dr->offset),
+    GNUNET_BIO_write_spec_int32 ("num children", (int32_t *) 
&dr->num_children),
+    GNUNET_BIO_write_spec_int32 ("depth", (int32_t *) &dr->depth),
+    GNUNET_BIO_write_spec_end (),
+  };
+
+  if ((GNUNET_OK != GNUNET_BIO_write_spec_commit (wh, ws)))
     return GNUNET_NO;
   if ((BRS_CHK_SET == dr->state) &&
       (GNUNET_OK !=
-       GNUNET_BIO_write (wh, &dr->chk, sizeof(struct ContentHashKey))))
+       GNUNET_BIO_write (wh, "hashkey",
+                         &dr->chk, sizeof(struct ContentHashKey))))
     return GNUNET_NO;
   for (i = 0; i < dr->num_children; i++)
     if (GNUNET_NO == write_download_request (wh, dr->children[i]))
@@ -1875,11 +1950,16 @@ read_download_request (struct GNUNET_BIO_ReadHandle *rh)
   unsigned int i;
 
   dr = GNUNET_new (struct DownloadRequest);
-  if ((GNUNET_OK != GNUNET_BIO_read_int32 (rh, &dr->state)) ||
-      (GNUNET_OK != GNUNET_BIO_read_int64 (rh, &dr->offset)) ||
-      (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &dr->num_children)) ||
+  struct GNUNET_BIO_ReadSpec rs[] = {
+    GNUNET_BIO_read_spec_int32 ("state", (int32_t *) &dr->state),
+    GNUNET_BIO_read_spec_int64 ("offset", (int64_t *) &dr->offset),
+    GNUNET_BIO_read_spec_int32 ("num children", (int32_t *) &dr->num_children),
+    GNUNET_BIO_read_spec_end (),
+  };
+  if ((GNUNET_OK != GNUNET_BIO_read_spec_commit (rh, rs)) ||
       (dr->num_children > CHK_PER_INODE) ||
-      (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &dr->depth)) ||
+      (GNUNET_OK != GNUNET_BIO_read_int32 (rh, "depth",
+                                           (int32_t *) &dr->depth)) ||
       ((0 == dr->depth) && (dr->num_children > 0)) ||
       ((dr->depth > 0) && (0 == dr->num_children)))
   {
@@ -2005,7 +2085,7 @@ GNUNET_FS_download_sync_ (struct 
GNUNET_FS_DownloadContext *dc)
       return;
     }
   }
-  wh = GNUNET_BIO_write_open (fn);
+  wh = GNUNET_BIO_write_open_file (fn);
   if (NULL == wh)
   {
     GNUNET_free (dc->serialization);
@@ -2016,19 +2096,28 @@ GNUNET_FS_download_sync_ (struct 
GNUNET_FS_DownloadContext *dc)
   GNUNET_assert ((GNUNET_YES == GNUNET_FS_uri_test_chk (dc->uri)) ||
                  (GNUNET_YES == GNUNET_FS_uri_test_loc (dc->uri)));
   uris = GNUNET_FS_uri_to_string (dc->uri);
-  if ((GNUNET_OK != GNUNET_BIO_write_string (wh, uris)) ||
-      (GNUNET_OK != GNUNET_BIO_write_meta_data (wh, dc->meta)) ||
-      (GNUNET_OK != GNUNET_BIO_write_string (wh, dc->emsg)) ||
-      (GNUNET_OK != GNUNET_BIO_write_string (wh, dc->filename)) ||
-      (GNUNET_OK != GNUNET_BIO_write_string (wh, dc->temp_filename)) ||
-      (GNUNET_OK != GNUNET_BIO_write_int64 (wh, dc->old_file_size)) ||
-      (GNUNET_OK != GNUNET_BIO_write_int64 (wh, dc->offset)) ||
-      (GNUNET_OK != GNUNET_BIO_write_int64 (wh, dc->length)) ||
-      (GNUNET_OK != GNUNET_BIO_write_int64 (wh, dc->completed)) ||
+  struct GNUNET_BIO_WriteSpec ws1[] = {
+    GNUNET_BIO_write_spec_string ("uris", uris),
+    GNUNET_BIO_write_spec_meta_data ("metadata", dc->meta),
+    GNUNET_BIO_write_spec_string ("emsg", dc->emsg),
+    GNUNET_BIO_write_spec_string ("filename", dc->filename),
+    GNUNET_BIO_write_spec_string ("temp filename", dc->temp_filename),
+    GNUNET_BIO_write_spec_int64 ("old file size",
+                                 (int64_t *) &dc->old_file_size),
+    GNUNET_BIO_write_spec_int64 ("offset", (int64_t *) &dc->offset),
+    GNUNET_BIO_write_spec_int64 ("length", (int64_t *) &dc->length),
+    GNUNET_BIO_write_spec_int64 ("completed", (int64_t *) &dc->completed),
+    GNUNET_BIO_write_spec_end (),
+  };
+  struct GNUNET_BIO_WriteSpec ws2[] = {
+    GNUNET_BIO_write_spec_int32 ("anonymity", (int32_t *) &dc->anonymity),
+    GNUNET_BIO_write_spec_int32 ("options", (int32_t *) &dc->options),
+    GNUNET_BIO_write_spec_int32 ("has finished", (int32_t *) 
&dc->has_finished),
+    GNUNET_BIO_write_spec_end (),
+  };
+  if ((GNUNET_OK != GNUNET_BIO_write_spec_commit (wh, ws1)) ||
       (GNUNET_OK != write_start_time (wh, dc->start_time)) ||
-      (GNUNET_OK != GNUNET_BIO_write_int32 (wh, dc->anonymity)) ||
-      (GNUNET_OK != GNUNET_BIO_write_int32 (wh, (uint32_t) dc->options)) ||
-      (GNUNET_OK != GNUNET_BIO_write_int32 (wh, (uint32_t) dc->has_finished)))
+      (GNUNET_OK != GNUNET_BIO_write_spec_commit (wh, ws2)))
   {
     GNUNET_break (0);
     goto cleanup;
@@ -2044,7 +2133,7 @@ GNUNET_FS_download_sync_ (struct 
GNUNET_FS_DownloadContext *dc)
   }
   GNUNET_free_non_null (uris);
   uris = NULL;
-  if (GNUNET_OK != GNUNET_BIO_write_close (wh))
+  if (GNUNET_OK != GNUNET_BIO_write_close (wh, NULL))
   {
     wh = NULL;
     GNUNET_break (0);
@@ -2054,7 +2143,7 @@ GNUNET_FS_download_sync_ (struct 
GNUNET_FS_DownloadContext *dc)
   return;
 cleanup:
   if (NULL != wh)
-    (void) GNUNET_BIO_write_close (wh);
+    (void) GNUNET_BIO_write_close (wh, NULL);
   GNUNET_free_non_null (uris);
   if (0 != unlink (fn))
     GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", fn);
@@ -2102,23 +2191,30 @@ GNUNET_FS_search_result_sync_ (struct 
GNUNET_FS_SearchResult *sr)
     goto cleanup;
   }
   uris = GNUNET_FS_uri_to_string (sr->uri);
-  if ((GNUNET_OK != GNUNET_BIO_write_string (wh, uris)) ||
-      (GNUNET_OK != GNUNET_BIO_write_string (wh,
-                                             (sr->download != NULL)
-                                             ? sr->download->serialization
-                                             : NULL)) ||
-      (GNUNET_OK !=
-       GNUNET_BIO_write_string (wh,
-                                (sr->update_search != NULL)
-                                ? sr->update_search->serialization
-                                : NULL)) ||
-      (GNUNET_OK != GNUNET_BIO_write_meta_data (wh, sr->meta)) ||
-      (GNUNET_OK !=
-       GNUNET_BIO_write (wh, &sr->key, sizeof(struct GNUNET_HashCode))) ||
-      (GNUNET_OK != GNUNET_BIO_write_int32 (wh, sr->mandatory_missing)) ||
-      (GNUNET_OK != GNUNET_BIO_write_int32 (wh, sr->optional_support)) ||
-      (GNUNET_OK != GNUNET_BIO_write_int32 (wh, sr->availability_success)) ||
-      (GNUNET_OK != GNUNET_BIO_write_int32 (wh, sr->availability_trials)))
+  struct GNUNET_BIO_WriteSpec ws[] = {
+    GNUNET_BIO_write_spec_string ("uris", uris),
+    GNUNET_BIO_write_spec_string ("download serialization",
+                                  (sr->download != NULL)
+                                  ? sr->download->serialization
+                                  : NULL),
+    GNUNET_BIO_write_spec_string ("update search serialization",
+                                  (sr->update_search != NULL)
+                                  ? sr->update_search->serialization
+                                  : NULL),
+    GNUNET_BIO_write_spec_meta_data ("metadata", sr->meta),
+    GNUNET_BIO_write_spec_object ("key", &sr->key,
+                                  sizeof(struct GNUNET_HashCode)),
+    GNUNET_BIO_write_spec_int32 ("mandatory missing",
+                                 (int32_t *) &sr->mandatory_missing),
+    GNUNET_BIO_write_spec_int32 ("optional support",
+                                 (int32_t *) &sr->optional_support),
+    GNUNET_BIO_write_spec_int32 ("availability success",
+                                 (int32_t *) &sr->availability_success),
+    GNUNET_BIO_write_spec_int32 ("availability trials",
+                                 (int32_t *) &sr->availability_trials),
+    GNUNET_BIO_write_spec_end (),
+  };
+  if ((GNUNET_OK != GNUNET_BIO_write_spec_commit (wh, ws)))
   {
     GNUNET_break (0);
     goto cleanup;
@@ -2126,13 +2222,14 @@ GNUNET_FS_search_result_sync_ (struct 
GNUNET_FS_SearchResult *sr)
   if ((NULL != sr->uri) && (GNUNET_FS_URI_KSK == sr->sc->uri->type) &&
       (GNUNET_OK !=
        GNUNET_BIO_write (wh,
+                         "keyword bitmap",
                          sr->keyword_bitmap,
                          (sr->sc->uri->data.ksk.keywordCount + 7) / 8)))
   {
     GNUNET_break (0);
     goto cleanup;
   }
-  if (GNUNET_OK != GNUNET_BIO_write_close (wh))
+  if (GNUNET_OK != GNUNET_BIO_write_close (wh, NULL))
   {
     wh = NULL;
     GNUNET_break (0);
@@ -2143,7 +2240,7 @@ GNUNET_FS_search_result_sync_ (struct 
GNUNET_FS_SearchResult *sr)
 cleanup:
   GNUNET_free_non_null (uris);
   if (NULL != wh)
-    (void) GNUNET_BIO_write_close (wh);
+    (void) GNUNET_BIO_write_close (wh, NULL);
   remove_sync_file_in_dir (sr->h,
                            (NULL == sr->sc->psearch_result)
                            ? GNUNET_FS_SYNC_PATH_MASTER_SEARCH
@@ -2188,19 +2285,21 @@ GNUNET_FS_search_sync_ (struct GNUNET_FS_SearchContext 
*sc)
                  (GNUNET_YES == GNUNET_FS_uri_test_sks (sc->uri)));
   uris = GNUNET_FS_uri_to_string (sc->uri);
   in_pause = (sc->task != NULL) ? 'r' : '\0';
-  if ((GNUNET_OK != GNUNET_BIO_write_string (wh, uris)) ||
+  if ((GNUNET_OK != GNUNET_BIO_write_string (wh, "uris", uris)) ||
       (GNUNET_OK != write_start_time (wh, sc->start_time)) ||
-      (GNUNET_OK != GNUNET_BIO_write_string (wh, sc->emsg)) ||
-      (GNUNET_OK != GNUNET_BIO_write_int32 (wh, (uint32_t) sc->options)) ||
-      (GNUNET_OK != GNUNET_BIO_write (wh, &in_pause, sizeof(in_pause))) ||
-      (GNUNET_OK != GNUNET_BIO_write_int32 (wh, sc->anonymity)))
+      (GNUNET_OK != GNUNET_BIO_write_string (wh, "emsg", sc->emsg)) ||
+      (GNUNET_OK != GNUNET_BIO_write_int32 (wh, "options",
+                                            (uint32_t) sc->options)) ||
+      (GNUNET_OK != GNUNET_BIO_write (wh, "in pause",
+                                      &in_pause, sizeof(in_pause))) ||
+      (GNUNET_OK != GNUNET_BIO_write_int32 (wh, "anonymity", sc->anonymity)))
   {
     GNUNET_break (0);
     goto cleanup;
   }
   GNUNET_free (uris);
   uris = NULL;
-  if (GNUNET_OK != GNUNET_BIO_write_close (wh))
+  if (GNUNET_OK != GNUNET_BIO_write_close (wh, NULL))
   {
     wh = NULL;
     GNUNET_break (0);
@@ -2209,7 +2308,7 @@ GNUNET_FS_search_sync_ (struct GNUNET_FS_SearchContext 
*sc)
   return;
 cleanup:
   if (NULL != wh)
-    (void) GNUNET_BIO_write_close (wh);
+    (void) GNUNET_BIO_write_close (wh, NULL);
   GNUNET_free_non_null (uris);
   GNUNET_FS_remove_sync_file_ (sc->h, category, sc->serialization);
   GNUNET_free (sc->serialization);
@@ -2239,7 +2338,7 @@ deserialize_unindex_file (void *cls, const char *filename)
   uc = GNUNET_new (struct GNUNET_FS_UnindexContext);
   uc->h = h;
   uc->serialization = get_serialization_short_name (filename);
-  rh = GNUNET_BIO_read_open (filename);
+  rh = GNUNET_BIO_read_open_file (filename);
   if (NULL == rh)
   {
     GNUNET_break (0);
@@ -2248,14 +2347,17 @@ deserialize_unindex_file (void *cls, const char 
*filename)
   uris = NULL;
   if ((GNUNET_OK !=
        GNUNET_BIO_read_string (rh, "unindex-fn", &uc->filename, 10 * 1024)) ||
-      (GNUNET_OK != GNUNET_BIO_read_int64 (rh, &uc->file_size)) ||
+      (GNUNET_OK != GNUNET_BIO_read_int64 (rh, "file size",
+                                           (int64_t *) &uc->file_size)) ||
       (GNUNET_OK != read_start_time (rh, &uc->start_time)) ||
-      (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &state)) ||
+      (GNUNET_OK != GNUNET_BIO_read_int32 (rh, "state",
+                                           (int32_t *) &state)) ||
       (GNUNET_OK !=
        GNUNET_BIO_read (rh, "uri", &uc->chk, sizeof(struct ContentHashKey))) ||
       (GNUNET_OK !=
        GNUNET_BIO_read_string (rh, "unindex-kskuri", &uris, 10 * 1024)) ||
-      (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &uc->ksk_offset)))
+      (GNUNET_OK != GNUNET_BIO_read_int32 (rh, "ksk offset",
+                                           (int32_t *) &uc->ksk_offset)))
   {
     GNUNET_free_non_null (uris);
     GNUNET_break (0);
@@ -2443,7 +2545,7 @@ deserialize_search_result (void *cls, const char 
*filename)
   struct GNUNET_FS_SearchResult *sr;
 
   ser = get_serialization_short_name (filename);
-  rh = GNUNET_BIO_read_open (filename);
+  rh = GNUNET_BIO_read_open_file (filename);
   if (NULL == rh)
   {
     if (NULL != ser)
@@ -2478,10 +2580,22 @@ deserialize_search_result (void *cls, const char 
*filename)
                                      "result-key",
                                      &sr->key,
                                      sizeof(struct GNUNET_HashCode))) ||
-      (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &sr->mandatory_missing)) ||
-      (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &sr->optional_support)) ||
-      (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &sr->availability_success)) ||
-      (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &sr->availability_trials)))
+      (GNUNET_OK != GNUNET_BIO_read_int32 (
+         rh,
+         "mandatory missing",
+         (int32_t *) &sr->mandatory_missing)) ||
+      (GNUNET_OK != GNUNET_BIO_read_int32 (
+         rh,
+         "optional support",
+         (int32_t *) &sr->optional_support)) ||
+      (GNUNET_OK != GNUNET_BIO_read_int32 (
+         rh,
+         "availability success",
+         (int32_t *) &sr->availability_success)) ||
+      (GNUNET_OK != GNUNET_BIO_read_int32 (
+         rh,
+         "availability trials",
+         (int32_t *) &sr->availability_trials)))
   {
     GNUNET_break (0);
     goto cleanup;
@@ -2741,7 +2855,7 @@ deserialize_subdownload (void *cls, const char *filename)
   struct GNUNET_BIO_ReadHandle *rh;
 
   ser = get_serialization_short_name (filename);
-  rh = GNUNET_BIO_read_open (filename);
+  rh = GNUNET_BIO_read_open_file (filename);
   if (NULL == rh)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
@@ -2827,29 +2941,35 @@ deserialize_download (struct GNUNET_FS_Handle *h,
   dc->parent = parent;
   dc->h = h;
   dc->serialization = GNUNET_strdup (serialization);
+  struct GNUNET_BIO_ReadSpec rs[] = {
+    GNUNET_BIO_read_spec_meta_data ("download-meta", &dc->meta),
+    GNUNET_BIO_read_spec_string ("download-emsg", &dc->emsg, 10 * 1024),
+    GNUNET_BIO_read_spec_string ("download-fn", &dc->filename, 10 * 1024),
+    GNUNET_BIO_read_spec_string ("download-tfn",
+                                 &dc->temp_filename, 10 * 1024),
+    GNUNET_BIO_read_spec_int64 ("old file size",
+                                (int64_t *) &dc->old_file_size),
+    GNUNET_BIO_read_spec_int64 ("offset",
+                                (int64_t *) &dc->offset),
+    GNUNET_BIO_read_spec_int64 ("length",
+                                (int64_t *) &dc->length),
+    GNUNET_BIO_read_spec_int64 ("completed",
+                                (int64_t *) &dc->completed),
+    GNUNET_BIO_read_spec_end (),
+  };
   if ((GNUNET_OK !=
        GNUNET_BIO_read_string (rh, "download-uri", &uris, 10 * 1024)) ||
       (NULL == (dc->uri = GNUNET_FS_uri_parse (uris, &emsg))) ||
       ((GNUNET_YES != GNUNET_FS_uri_test_chk (dc->uri)) &&
        (GNUNET_YES != GNUNET_FS_uri_test_loc (dc->uri))) ||
-      (GNUNET_OK !=
-       GNUNET_BIO_read_meta_data (rh, "download-meta", &dc->meta)) ||
-      (GNUNET_OK !=
-       GNUNET_BIO_read_string (rh, "download-emsg", &dc->emsg, 10 * 1024)) ||
-      (GNUNET_OK !=
-       GNUNET_BIO_read_string (rh, "download-fn", &dc->filename, 10 * 1024)) ||
-      (GNUNET_OK != GNUNET_BIO_read_string (rh,
-                                            "download-tfn",
-                                            &dc->temp_filename,
-                                            10 * 1024)) ||
-      (GNUNET_OK != GNUNET_BIO_read_int64 (rh, &dc->old_file_size)) ||
-      (GNUNET_OK != GNUNET_BIO_read_int64 (rh, &dc->offset)) ||
-      (GNUNET_OK != GNUNET_BIO_read_int64 (rh, &dc->length)) ||
-      (GNUNET_OK != GNUNET_BIO_read_int64 (rh, &dc->completed)) ||
+      (GNUNET_OK != GNUNET_BIO_read_spec_commit (rh, rs)) ||
       (GNUNET_OK != read_start_time (rh, &dc->start_time)) ||
-      (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &dc->anonymity)) ||
-      (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &options)) ||
-      (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &status)))
+      (GNUNET_OK != GNUNET_BIO_read_int32 (rh, "anonymity",
+                                           (int32_t *) &dc->anonymity)) ||
+      (GNUNET_OK != GNUNET_BIO_read_int32 (rh, "options",
+                                           (int32_t *) &options)) ||
+      (GNUNET_OK != GNUNET_BIO_read_int32 (rh, "status",
+                                           (int32_t *) &status)))
   {
     GNUNET_break (0);
     goto cleanup;
@@ -2972,10 +3092,12 @@ deserialize_search (struct GNUNET_FS_Handle *h,
       (GNUNET_OK != read_start_time (rh, &sc->start_time)) ||
       (GNUNET_OK !=
        GNUNET_BIO_read_string (rh, "search-emsg", &sc->emsg, 10 * 1024)) ||
-      (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &options)) ||
+      (GNUNET_OK != GNUNET_BIO_read_int32 (rh, "options",
+                                           (int32_t *) &options)) ||
       (GNUNET_OK !=
        GNUNET_BIO_read (rh, "search-pause", &in_pause, sizeof(in_pause))) ||
-      (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &sc->anonymity)))
+      (GNUNET_OK != GNUNET_BIO_read_int32 (rh, "anonymity",
+                                           (int32_t *) &sc->anonymity)))
   {
     GNUNET_break (0);
     goto cleanup;
@@ -3038,7 +3160,7 @@ deserialize_search_file (void *cls, const char *filename)
   if (S_ISDIR (buf.st_mode))
     return GNUNET_OK; /* skip directories */
   ser = get_serialization_short_name (filename);
-  rh = GNUNET_BIO_read_open (filename);
+  rh = GNUNET_BIO_read_open_file (filename);
   if (NULL == rh)
   {
     if (NULL != ser)
@@ -3081,7 +3203,7 @@ deserialize_download_file (void *cls, const char 
*filename)
   struct GNUNET_BIO_ReadHandle *rh;
 
   ser = get_serialization_short_name (filename);
-  rh = GNUNET_BIO_read_open (filename);
+  rh = GNUNET_BIO_read_open_file (filename);
   if (NULL == rh)
   {
     if (0 != unlink (filename))
diff --git a/src/fs/fs_namespace.c b/src/fs/fs_namespace.c
index 6ede02afd..f098032d7 100644
--- a/src/fs/fs_namespace.c
+++ b/src/fs/fs_namespace.c
@@ -195,7 +195,7 @@ write_update_information_graph (struct 
GNUNET_FS_UpdateInformationGraph *uig)
   char *uris;
 
   fn = get_update_information_directory (uig->h, &uig->ns);
-  wh = GNUNET_BIO_write_open (fn);
+  wh = GNUNET_BIO_write_open_file (fn);
   if (NULL == wh)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -205,16 +205,22 @@ write_update_information_graph (struct 
GNUNET_FS_UpdateInformationGraph *uig)
     GNUNET_free (fn);
     return;
   }
-  if (GNUNET_OK != GNUNET_BIO_write_int32 (wh, uig->update_node_count))
+  if (GNUNET_OK != GNUNET_BIO_write_int32 (wh,
+                                           "fs-namespace-node-count",
+                                           uig->update_node_count))
     goto END;
   for (i = 0; i < uig->update_node_count; i++)
   {
     n = uig->update_nodes[i];
     uris = GNUNET_FS_uri_to_string (n->uri);
-    if ((GNUNET_OK != GNUNET_BIO_write_string (wh, n->id)) ||
-        (GNUNET_OK != GNUNET_BIO_write_meta_data (wh, n->md)) ||
-        (GNUNET_OK != GNUNET_BIO_write_string (wh, n->update)) ||
-        (GNUNET_OK != GNUNET_BIO_write_string (wh, uris)))
+    struct GNUNET_BIO_WriteSpec ws[] = {
+      GNUNET_BIO_write_spec_string("fs-namespace-node-id", n->id),
+      GNUNET_BIO_write_spec_meta_data("fs-namespace-node-meta", n->md),
+      GNUNET_BIO_write_spec_string("fs-namespace-node-update", n->update),
+      GNUNET_BIO_write_spec_string("fs-namespace-uris", uris),
+      GNUNET_BIO_write_spec_end(),
+    };
+    if (GNUNET_OK != GNUNET_BIO_write_spec_commit(wh, ws))
     {
       GNUNET_free (uris);
       break;
@@ -222,7 +228,7 @@ write_update_information_graph (struct 
GNUNET_FS_UpdateInformationGraph *uig)
     GNUNET_free (uris);
   }
 END:
-  if (GNUNET_OK != GNUNET_BIO_write_close (wh))
+  if (GNUNET_OK != GNUNET_BIO_write_close (wh, NULL))
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                 _ ("Failed to write `%s': %s\n"),
                 fn,
@@ -260,13 +266,14 @@ read_update_information_graph (struct GNUNET_FS_Handle *h,
     GNUNET_free (fn);
     return uig;
   }
-  rh = GNUNET_BIO_read_open (fn);
+  rh = GNUNET_BIO_read_open_file (fn);
   if (NULL == rh)
   {
     GNUNET_free (fn);
     return uig;
   }
-  if (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &count))
+  if (GNUNET_OK != GNUNET_BIO_read_int32 (rh, "fs-namespace-count",
+                                          (int32_t *) &count))
   {
     GNUNET_break (0);
     goto END;
@@ -284,12 +291,14 @@ read_update_information_graph (struct GNUNET_FS_Handle *h,
   for (i = 0; i < count; i++)
   {
     n = GNUNET_new (struct NamespaceUpdateNode);
-    if ((GNUNET_OK !=
-         GNUNET_BIO_read_string (rh, "identifier", &n->id, 1024)) ||
-        (GNUNET_OK != GNUNET_BIO_read_meta_data (rh, "meta", &n->md)) ||
-        (GNUNET_OK !=
-         GNUNET_BIO_read_string (rh, "update-id", &n->update, 1024)) ||
-        (GNUNET_OK != GNUNET_BIO_read_string (rh, "uri", &uris, 1024 * 2)))
+    struct GNUNET_BIO_ReadSpec rs[] = {
+      GNUNET_BIO_read_spec_string("identifier", &n->id, 1024),
+      GNUNET_BIO_read_spec_meta_data("meta", &n->md),
+      GNUNET_BIO_read_spec_string("update-id", &n->update, 1024),
+      GNUNET_BIO_read_spec_string("uri", &uris, 1024 * 2),
+      GNUNET_BIO_read_spec_end(),
+    };
+    if (GNUNET_OK != GNUNET_BIO_read_spec_commit (rh, rs))
     {
       GNUNET_break (0);
       GNUNET_free_non_null (n->id);
diff --git a/src/fs/gnunet-auto-share.c b/src/fs/gnunet-auto-share.c
index 13bc908e8..3aed0268b 100644
--- a/src/fs/gnunet-auto-share.c
+++ b/src/fs/gnunet-auto-share.c
@@ -190,18 +190,22 @@ load_state ()
 
   emsg = NULL;
   fn = get_state_file ();
-  rh = GNUNET_BIO_read_open (fn);
+  rh = GNUNET_BIO_read_open_file (fn);
   GNUNET_free (fn);
   if (NULL == rh)
     return;
   fn = NULL;
-  if (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &n))
+  if (GNUNET_OK != GNUNET_BIO_read_int32 (rh, "number of files",
+                                          (int32_t *) &n))
     goto error;
   while (n-- > 0)
   {
-    if ((GNUNET_OK != GNUNET_BIO_read_string (rh, "filename", &fn, 1024)) ||
-        (GNUNET_OK !=
-         GNUNET_BIO_read (rh, "id", &id, sizeof(struct GNUNET_HashCode))))
+    struct GNUNET_BIO_ReadSpec rs[] = {
+      GNUNET_BIO_read_spec_string("filename", &fn, 1024),
+      GNUNET_BIO_read_spec_object("id", &id, sizeof(struct GNUNET_HashCode)),
+      GNUNET_BIO_read_spec_end(),
+    };
+    if (GNUNET_OK != GNUNET_BIO_read_spec_commit (rh, rs))
       goto error;
     wi = GNUNET_new (struct WorkItem);
     wi->id = id;
@@ -251,9 +255,13 @@ write_item (void *cls, const struct GNUNET_HashCode *key, 
void *value)
               "Saving serialization ID of file `%s' with value `%s'\n",
               wi->filename,
               GNUNET_h2s (&wi->id));
-  if ((GNUNET_OK != GNUNET_BIO_write_string (wh, wi->filename)) ||
-      (GNUNET_OK !=
-       GNUNET_BIO_write (wh, &wi->id, sizeof(struct GNUNET_HashCode))))
+  struct GNUNET_BIO_WriteSpec ws[] = {
+    GNUNET_BIO_write_spec_string ("auto-share-write-item-filename",
+                                  wi->filename),
+    GNUNET_BIO_write_spec_object ("id", &wi->id, sizeof(struct 
GNUNET_HashCode)),
+    GNUNET_BIO_write_spec_end (),
+  };
+  if (GNUNET_OK != GNUNET_BIO_write_spec_commit (wh, ws))
     return GNUNET_SYSERR; /* write error, abort iteration */
   return GNUNET_OK;
 }
@@ -271,7 +279,7 @@ save_state ()
 
   n = GNUNET_CONTAINER_multihashmap_size (work_finished);
   fn = get_state_file ();
-  wh = GNUNET_BIO_write_open (fn);
+  wh = GNUNET_BIO_write_open_file (fn);
   if (NULL == wh)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
@@ -280,9 +288,9 @@ save_state ()
     GNUNET_free (fn);
     return;
   }
-  if (GNUNET_OK != GNUNET_BIO_write_int32 (wh, n))
+  if (GNUNET_OK != GNUNET_BIO_write_int32 (wh, "size of state", n))
   {
-    (void) GNUNET_BIO_write_close (wh);
+    (void) GNUNET_BIO_write_close (wh, NULL);
     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                 _ ("Failed to save state to file %s\n"),
                 fn);
@@ -290,7 +298,7 @@ save_state ()
     return;
   }
   (void) GNUNET_CONTAINER_multihashmap_iterate (work_finished, &write_item, 
wh);
-  if (GNUNET_OK != GNUNET_BIO_write_close (wh))
+  if (GNUNET_OK != GNUNET_BIO_write_close (wh, NULL))
     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                 _ ("Failed to save state to file %s\n"),
                 fn);
diff --git a/src/fs/gnunet-service-fs_indexing.c 
b/src/fs/gnunet-service-fs_indexing.c
index 98fca3ec5..f4d560176 100644
--- a/src/fs/gnunet-service-fs_indexing.c
+++ b/src/fs/gnunet-service-fs_indexing.c
@@ -123,7 +123,7 @@ write_index_list ()
                                "INDEXDB");
     return;
   }
-  wh = GNUNET_BIO_write_open (fn);
+  wh = GNUNET_BIO_write_open_file (fn);
   if (NULL == wh)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
@@ -134,11 +134,14 @@ write_index_list ()
   }
   for (pos = indexed_files_head; NULL != pos; pos = pos->next)
     if ((GNUNET_OK != GNUNET_BIO_write (wh,
+                                        "fs-indexing-file-id",
                                         &pos->file_id,
                                         sizeof(struct GNUNET_HashCode))) ||
-        (GNUNET_OK != GNUNET_BIO_write_string (wh, pos->filename)))
+        (GNUNET_OK != GNUNET_BIO_write_string (wh,
+                                               "fs-indexing-filename",
+                                               pos->filename)))
       break;
-  if (GNUNET_OK != GNUNET_BIO_write_close (wh))
+  if (GNUNET_OK != GNUNET_BIO_write_close (wh, NULL))
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
                 _ ("Error writing `%s'.\n"),
@@ -178,7 +181,7 @@ read_index_list ()
     GNUNET_free (fn);
     return;
   }
-  rh = GNUNET_BIO_read_open (fn);
+  rh = GNUNET_BIO_read_open_file (fn);
   if (NULL == rh)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
diff --git a/src/hostlist/gnunet-daemon-hostlist_client.c 
b/src/hostlist/gnunet-daemon-hostlist_client.c
index a5ff9f9fa..c2e8f5d88 100644
--- a/src/hostlist/gnunet-daemon-hostlist_client.c
+++ b/src/hostlist/gnunet-daemon-hostlist_client.c
@@ -1404,7 +1404,7 @@ load_hostlist_file ()
     return;
   }
 
-  rh = GNUNET_BIO_read_open (filename);
+  rh = GNUNET_BIO_read_open_file (filename);
   if (NULL == rh)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
@@ -1417,13 +1417,17 @@ load_hostlist_file ()
   }
 
   counter = 0;
+  struct GNUNET_BIO_ReadSpec rs[] = {
+    GNUNET_BIO_read_spec_int32 ("times used", (int32_t *)&times_used),
+    GNUNET_BIO_read_spec_int64 ("quality", (int64_t *) &quality),
+    GNUNET_BIO_read_spec_int64 ("last used", (int64_t *) &last_used),
+    GNUNET_BIO_read_spec_int64 ("created", (int64_t *) &created),
+    GNUNET_BIO_read_spec_int32 ("hellos returned", (int32_t *) 
&hellos_returned),
+    GNUNET_BIO_read_spec_end (),
+  };
   while ((GNUNET_OK == GNUNET_BIO_read_string (rh, "url", &uri, MAX_URL_LEN)) 
&&
          (NULL != uri) &&
-         (GNUNET_OK == GNUNET_BIO_read_int32 (rh, &times_used)) &&
-         (GNUNET_OK == GNUNET_BIO_read_int64 (rh, &quality)) &&
-         (GNUNET_OK == GNUNET_BIO_read_int64 (rh, &last_used)) &&
-         (GNUNET_OK == GNUNET_BIO_read_int64 (rh, &created)) &&
-         (GNUNET_OK == GNUNET_BIO_read_int32 (rh, &hellos_returned)))
+         (GNUNET_OK == GNUNET_BIO_read_spec_commit (rh, rs)))
   {
     hostlist = GNUNET_malloc (sizeof(struct Hostlist) + strlen (uri) + 1);
     hostlist->hello_count = hellos_returned;
@@ -1494,7 +1498,7 @@ save_hostlist_file (int shutdown)
     GNUNET_free (filename);
     return;
   }
-  wh = GNUNET_BIO_write_open (filename);
+  wh = GNUNET_BIO_write_open_file (filename);
   if (NULL == wh)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
@@ -1521,14 +1525,21 @@ save_hostlist_file (int shutdown)
     }
     if (GNUNET_YES == ok)
     {
-      if ((GNUNET_OK != GNUNET_BIO_write_string (wh, pos->hostlist_uri)) ||
-          (GNUNET_OK != GNUNET_BIO_write_int32 (wh, pos->times_used)) ||
-          (GNUNET_OK != GNUNET_BIO_write_int64 (wh, pos->quality)) ||
-          (GNUNET_OK !=
-           GNUNET_BIO_write_int64 (wh, pos->time_last_usage.abs_value_us)) ||
-          (GNUNET_OK !=
-           GNUNET_BIO_write_int64 (wh, pos->time_creation.abs_value_us)) ||
-          (GNUNET_OK != GNUNET_BIO_write_int32 (wh, pos->hello_count)))
+      struct GNUNET_BIO_WriteSpec ws[] = {
+        GNUNET_BIO_write_spec_string ("hostlist uri", pos->hostlist_uri),
+        GNUNET_BIO_write_spec_int32 ("times used", (int32_t *) 
&pos->times_used),
+        GNUNET_BIO_write_spec_int64 ("quality", (int64_t *) &pos->quality),
+        GNUNET_BIO_write_spec_int64 (
+          "last usage",
+          (int64_t *) &pos->time_last_usage.abs_value_us),
+        GNUNET_BIO_write_spec_int64 (
+          "creation time",
+          (int64_t *) &pos->time_creation.abs_value_us),
+        GNUNET_BIO_write_spec_int32 ("hellos count",
+                                     (int32_t *) &pos->hello_count),
+        GNUNET_BIO_write_spec_end (),
+      };
+      if ((GNUNET_OK != GNUNET_BIO_write_spec_commit (wh, ws)))
       {
         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                     _ ("Error writing hostlist URIs to file `%s'\n"),
@@ -1548,7 +1559,7 @@ save_hostlist_file (int shutdown)
                          counter,
                          GNUNET_YES);
 
-  if (GNUNET_OK != GNUNET_BIO_write_close (wh))
+  if (GNUNET_OK != GNUNET_BIO_write_close (wh, NULL))
     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                 _ ("Error writing hostlist URIs to file `%s'\n"),
                 filename);
diff --git a/src/include/gnunet_bio_lib.h b/src/include/gnunet_bio_lib.h
index 2f715ec97..687334c1c 100644
--- a/src/include/gnunet_bio_lib.h
+++ b/src/include/gnunet_bio_lib.h
@@ -42,6 +42,8 @@ extern "C"
 #endif
 #endif
 
+/****************************** READING API *******************************/
+
 /**
  * Handle for buffered reading.
  */
@@ -55,11 +57,22 @@ struct GNUNET_BIO_ReadHandle;
  * @return IO handle on success, NULL on error
  */
 struct GNUNET_BIO_ReadHandle *
-GNUNET_BIO_read_open (const char *fn);
+GNUNET_BIO_read_open_file (const char *fn);
+
+
+/**
+ * Create a handle from an existing allocated buffer.
+ *
+ * @param buffer the buffer to use as source
+ * @param size the total size in bytes of the buffer
+ * @return IO handle on sucess, NULL on error
+ */
+struct GNUNET_BIO_ReadHandle *
+GNUNET_BIO_read_open_buffer (void *buffer, size_t size);
 
 
 /**
- * Close an open file.  Reports if any errors reading
+ * Close an open handle.  Reports if any errors reading
  * from the file were encountered.
  *
  * @param h file handle
@@ -71,51 +84,40 @@ GNUNET_BIO_read_close (struct GNUNET_BIO_ReadHandle *h, 
char **emsg);
 
 
 /**
- * Read the contents of a binary file into a buffer.
+ * Read some contents into a buffer.
  *
- * @param h handle to an open file
+ * @param h the IO handle to read from
  * @param what describes what is being read (for error message creation)
  * @param result the buffer to write the result to
  * @param len the number of bytes to read
  * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
  */
 int
-GNUNET_BIO_read (struct GNUNET_BIO_ReadHandle *h, const char *what,
-                 void *result, size_t len);
+GNUNET_BIO_read (struct GNUNET_BIO_ReadHandle *h,
+                 const char *what,
+                 void *result,
+                 size_t len);
 
 
 /**
- * Read the contents of a binary file into a buffer.
+ * Read 0-terminated string.
  *
- * @param h handle to an open file
- * @param file name of the source file
- * @param line line number in the source file
- * @param result the buffer to write the result to
- * @param len the number of bytes to read
- * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
- */
-int
-GNUNET_BIO_read_fn (struct GNUNET_BIO_ReadHandle *h,
-                    const char *file, int line,
-                    void *result, size_t len);
-
-/**
- * Read 0-terminated string from a file.
- *
- * @param h handle to an open file
+ * @param h the IO handle to read from
  * @param what describes what is being read (for error message creation)
- * @param result the buffer to store a pointer to the (allocated) string to
+ * @param result where to store the pointer to the (allocated) string
  *        (note that *result could be set to NULL as well)
  * @param max_length maximum allowed length for the string
  * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
  */
 int
-GNUNET_BIO_read_string (struct GNUNET_BIO_ReadHandle *h, const char *what,
-                        char **result, size_t max_length);
+GNUNET_BIO_read_string (struct GNUNET_BIO_ReadHandle *h,
+                        const char *what,
+                        char **result,
+                        size_t max_length);
 
 
 /**
- * Read metadata container from a file.
+ * Read a metadata container.
  *
  * @param h handle to an open file
  * @param what describes what is being read (for error message creation)
@@ -123,79 +125,69 @@ GNUNET_BIO_read_string (struct GNUNET_BIO_ReadHandle *h, 
const char *what,
  * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
  */
 int
-GNUNET_BIO_read_meta_data (struct GNUNET_BIO_ReadHandle *h, const char *what,
+GNUNET_BIO_read_meta_data (struct GNUNET_BIO_ReadHandle *h,
+                           const char *what,
                            struct GNUNET_CONTAINER_MetaData **result);
 
 
 /**
  * Read a float.
  *
- * @param h hande to open file
+ * @param h the IO handle to read from
+ * @param what describes what is being read (for error message creation)
  * @param f address of float to read
  */
-#define GNUNET_BIO_read_float(h, f) (GNUNET_BIO_read_fn (h, __FILE__, 
__LINE__, \
-                                                         f, sizeof(float)))
+int
+GNUNET_BIO_read_float(struct GNUNET_BIO_ReadHandle *h,
+                      const char *what,
+                      float *f);
 
 
 /**
  * Read a double.
  *
- * @param h hande to open file
+ * @param h the IO handle to read from
+ * @param what describes what is being read (for error message creation)
  * @param f address of double to read
  */
-#define GNUNET_BIO_read_double(h, f) (GNUNET_BIO_read_fn (h, __FILE__, 
__LINE__, \
-                                                          f, sizeof(double)))
+int
+GNUNET_BIO_read_double(struct GNUNET_BIO_ReadHandle *h,
+                       const char *what,
+                       double *f);
+
 
 
 /**
  * Read an (u)int32_t.
  *
- * @param h hande to open file
- * @param file name of the source file
- * @param line line number in the code
- * @param i address of 32-bit integer to read
+ * @param h the IO handle to read from
+ * @param what describes what is being read (for error message creation)
+ * @param i where to store the data
  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
  */
 int
-GNUNET_BIO_read_int32__ (struct GNUNET_BIO_ReadHandle *h, const char *file,
-                         int line, int32_t *i);
-
+GNUNET_BIO_read_int32 (struct GNUNET_BIO_ReadHandle *h,
+                       const char *what,
+                       int32_t *i);
 
-/**
- * Read an (u)int32_t.
- *
- * @param h hande to open file
- * @param i address of 32-bit integer to read
- */
-#define GNUNET_BIO_read_int32(h, i) GNUNET_BIO_read_int32__ (h, __FILE__, \
-                                                             __LINE__, \
-                                                             (int32_t *) i)
 
 
 /**
  * Read an (u)int64_t.
  *
- * @param h hande to open file
- * @param file name of the source file
- * @param line line number in the code
- * @param i address of 64-bit integer to read
+ * @param h the IO handle to read from
+ * @param what describes what is being read (for error message creation)
+ * @param i where to store the data
  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
  */
 int
-GNUNET_BIO_read_int64__ (struct GNUNET_BIO_ReadHandle *h, const char *file,
-                         int line, int64_t *i);
+GNUNET_BIO_read_int64 (struct GNUNET_BIO_ReadHandle *h,
+                       const char *what,
+                       int64_t *i);
 
 
-/**
- * Read an (u)int64_t.
- *
- * @param h hande to open file
- * @param i address of 64-bit integer to read
- */
-#define GNUNET_BIO_read_int64(h, i) GNUNET_BIO_read_int64__ (h, __FILE__, \
-                                                             __LINE__, \
-                                                             (int64_t *) i)
 
+/****************************** WRITING API *******************************/
 
 /**
  * Handle for buffered writing.
@@ -205,108 +197,481 @@ struct GNUNET_BIO_WriteHandle;
 /**
  * Open a file for writing.
  *
- * @param fn file name to be opened
+ * @param fn name of the file to be opened
  * @return IO handle on success, NULL on error
  */
 struct GNUNET_BIO_WriteHandle *
-GNUNET_BIO_write_open (const char *fn);
+GNUNET_BIO_write_open_file (const char *fn);
 
 
 /**
- * Close an open file for writing.
+ * Create a handle backed by an in-memory buffer.
  *
- * @param h file handle
- * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
+ * @return IO handle on success, NULL on error
+ */
+struct GNUNET_BIO_WriteHandle *
+GNUNET_BIO_write_open_buffer (void);
+
+
+/**
+ * Force a file-based buffered writer to flush its buffer.
+ * If the handle does not use a file, this function returs #GNUNET_OK
+ * without doing anything.
+ *
+ * @param h the IO handle
+ * @return #GNUNET_OK upon success.  Upon failure #GNUNET_SYSERR is returned
+ *         and the file is closed
  */
 int
-GNUNET_BIO_write_close (struct GNUNET_BIO_WriteHandle *h);
+GNUNET_BIO_flush (struct GNUNET_BIO_WriteHandle *h);
 
 
 /**
- * Write a buffer to a file.
+ * Get the IO handle's contents.
+ * If the handle doesn't use an in-memory buffer, this function returns
+ * #GNUNET_SYSERR.
  *
- * @param h handle to open file
- * @param buffer the data to write
- * @param n number of bytes to write
- * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
+ * @param h the IO handle
+ * @param emsg set to the (allocated) error message
+ *        if the handle has an error message the return value is #GNUNET_SYSERR
+ * @param contents where to store the pointer to the handle's contents
+ * @param size where to store the size of @e contents
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
  */
 int
-GNUNET_BIO_write (struct GNUNET_BIO_WriteHandle *h, const void *buffer,
-                  size_t n);
+GNUNET_BIO_get_buffer_contents (struct GNUNET_BIO_WriteHandle *h,
+                                char **emsg,
+                                void **contents,
+                                size_t *size);
+
+
+/**
+ * Close an IO handle.
+ * If the handle was using a file, the file will be closed.
+ *
+ * @param h file handle
+ * @param emsg set to the (allocated) error message
+ *        if the handle has an error message, the return value is 
#GNUNET_SYSERR
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
+ */
+int
+GNUNET_BIO_write_close (struct GNUNET_BIO_WriteHandle *h, char **emsg);
 
 
 /**
- * Force a buffered writer to flush its buffer
+ * Write a buffer to a handle.
  *
- * @param h the writer handle
- * @return #GNUNET_OK upon success.  Upon failure #GNUNET_SYSERR is returned 
and
- *           the file is closed
+ * @param h the IO handle to write to
+ * @param what what is being written (for error message creation)
+ * @param buffer the data to write
+ * @param n number of bytes to write
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
  */
 int
-GNUNET_BIO_flush (struct GNUNET_BIO_WriteHandle *h);
+GNUNET_BIO_write (struct GNUNET_BIO_WriteHandle *h,
+                  const char *what,
+                  const void *buffer,
+                  size_t n);
 
 
 /**
- * Write a string to a file.
+ * Write a 0-terminated string.
  *
- * @param h handle to open file
+ * @param h the IO handle to write to
+ * @param what what is being written (for error message creation)
  * @param s string to write (can be NULL)
  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
  */
 int
-GNUNET_BIO_write_string (struct GNUNET_BIO_WriteHandle *h, const char *s);
+GNUNET_BIO_write_string (struct GNUNET_BIO_WriteHandle *h,
+                         const char *what,
+                         const char *s);
 
 
 /**
- * Write metadata container to a file.
+ * Write a metadata container.
  *
- * @param h handle to open file
+ * @param h the IO handle to write to
+ * @param what what is being written (for error message creation)
  * @param m metadata to write
  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
  */
 int
 GNUNET_BIO_write_meta_data (struct GNUNET_BIO_WriteHandle *h,
+                            const char *what,
                             const struct GNUNET_CONTAINER_MetaData *m);
 
 
 /**
  * Write a float.
  *
- * @param h hande to open file
+ * @param h the IO handle to write to
+ * @param what what is being written (for error message creation)
  * @param f float to write (must be a variable)
  */
-#define GNUNET_BIO_write_float(h, f) GNUNET_BIO_write (h, &f, sizeof(float))
-
+int
+GNUNET_BIO_write_float(struct GNUNET_BIO_WriteHandle *h,
+                       const char *what,
+                       float f);
 
 /**
  * Write a double.
  *
- * @param h hande to open file
+ * @param h the IO handle to write to
+ * @param what what is being written (for error message creation)
  * @param f double to write (must be a variable)
  */
-#define GNUNET_BIO_write_double(h, f) GNUNET_BIO_write (h, &f, sizeof(double))
+int
+GNUNET_BIO_write_double(struct GNUNET_BIO_WriteHandle *h,
+                        const char *what,
+                        double f);
 
 
 /**
  * Write an (u)int32_t.
  *
- * @param h hande to open file
+ * @param h the IO handle to write to
+ * @param what what is being written (for error message creation)
  * @param i 32-bit integer to write
  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
  */
 int
-GNUNET_BIO_write_int32 (struct GNUNET_BIO_WriteHandle *h, int32_t i);
+GNUNET_BIO_write_int32 (struct GNUNET_BIO_WriteHandle *h,
+                        const char *what,
+                        int32_t i);
 
 
 /**
  * Write an (u)int64_t.
  *
- * @param h hande to open file
+ * @param h the IO handle to write to
+ * @param what what is being written (for error message creation)
  * @param i 64-bit integer to write
  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
  */
 int
-GNUNET_BIO_write_int64 (struct GNUNET_BIO_WriteHandle *h, int64_t i);
+GNUNET_BIO_write_int64 (struct GNUNET_BIO_WriteHandle *h,
+                        const char *what,
+                        int64_t i);
+
+
+/****************************** READ SPEC API ***************************/
+
+
+/**
+ * Function used to deserialize data read from @a h and store it into @a
+ * target.
+ *
+ * @param cls closure (can be NULL)
+ * @param h the IO handle to read from
+ * @param what what is being read (for error message creation)
+ * @param target where to store the data
+ * @param target_size how many bytes can be written in @a target
+ *        can be 0 if the size is unknown or is not fixed
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
+ */
+typedef int
+(*GNUNET_BIO_ReadHandler)(void *cls,
+                          struct GNUNET_BIO_ReadHandle *h,
+                          const char *what,
+                          void *target,
+                          size_t target_size);
+
+
+/**
+ * Structure specifying a reading operation on an IO handle.
+ */
+struct GNUNET_BIO_ReadSpec
+{
+  /**
+   * Function performing data deserialization.
+   */
+  GNUNET_BIO_ReadHandler rh;
+
+  /**
+   * Closure for @e rh. Can be NULL.
+   */
+  void *cls;
+
+  /**
+   * What is being read (for error message creation)
+   */
+  const char *what;
+
+  /**
+   * Destination buffer. Can also be a pointer to a pointer, especially for
+   * dynamically allocated structures.
+   */
+  void *target;
+
+  /**
+   * Size of @e target. Can be 0 if unknown or not fixed.
+   */
+  size_t size;
+};
+
+
+/**
+ * End of specifications marker.
+ */
+#define GNUNET_BIO_read_spec_end()              \
+  { NULL, NULL, NULL, NULL, 0 }
+
+
+/**
+ * Create the specification to read a certain amount of bytes.
+ *
+ * @param what describes what is being read (for error message creation)
+ * @param result the buffer to write the result to
+ * @param len the number of bytes to read
+ * @return the read spec
+ */
+struct GNUNET_BIO_ReadSpec
+GNUNET_BIO_read_spec_object (const char *what,
+                             void *result,
+                             size_t size);
+
+
+/**
+ * Create the specification to read a 0-terminated string.
+ *
+ * @param what describes what is being read (for error message creation)
+ * @param result where to store the pointer to the (allocated) string
+ *        (note that *result could be set to NULL as well)
+ * @param max_length maximum allowed length for the string
+ * @return the read spec
+ */
+struct GNUNET_BIO_ReadSpec
+GNUNET_BIO_read_spec_string (const char *what,
+                             char **result,
+                             size_t max_length);
+
+
+/**
+ * Create the specification to read a metadata container.
+ *
+ * @param what describes what is being read (for error message creation)
+ * @param result the buffer to store a pointer to the (allocated) metadata
+ * @return the read spec
+ */
+struct GNUNET_BIO_ReadSpec
+GNUNET_BIO_read_spec_meta_data (const char *what,
+                                struct GNUNET_CONTAINER_MetaData **result);
+
+
+/**
+ * Create the specification to read an (u)int32_t.
+ *
+ * @param what describes what is being read (for error message creation)
+ * @param i where to store the data
+ * @return the read spec
+ */
+struct GNUNET_BIO_ReadSpec
+GNUNET_BIO_read_spec_int32 (const char *what,
+                            int32_t *i);
+
+
+/**
+ * Create the specification to read an (u)int64_t.
+ *
+ * @param what describes what is being read (for error message creation)
+ * @param i where to store the data
+ * @return the read spec
+ */
+struct GNUNET_BIO_ReadSpec
+GNUNET_BIO_read_spec_int64 (const char *what,
+                            int64_t *i);
+
+
+/**
+ * Create the specification to read a float.
+ *
+ * @param what describes what is being read (for error message creation)
+ * @param f address of float to read
+ */
+struct GNUNET_BIO_ReadSpec
+GNUNET_BIO_read_spec_float(const char *what, float *f);
+
+
+/**
+ * Create the specification to read a double.
+ *
+ * @param what describes what is being read (for error message creation)
+ * @param f address of double to read
+ */
+struct GNUNET_BIO_ReadSpec
+GNUNET_BIO_read_spec_double(const char *what, double *f);
+
+
+/**
+ * Execute the read specifications in order.
+ *
+ * @param h the IO handle to read from
+ * @param rs array of read specs
+ *        the last element must be #GNUNET_BIO_read_spec_end
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
+ */
+int
+GNUNET_BIO_read_spec_commit (struct GNUNET_BIO_ReadHandle *h,
+                             struct GNUNET_BIO_ReadSpec *rs);
+
+
+/******************************* WRITE SPEC API *****************************/
+
+
+/**
+ * Function used to serialize data from a buffer and write it to @a h.
+ *
+ * @param cls closure (can be NULL)
+ * @param h the IO handle to write to
+ * @param what what is being written (for error message creation)
+ * @param source the data to write
+ * @param source_size how many bytes should be written
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
+ */
+typedef int
+(*GNUNET_BIO_WriteHandler) (void *cls,
+                            struct GNUNET_BIO_WriteHandle *h,
+                            const char *what,
+                            void *source,
+                            size_t source_size);
+
+
+/**
+ * Structure specifying a writing operation on an IO handle.
+ */
+struct GNUNET_BIO_WriteSpec
+{
+  /**
+   * Function performing data serialization.
+   */
+  GNUNET_BIO_WriteHandler wh;
+
+  /**
+   * Closure for @e rh. Can be NULL.
+   */
+  void *cls;
+
+  /**
+   * What is being read (for error message creation)
+   */
+  const char *what;
+
+  /**
+   * Source buffer. The data in this buffer will be written to the handle.
+   */
+  void *source;
+
+  /**
+   * Size of @e source. If it's smaller than the real size of @e source, only
+   * this many bytes will be written.
+   */
+  size_t source_size;
+};
+
+
+/**
+ * End of specifications marker.
+ */
+#define GNUNET_BIO_write_spec_end()             \
+  { NULL, NULL, NULL, NULL, 0 }
+
+
+/**
+ * Create the specification to read some bytes.
+ *
+ * @param what describes what is being written (for error message creation)
+ * @param source the data to write
+ * @param size how many bytes should be written
+ * @return the write spec
+ */
+struct GNUNET_BIO_WriteSpec
+GNUNET_BIO_write_spec_object (const char *what,
+                              void *source,
+                              size_t size);
+
+
+/**
+ * Create the specification to write a 0-terminated string.
+ *
+ * @param what describes what is being read (for error message creation)
+ * @param s string to write (can be NULL)
+ * @return the read spec
+ */
+struct GNUNET_BIO_WriteSpec
+GNUNET_BIO_write_spec_string (const char *what,
+                              const char *s);
+
+
+/**
+ * Create the specification to write a metadata container.
+ *
+ * @param what what is being written (for error message creation)
+ * @param m metadata to write
+ * @return the write spec
+ */
+struct GNUNET_BIO_WriteSpec
+GNUNET_BIO_write_spec_meta_data (const char *what,
+                                 const struct GNUNET_CONTAINER_MetaData *m);
+
+
+/**
+ * Create the specification to write an (u)int32_t.
+ *
+ * @param what describes what is being written (for error message creation)
+ * @param i pointer to a 32-bit integer
+ * @return the write spec
+ */
+struct GNUNET_BIO_WriteSpec
+GNUNET_BIO_write_spec_int32 (const char *what,
+                             int32_t *i);
+
+
+/**
+ * Create the specification to write an (u)int64_t.
+ *
+ * @param what describes what is being written (for error message creation)
+ * @param i pointer to a 64-bit integer
+ * @return the write spec
+ */
+struct GNUNET_BIO_WriteSpec
+GNUNET_BIO_write_spec_int64 (const char *what,
+                             int64_t *i);
+
+
+/**
+ * Create the specification to write a float.
+ *
+ * @param what describes what is being written (for error message creation)
+ * @param f pointer to a float
+ * @return the write spec
+ */
+struct GNUNET_BIO_WriteSpec
+GNUNET_BIO_write_spec_float(const char *what, float *f);
+
+
+/**
+ * Create the specification to write an double.
+ *
+ * @param what describes what is being written (for error message creation)
+ * @param f pointer to a double
+ * @return the write spec
+ */
+struct GNUNET_BIO_WriteSpec
+GNUNET_BIO_write_spec_double(const char *what, double *f);
+
+
+/**
+ * Execute the write specifications in order.
+ *
+ * @param h the IO handle to write to
+ * @param ws array of write specs
+ *        the last element must be #GNUNET_BIO_write_spec_end
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
+ */
+int
+GNUNET_BIO_write_spec_commit (struct GNUNET_BIO_WriteHandle *h,
+                              struct GNUNET_BIO_WriteSpec *ws);
 
 
 #if 0                           /* keep Emacsens' auto-indent happy */
diff --git a/src/include/gnunet_buffer_lib.h b/src/include/gnunet_buffer_lib.h
index c0ae06d77..e23536ab2 100644
--- a/src/include/gnunet_buffer_lib.h
+++ b/src/include/gnunet_buffer_lib.h
@@ -164,6 +164,19 @@ char *
 GNUNET_buffer_reap_str (struct GNUNET_Buffer *buf);
 
 
+/**
+ * Clear the buffer and return its contents.
+ * The caller is responsible to eventually #GNUNET_free
+ * the returned data.
+ *
+ * @param buf the buffer to reap the contents from
+ * @param size where to store the size of the returned data
+ * @returns the data contained in the string
+ */
+void *
+GNUNET_buffer_reap (struct GNUNET_Buffer *buf, size_t *size);
+
+
 /**
  * Free the backing memory of the given buffer.
  * Does not free the memory of the buffer control structure,
diff --git a/src/nse/gnunet-service-nse.c b/src/nse/gnunet-service-nse.c
index 793f60694..411f533a5 100644
--- a/src/nse/gnunet-service-nse.c
+++ b/src/nse/gnunet-service-nse.c
@@ -1001,7 +1001,7 @@ handle_p2p_estimate (void *cls,
     if (NULL != lh)
       GNUNET_TESTBED_LOGGER_write (lh, &t, sizeof(uint64_t));
     if (NULL != histogram)
-      GNUNET_BIO_write_int64 (histogram, t);
+      GNUNET_BIO_write_int64 (histogram, "histogram-time", t);
   }
 #endif
   GNUNET_STATISTICS_update (stats, "# flood messages received", 1, GNUNET_NO);
@@ -1299,7 +1299,7 @@ shutdown_task (void *cls)
   }
   if (NULL != histogram)
   {
-    GNUNET_BIO_write_close (histogram);
+    GNUNET_BIO_write_close (histogram, NULL);
     histogram = NULL;
   }
 #endif
@@ -1453,7 +1453,7 @@ run (void *cls,
       GNUNET_assert (
         0 < GNUNET_asprintf (&histogram_fn, "%s/timestamps", histogram_dir));
       GNUNET_free (histogram_dir);
-      histogram = GNUNET_BIO_write_open (histogram_fn);
+      histogram = GNUNET_BIO_write_open_file (histogram_fn);
       if (NULL == histogram)
         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                     "Unable to open histogram file `%s'\n",
diff --git a/src/statistics/gnunet-service-statistics.c 
b/src/statistics/gnunet-service-statistics.c
index 5d58c3743..d40f74aaf 100644
--- a/src/statistics/gnunet-service-statistics.c
+++ b/src/statistics/gnunet-service-statistics.c
@@ -263,7 +263,7 @@ save ()
     return;
   }
   (void) GNUNET_DISK_directory_create_for_file (fn);
-  wh = GNUNET_BIO_write_open (fn);
+  wh = GNUNET_BIO_write_open_file (fn);
   total = 0;
   while (NULL != (se = sub_head))
   {
@@ -290,10 +290,10 @@ save ()
         msg->flags =
           htonl (pos->persistent ? GNUNET_STATISTICS_SETFLAG_PERSISTENT : 0);
         msg->value = GNUNET_htonll (pos->value);
-        if (GNUNET_OK != GNUNET_BIO_write (wh, msg, size))
+        if (GNUNET_OK != GNUNET_BIO_write (wh, "statistics-save-msg", msg, 
size))
         {
           GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "write", fn);
-          if (GNUNET_OK != GNUNET_BIO_write_close (wh))
+          if (GNUNET_OK != GNUNET_BIO_write_close (wh, NULL))
             GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "close", fn);
           wh = NULL;
         }
@@ -309,7 +309,7 @@ save ()
   }
   if (NULL != wh)
   {
-    if (GNUNET_OK != GNUNET_BIO_write_close (wh))
+    if (GNUNET_OK != GNUNET_BIO_write_close (wh, NULL))
       GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "close", fn);
     if (0 == total)
       GNUNET_break (0 == unlink (fn));
@@ -964,7 +964,7 @@ load ()
     return;
   }
   buf = GNUNET_malloc (fsize);
-  rh = GNUNET_BIO_read_open (fn);
+  rh = GNUNET_BIO_read_open_file (fn);
   if (! rh)
   {
     GNUNET_free (buf);
diff --git a/src/testbed-logger/gnunet-service-testbed-logger.c 
b/src/testbed-logger/gnunet-service-testbed-logger.c
index 4e0a3cd34..81652fa4f 100644
--- a/src/testbed-logger/gnunet-service-testbed-logger.c
+++ b/src/testbed-logger/gnunet-service-testbed-logger.c
@@ -85,6 +85,7 @@ handle_log_msg (void *cls,
 
   ms = ntohs (msg->size) - sizeof(struct GNUNET_MessageHeader);
   GNUNET_BIO_write (bio,
+                    "testbed-logger-handle-log-msg",
                     &msg[1],
                     ms);
   GNUNET_SERVICE_client_continue (client);
@@ -108,7 +109,7 @@ shutdown_task (void *cls)
     return;
   }
   GNUNET_break (GNUNET_OK ==
-                GNUNET_BIO_write_close (bio));
+                GNUNET_BIO_write_close (bio, NULL));
 }
 
 
@@ -202,7 +203,7 @@ logger_run (void *cls,
                    (intmax_t) pid);
   GNUNET_free (hname);
   GNUNET_free (dir);
-  if (NULL == (bio = GNUNET_BIO_write_open (fn)))
+  if (NULL == (bio = GNUNET_BIO_write_open_file (fn)))
   {
     GNUNET_free (fn);
     GNUNET_SCHEDULER_shutdown ();
diff --git a/src/testbed/gnunet-service-testbed_cpustatus.c 
b/src/testbed/gnunet-service-testbed_cpustatus.c
index e96449def..2d490ba8c 100644
--- a/src/testbed/gnunet-service-testbed_cpustatus.c
+++ b/src/testbed/gnunet-service-testbed_cpustatus.c
@@ -568,7 +568,7 @@ sample_load_task (void *cls)
                          ld_cpu, ld_disk, mem_usage, nproc);
   if (0 < nbs)
   {
-    GNUNET_BIO_write (bw, str, nbs);
+    GNUNET_BIO_write (bw, "sample load task", str, nbs);
   }
   else
     GNUNET_break (0);
@@ -612,7 +612,7 @@ GST_stats_init (const struct GNUNET_CONFIGURATION_Handle 
*cfg)
                           hostname, (intmax_t) getpid ());
   GNUNET_free (stats_dir);
   GNUNET_free (hostname);
-  if (NULL == (bw = GNUNET_BIO_write_open (fn)))
+  if (NULL == (bw = GNUNET_BIO_write_open_file (fn)))
   {
     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                 _ ("Cannot open %s for writing load statistics.  "
@@ -656,7 +656,7 @@ GST_stats_destroy ()
     GNUNET_SCHEDULER_cancel (sample_load_task_id);
     sample_load_task_id = NULL;
   }
-  GNUNET_break (GNUNET_OK == GNUNET_BIO_write_close (bw));
+  GNUNET_break (GNUNET_OK == GNUNET_BIO_write_close (bw, NULL));
   bw = NULL;
 }
 
diff --git a/src/util/bio.c b/src/util/bio.c
index e05258f73..ce15f073b 100644
--- a/src/util/bio.c
+++ b/src/util/bio.c
@@ -47,13 +47,38 @@
 #define MAX_META_DATA (1024 * 1024)
 
 
+/**
+ * Enum used internally to know how buffering is handled.
+ *
+ * The idea is that by using an enum, BIO can be extended to support other
+ * kinds of "backend" for buffering (or just formatted I/O.)
+ */
+enum IOType
+{
+  /**
+   * The handle uses a file to read/write data.
+   */
+  IO_FILE = 0,
+
+  /**
+   * The data is stored entirely in memory.
+   */
+  IO_BUFFER,
+};
+
+
 /**
  * Handle for buffered reading.
  */
 struct GNUNET_BIO_ReadHandle
 {
   /**
-   * Underlying file abstraction.
+   * The "backend" type.
+   */
+  enum IOType type;
+
+  /**
+   * Handle to a file on disk, if @e type is #IO_FILE.
    */
   struct GNUNET_DISK_FileHandle *fd;
 
@@ -63,12 +88,12 @@ struct GNUNET_BIO_ReadHandle
   char *emsg;
 
   /**
-   * I/O buffer.  Allocated at the end of the struct, do not free!
+   * I/O buffer.  Do @b not free!
    */
   char *buffer;
 
   /**
-   * Number of bytes available in read @e buffer.
+   * Number of bytes available in @e buffer.
    */
   size_t have;
 
@@ -91,7 +116,7 @@ struct GNUNET_BIO_ReadHandle
  * @return IO handle on success, NULL on error
  */
 struct GNUNET_BIO_ReadHandle *
-GNUNET_BIO_read_open (const char *fn)
+GNUNET_BIO_read_open_file (const char *fn)
 {
   struct GNUNET_DISK_FileHandle *fd;
   struct GNUNET_BIO_ReadHandle *h;
@@ -100,6 +125,7 @@ GNUNET_BIO_read_open (const char *fn)
   if (NULL == fd)
     return NULL;
   h = GNUNET_malloc (sizeof(struct GNUNET_BIO_ReadHandle) + BIO_BUFFER_SIZE);
+  h->type = IO_FILE;
   h->buffer = (char *) &h[1];
   h->size = BIO_BUFFER_SIZE;
   h->fd = fd;
@@ -108,11 +134,32 @@ GNUNET_BIO_read_open (const char *fn)
 
 
 /**
- * Close an open file.  Reports if any errors reading
+ * Create a handle from an existing allocated buffer.
+ *
+ * @param buffer the buffer to use as source
+ * @param size the total size in bytes of the buffer
+ * @return IO handle on sucess, NULL on error
+ */
+struct GNUNET_BIO_ReadHandle *
+GNUNET_BIO_read_open_buffer (void *buffer, size_t size)
+{
+  struct GNUNET_BIO_ReadHandle *h;
+
+  h = GNUNET_new (struct GNUNET_BIO_ReadHandle);
+  h->type = IO_BUFFER;
+  h->buffer = buffer;
+  h->size = size;
+  return h;
+}
+
+
+/**
+ * Close an open handle.  Reports if any errors reading
  * from the file were encountered.
  *
  * @param h file handle
- * @param emsg set to the error message
+ * @param emsg set to the (allocated) error message
+ *        if the handle has an error message, the return value is 
#GNUNET_SYSERR
  * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
  */
 int
@@ -121,60 +168,63 @@ GNUNET_BIO_read_close (struct GNUNET_BIO_ReadHandle *h, 
char **emsg)
   int err;
 
   err = (NULL == h->emsg) ? GNUNET_OK : GNUNET_SYSERR;
-  if (emsg != NULL)
+  if (NULL != emsg)
     *emsg = h->emsg;
   else
     GNUNET_free_non_null (h->emsg);
-  GNUNET_DISK_file_close (h->fd);
+  switch (h->type)
+  {
+  case IO_FILE:
+    GNUNET_DISK_file_close (h->fd);
+    break;
+  case IO_BUFFER:
+    break;
+  default:
+    break;
+  }
   GNUNET_free (h);
   return err;
 }
 
 
 /**
- * Read the contents of a binary file into a buffer.
+ * Function used internally to read the contents of a file into a buffer.
  *
- * @param h handle to an open file
+ * @param h the IO handle to read from
  * @param what describes what is being read (for error message creation)
- * @param result the buffer to write the result to
+ * @param result the buffer to write the data to
  * @param len the number of bytes to read
- * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
  */
-int
-GNUNET_BIO_read (struct GNUNET_BIO_ReadHandle *h,
-                 const char *what,
-                 void *result,
-                 size_t len)
+static int
+read_from_file (struct GNUNET_BIO_ReadHandle *h,
+                const char *what,
+                char *result,
+                size_t len)
 {
-  char *dst = result;
+  size_t pos = 0;
   size_t min;
-  size_t pos;
   ssize_t ret;
 
-  if (NULL != h->emsg)
-    return GNUNET_SYSERR;
-  pos = 0;
   do
   {
-    /* first, use buffer */
     min = h->have - h->pos;
-    if (min > 0)
+    if (0 < min)
     {
-      if (min > len - pos)
+      if (len - pos < min)
         min = len - pos;
-      GNUNET_memcpy (&dst[pos], &h->buffer[h->pos], min);
+      GNUNET_memcpy (&result[pos], &h->buffer[h->pos], min);
       h->pos += min;
       pos += min;
     }
-    if (pos == len)
-      return GNUNET_OK;   /* done! */
+    if (len == pos)
+      return GNUNET_OK;
     GNUNET_assert (((off_t) h->have) == h->pos);
-    /* fill buffer */
     ret = GNUNET_DISK_file_read (h->fd, h->buffer, h->size);
     if (-1 == ret)
     {
       GNUNET_asprintf (&h->emsg,
-                       _ ("Error reading `%s': %s"),
+                       _ ("Error reading `%s' from file: %s"),
                        what,
                        strerror (errno));
       return GNUNET_SYSERR;
@@ -182,7 +232,7 @@ GNUNET_BIO_read (struct GNUNET_BIO_ReadHandle *h,
     if (0 == ret)
     {
       GNUNET_asprintf (&h->emsg,
-                       _ ("Error reading `%s': %s"),
+                       _ ("Error reading `%s' from file: %s"),
                        what,
                        _ ("End of file"));
       return GNUNET_SYSERR;
@@ -190,41 +240,84 @@ GNUNET_BIO_read (struct GNUNET_BIO_ReadHandle *h,
     h->pos = 0;
     h->have = ret;
   }
-  while (pos < len);   /* should always be true */
+  while (pos < len);
   return GNUNET_OK;
 }
 
 
 /**
- * Read the contents of a binary file into a buffer.
+ * Function used internally to read the content of a buffer into a buffer.
  *
- * @param h handle to an open file
- * @param file name of the source file
- * @param line line number in the source file
+ * @param h the IO handle to read from
+ * @param what describes what is being read (for error message creation)
+ * @param result the buffer to write the result to
+ * @param len the number of bytes to read
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
+ */
+static int
+read_from_buffer (struct GNUNET_BIO_ReadHandle *h,
+                  const char *what,
+                  char *result,
+                  size_t len)
+{
+  if (h->size < len || h->size - h->pos < len)
+  {
+    GNUNET_asprintf (&h->emsg,
+                     _ ("Error while reading `%s' from buffer: %s"),
+                     what,
+                     _ ("Not enough data left"));
+    return GNUNET_SYSERR;
+  }
+  GNUNET_memcpy (result, h->buffer + h->pos, len);
+  h->pos += len;
+  return GNUNET_OK;
+}
+
+
+/**
+ * Read some contents into a buffer.
+ *
+ * @param h the IO handle to read from
+ * @param what describes what is being read (for error message creation)
  * @param result the buffer to write the result to
  * @param len the number of bytes to read
  * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
  */
 int
-GNUNET_BIO_read_fn (struct GNUNET_BIO_ReadHandle *h,
-                    const char *file,
-                    int line,
-                    void *result,
-                    size_t len)
+GNUNET_BIO_read (struct GNUNET_BIO_ReadHandle *h,
+                 const char *what,
+                 void *result,
+                 size_t len)
 {
-  char what[PATH_MAX + 1024];
+  char *dst = result;
 
-  GNUNET_snprintf (what, sizeof(what), "%s:%d", file, line);
-  return GNUNET_BIO_read (h, what, result, len);
+  if (NULL != h->emsg)
+    return GNUNET_SYSERR;
+
+  if (0 == len)
+    return GNUNET_OK;
+
+  switch (h->type)
+  {
+  case IO_FILE:
+    return read_from_file (h, what, dst, len);
+  case IO_BUFFER:
+    return read_from_buffer (h, what, dst, len);
+  default:
+    GNUNET_asprintf (&h->emsg,
+                     _ ("Invalid handle type while reading `%s'"),
+                     what);
+    return GNUNET_SYSERR;
+  }
 }
 
 
 /**
- * Read 0-terminated string from a file.
+ * Read 0-terminated string.
  *
- * @param h handle to an open file
+ * @param h the IO handle to read from
  * @param what describes what is being read (for error message creation)
- * @param result the buffer to store a pointer to the (allocated) string to
+ * @param result where to store the pointer to the (allocated) string
  *        (note that *result could be set to NULL as well)
  * @param max_length maximum allowed length for the string
  * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
@@ -238,10 +331,21 @@ GNUNET_BIO_read_string (struct GNUNET_BIO_ReadHandle *h,
   char *buf;
   uint32_t big;
 
-  if (GNUNET_OK != GNUNET_BIO_read_int32 (h, &big))
+  if (GNUNET_OK != GNUNET_BIO_read_int32 (h,
+                                          _ ("string length"),
+                                          (int32_t *) &big))
   {
-    GNUNET_free_non_null (h->emsg);
-    GNUNET_asprintf (&h->emsg, _ ("Error reading length of string `%s'"), 
what);
+    char *tmp = h->emsg;
+    if (NULL != tmp)
+      GNUNET_asprintf (&h->emsg,
+                       _ ("%s (while reading `%s')"),
+                       tmp,
+                       what);
+    else
+      GNUNET_asprintf (&h->emsg,
+                       _ ("Error reading length of string `%s'"),
+                       what);
+    GNUNET_free_non_null (tmp);
     return GNUNET_SYSERR;
   }
   if (0 == big)
@@ -274,7 +378,7 @@ GNUNET_BIO_read_string (struct GNUNET_BIO_ReadHandle *h,
 
 
 /**
- * Read metadata container from a file.
+ * Read a metadata container.
  *
  * @param h handle to an open file
  * @param what describes what is being read (for error message creation)
@@ -290,20 +394,23 @@ GNUNET_BIO_read_meta_data (struct GNUNET_BIO_ReadHandle 
*h,
   char *buf;
   struct GNUNET_CONTAINER_MetaData *meta;
 
-  if (GNUNET_OK != GNUNET_BIO_read_int32 (h, (int32_t *) &size))
+  if (GNUNET_OK != GNUNET_BIO_read_int32 (h,
+                                          _ ("metadata length"),
+                                          (int32_t *) &size))
     return GNUNET_SYSERR;
-  if (size == 0)
+  if (0 == size)
   {
     *result = NULL;
     return GNUNET_OK;
   }
-  if (size > MAX_META_DATA)
+  if (MAX_META_DATA < size)
   {
-    GNUNET_asprintf (&h->emsg,
-                     _ ("Serialized metadata `%s' larger than allowed 
(%u>%u)"),
-                     what,
-                     size,
-                     MAX_META_DATA);
+    GNUNET_asprintf (
+      &h->emsg,
+      _ ("Serialized metadata `%s' larger than allowed (%u > %u)"),
+      what,
+      size,
+      MAX_META_DATA);
     return GNUNET_SYSERR;
   }
   buf = GNUNET_malloc (size);
@@ -316,7 +423,7 @@ GNUNET_BIO_read_meta_data (struct GNUNET_BIO_ReadHandle *h,
   if (NULL == meta)
   {
     GNUNET_free (buf);
-    GNUNET_asprintf (&h->emsg, _ ("Metadata `%s' failed to deserialize"), 
what);
+    GNUNET_asprintf (&h->emsg, _ ("Failed to deserialize metadata `%s'"), 
what);
     return GNUNET_SYSERR;
   }
   GNUNET_free (buf);
@@ -324,25 +431,56 @@ GNUNET_BIO_read_meta_data (struct GNUNET_BIO_ReadHandle 
*h,
   return GNUNET_OK;
 }
 
+/**
+ * Read a float.
+ *
+ * @param h the IO handle to read from
+ * @param what describes what is being read (for error message creation)
+ * @param f address of float to read
+ */
+int
+GNUNET_BIO_read_float(struct GNUNET_BIO_ReadHandle *h,
+                      const char *what,
+                      float *f)
+{
+  int32_t *i = (int32_t *) f;
+  return GNUNET_BIO_read_int32 (h, what, i);
+}
+
+
+/**
+ * Read a double.
+ *
+ * @param h the IO handle to read from
+ * @param what describes what is being read (for error message creation)
+ * @param f address of double to read
+ */
+int
+GNUNET_BIO_read_double(struct GNUNET_BIO_ReadHandle *h,
+                       const char *what,
+                       double *f)
+{
+  int64_t *i = (int64_t *) f;
+  return GNUNET_BIO_read_int64 (h, what, i);
+}
+
 
 /**
  * Read an (u)int32_t.
  *
- * @param h hande to open file
- * @param file name of the source file
- * @param line line number in the source file
- * @param i address of 32-bit integer to read
+ * @param h the IO handle to read from
+ * @param what describes what is being read (for error message creation)
+ * @param i where to store the data
  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
  */
 int
-GNUNET_BIO_read_int32__ (struct GNUNET_BIO_ReadHandle *h,
-                         const char *file,
-                         int line,
-                         int32_t *i)
+GNUNET_BIO_read_int32 (struct GNUNET_BIO_ReadHandle *h,
+                       const char *what,
+                       int32_t *i)
 {
   int32_t big;
 
-  if (GNUNET_OK != GNUNET_BIO_read_fn (h, file, line, &big, sizeof(int32_t)))
+  if (GNUNET_OK != GNUNET_BIO_read (h, what, &big, sizeof(int32_t)))
     return GNUNET_SYSERR;
   *i = ntohl (big);
   return GNUNET_OK;
@@ -352,21 +490,19 @@ GNUNET_BIO_read_int32__ (struct GNUNET_BIO_ReadHandle *h,
 /**
  * Read an (u)int64_t.
  *
- * @param h hande to open file
- * @param file name of the source file
- * @param line line number in the source file
- * @param i address of 64-bit integer to read
+ * @param h the IO handle to read from
+ * @param what describes what is being read (for error message creation)
+ * @param i where to store the data
  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
  */
 int
-GNUNET_BIO_read_int64__ (struct GNUNET_BIO_ReadHandle *h,
-                         const char *file,
-                         int line,
-                         int64_t *i)
+GNUNET_BIO_read_int64 (struct GNUNET_BIO_ReadHandle *h,
+                       const char *what,
+                       int64_t *i)
 {
   int64_t big;
 
-  if (GNUNET_OK != GNUNET_BIO_read_fn (h, file, line, &big, sizeof(int64_t)))
+  if (GNUNET_OK != GNUNET_BIO_read (h, what, &big, sizeof(int64_t)))
     return GNUNET_SYSERR;
   *i = GNUNET_ntohll (big);
   return GNUNET_OK;
@@ -379,17 +515,29 @@ GNUNET_BIO_read_int64__ (struct GNUNET_BIO_ReadHandle *h,
 struct GNUNET_BIO_WriteHandle
 {
   /**
-   * Underlying file handle.
+   * The "backend" type.
+   */
+  enum IOType type;
+
+  /**
+   * Handle to a file on disk, if @e type is #IO_FILE.
    */
   struct GNUNET_DISK_FileHandle *fd;
 
   /**
-   * I/O buffer.  Do not free, allocated at the end of the struct.
+   * Error message, NULL if there were no errors.
    */
-  char *buffer;
+  char *emsg;
+
+  /**
+   * I/O buffer.
+   * This field is a void * because it is used to hold pointers to allocated
+   * structures or arrays and will be casted to the appropriate type.
+   */
+  void *buffer;
 
   /**
-   * Number of bytes already in @e buffer.
+   * Number of bytes available in @e buffer.
    */
   size_t have;
 
@@ -403,25 +551,26 @@ struct GNUNET_BIO_WriteHandle
 /**
  * Open a file for writing.
  *
- * @param fn file name to be opened
+ * @param fn name of the file to be opened
  * @return IO handle on success, NULL on error
  */
 struct GNUNET_BIO_WriteHandle *
-GNUNET_BIO_write_open (const char *fn)
+GNUNET_BIO_write_open_file (const char *fn)
 {
   struct GNUNET_DISK_FileHandle *fd;
   struct GNUNET_BIO_WriteHandle *h;
 
   fd =
     GNUNET_DISK_file_open (fn,
-                           GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_TRUNCATE
+                           GNUNET_DISK_OPEN_WRITE
+                           | GNUNET_DISK_OPEN_TRUNCATE
                            | GNUNET_DISK_OPEN_CREATE,
                            GNUNET_DISK_PERM_USER_READ
                            | GNUNET_DISK_PERM_USER_WRITE);
   if (NULL == fd)
     return NULL;
   h = GNUNET_malloc (sizeof(struct GNUNET_BIO_WriteHandle) + BIO_BUFFER_SIZE);
-  h->buffer = (char *) &h[1];
+  h->buffer = &h[1];
   h->size = BIO_BUFFER_SIZE;
   h->fd = fd;
   return h;
@@ -429,42 +578,94 @@ GNUNET_BIO_write_open (const char *fn)
 
 
 /**
- * Close an open file for writing.
+ * Create a handle backed by an in-memory buffer.
+ *
+ * @return IO handle on success, NULL on error
+ */
+struct GNUNET_BIO_WriteHandle *
+GNUNET_BIO_write_open_buffer (void)
+{
+  struct GNUNET_BIO_WriteHandle *h;
+
+  h = GNUNET_new (struct GNUNET_BIO_WriteHandle);
+  h->type = IO_BUFFER;
+  h->buffer = (void *) GNUNET_malloc (sizeof (struct GNUNET_Buffer));
+  return h;
+}
+
+
+/**
+ * Close an IO handle.
+ * If the handle was using a file, the file will be closed.
  *
  * @param h file handle
+ * @param emsg set to the (allocated) error message
+ *        if the handle has an error message, the return value is 
#GNUNET_SYSERR
  * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
  */
 int
-GNUNET_BIO_write_close (struct GNUNET_BIO_WriteHandle *h)
+GNUNET_BIO_write_close (struct GNUNET_BIO_WriteHandle *h, char **emsg)
 {
-  int ret;
+  int err;
 
-  ret = GNUNET_SYSERR;
-  if ((NULL != h->fd) && (GNUNET_OK == (ret = GNUNET_BIO_flush (h))))
-    GNUNET_DISK_file_close (h->fd);
+  err = (NULL == h->emsg) ? GNUNET_OK : GNUNET_SYSERR;
+  if (NULL != emsg)
+    *emsg = h->emsg;
+  else
+    GNUNET_free_non_null (h->emsg);
+  switch (h->type)
+  {
+  case IO_FILE:
+    if (NULL == h->fd)
+      return GNUNET_SYSERR;
+    if (GNUNET_OK != GNUNET_BIO_flush (h))
+    {
+      if (NULL != emsg)
+        *emsg = h->emsg;
+      else
+        GNUNET_free_non_null (h->emsg);
+      err = GNUNET_SYSERR;
+    }
+    else
+    {
+      GNUNET_DISK_file_close (h->fd);
+    }
+    break;
+  case IO_BUFFER:
+    GNUNET_buffer_clear ((struct GNUNET_Buffer *) h->buffer);
+    GNUNET_free (h->buffer);
+    break;
+  }
   GNUNET_free (h);
-  return ret;
+  return err;
 }
 
 
 /**
- * Force a buffered writer to flush its buffer
+ * Force a file-based buffered writer to flush its buffer.
+ * If the handle does not use a file, this function returs #GNUNET_OK
+ * without doing anything.
  *
- * @param h the writer handle
- * @return #GNUNET_OK upon success.  Upon failure #GNUNET_SYSERR is returned 
and
- *           the file is closed
+ * @param h the IO handle
+ * @return #GNUNET_OK upon success.  Upon failure #GNUNET_SYSERR is returned
+ *         and the file is closed
  */
 int
 GNUNET_BIO_flush (struct GNUNET_BIO_WriteHandle *h)
 {
   ssize_t ret;
 
+  if (IO_FILE != h->type)
+    return GNUNET_OK;
+
   ret = GNUNET_DISK_file_write (h->fd, h->buffer, h->have);
   if (ret != (ssize_t) h->have)
   {
     GNUNET_DISK_file_close (h->fd);
     h->fd = NULL;
-    return GNUNET_SYSERR;   /* error */
+    GNUNET_free_non_null (h->emsg);
+    GNUNET_asprintf (&h->emsg, _ ("Unable to flush buffer to file"));
+    return GNUNET_SYSERR;
   }
   h->have = 0;
   return GNUNET_OK;
@@ -472,96 +673,213 @@ GNUNET_BIO_flush (struct GNUNET_BIO_WriteHandle *h)
 
 
 /**
- * Write a buffer to a file.
+ * Get the IO handle's contents.
+ * If the handle doesn't use an in-memory buffer, this function returns
+ * #GNUNET_SYSERR.
  *
- * @param h handle to open file
- * @param buffer the data to write
- * @param n number of bytes to write
- * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
+ * @param h the IO handle
+ * @param emsg set to the (allocated) error message
+ *        if the handle has an error message the return value is #GNUNET_SYSERR
+ * @param contents where to store the pointer to the handle's contents
+ * @param size where to store the size of @e contents
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
  */
 int
-GNUNET_BIO_write (struct GNUNET_BIO_WriteHandle *h,
-                  const void *buffer,
-                  size_t n)
+GNUNET_BIO_get_buffer_contents (struct GNUNET_BIO_WriteHandle *h,
+                                char **emsg,
+                                void **contents,
+                                size_t *size)
+{
+  if (IO_BUFFER != h->type)
+    return GNUNET_SYSERR;
+  if (NULL == contents || NULL == size)
+    return GNUNET_SYSERR;
+  int ret = (NULL != h->emsg) ? GNUNET_SYSERR : GNUNET_OK;
+  if (NULL != emsg)
+    *emsg = h->emsg;
+  else
+    GNUNET_free_non_null (h->emsg);
+  *contents = GNUNET_buffer_reap ((struct GNUNET_Buffer *) h->buffer, size);
+  return ret;
+}
+
+
+/**
+ * Function used internally to write the contents of a buffer into a file.
+ *
+ * @param h the IO handle to write to
+ * @param what describes what is being written (for error message creation)
+ * @param source the buffer to write
+ * @param len the number of bytes to write
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
+ */
+static int
+write_to_file (struct GNUNET_BIO_WriteHandle *h,
+               const char *what,
+               const char *source,
+               size_t len)
 {
-  const char *src = buffer;
   size_t min;
-  size_t pos;
+  size_t pos = 0;
+  char *buffer = (char *) h->buffer;
 
   if (NULL == h->fd)
+  {
+    GNUNET_asprintf (&h->emsg,
+                     _ ("Error while writing `%s' to file: %s"),
+                     what,
+                     _ ("No associated file"));
     return GNUNET_SYSERR;
-  pos = 0;
+  }
+
   do
   {
-    /* first, just use buffer */
     min = h->size - h->have;
-    if (min > n - pos)
-      min = n - pos;
-    GNUNET_memcpy (&h->buffer[h->have], &src[pos], min);
+    if (len - pos < min)
+      min = len - pos;
+    GNUNET_memcpy (&buffer[h->have], &source[pos], min);
     pos += min;
     h->have += min;
-    if (pos == n)
-      return GNUNET_OK;   /* done */
+    if (len == pos)
+      return GNUNET_OK;
     GNUNET_assert (h->have == h->size);
     if (GNUNET_OK != GNUNET_BIO_flush (h))
-      return GNUNET_SYSERR;   /* error */
+    {
+      char *tmp = h->emsg;
+      GNUNET_asprintf (&h->emsg,
+                       _ ("Error while writing `%s' to file: %s"),
+                       what,
+                       tmp);
+      GNUNET_free_non_null (tmp);
+      return GNUNET_SYSERR;
+    }
   }
-  while (pos < n);   /* should always be true */
+  while (pos < len);
   GNUNET_break (0);
   return GNUNET_OK;
 }
 
 
 /**
- * Write a string to a file.
+ * Function used internally to write the contents of a buffer to another 
buffer.
+ *
+ * @param h the IO handle to write to
+ * @param what describes what is being written (for error message creation)
+ * @param source the buffer to write
+ * @param len the number of bytes to write
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
+ */
+static int
+write_to_buffer (struct GNUNET_BIO_WriteHandle *h,
+                 const char *what,
+                 const char *source,
+                 size_t len)
+{
+  GNUNET_buffer_write ((struct GNUNET_Buffer *) h->buffer, source, len);
+  h->have += len;
+  return GNUNET_OK;
+}
+
+
+/**
+ * Write a buffer to a handle.
+ *
+ * @param h the IO handle to write to
+ * @param what what is being written (for error message creation)
+ * @param buffer the data to write
+ * @param n number of bytes to write
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
+ */
+int
+GNUNET_BIO_write (struct GNUNET_BIO_WriteHandle *h,
+                  const char *what,
+                  const void *buffer,
+                  size_t n)
+{
+  const char *src = buffer;
+
+  if (NULL != h->emsg)
+    return GNUNET_SYSERR;
+
+  if (0 == n)
+    return GNUNET_OK;
+
+  switch (h->type)
+  {
+  case IO_FILE:
+    return write_to_file (h, what, src, n);
+  case IO_BUFFER:
+    return write_to_buffer (h, what, src, n);
+  default:
+    GNUNET_asprintf (&h->emsg,
+                     _ ("Invalid handle type while writing `%s'"),
+                     what);
+    return GNUNET_SYSERR;
+  }
+}
+
+
+/**
+ * Write a 0-terminated string.
  *
- * @param h handle to open file
+ * @param h the IO handle to write to
+ * @param what what is being written (for error message creation)
  * @param s string to write (can be NULL)
  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
  */
 int
-GNUNET_BIO_write_string (struct GNUNET_BIO_WriteHandle *h, const char *s)
+GNUNET_BIO_write_string (struct GNUNET_BIO_WriteHandle *h,
+                         const char *what,
+                         const char *s)
 {
   uint32_t slen;
 
   slen = (uint32_t) ((s == NULL) ? 0 : strlen (s) + 1);
-  if (GNUNET_OK != GNUNET_BIO_write_int32 (h, slen))
+  if (GNUNET_OK != GNUNET_BIO_write_int32 (h, _ ("string length"), slen))
     return GNUNET_SYSERR;
   if (0 != slen)
-    return GNUNET_BIO_write (h, s, slen - 1);
+    return GNUNET_BIO_write (h, what, s, slen - 1);
   return GNUNET_OK;
 }
 
 
 /**
- * Write metadata container to a file.
+ * Write a metadata container.
  *
- * @param h handle to open file
+ * @param h the IO handle to write to
+ * @param what what is being written (for error message creation)
  * @param m metadata to write
  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
  */
 int
 GNUNET_BIO_write_meta_data (struct GNUNET_BIO_WriteHandle *h,
+                            const char *what,
                             const struct GNUNET_CONTAINER_MetaData *m)
 {
   ssize_t size;
   char *buf;
 
   if (m == NULL)
-    return GNUNET_BIO_write_int32 (h, 0);
+    return GNUNET_BIO_write_int32 (h, _ ("metadata length"), 0);
   buf = NULL;
   size = GNUNET_CONTAINER_meta_data_serialize (
     m,
     &buf,
     MAX_META_DATA,
     GNUNET_CONTAINER_META_DATA_SERIALIZE_PART);
-  if (size == -1)
+  if (-1 == size)
   {
     GNUNET_free (buf);
+    GNUNET_free_non_null (h->emsg);
+    GNUNET_asprintf (&h->emsg,
+                     _ ("Failed to serialize metadata `%s'"),
+                     what);
     return GNUNET_SYSERR;
   }
-  if ((GNUNET_OK != GNUNET_BIO_write_int32 (h, (uint32_t) size)) ||
-      (GNUNET_OK != GNUNET_BIO_write (h, buf, size)))
+  if ((GNUNET_OK != GNUNET_BIO_write_int32 (h,
+                                            _ ("metadata length"),
+                                            (uint32_t) size))
+      || (GNUNET_OK != GNUNET_BIO_write (h, what, buf, size)))
   {
     GNUNET_free (buf);
     return GNUNET_SYSERR;
@@ -571,37 +889,670 @@ GNUNET_BIO_write_meta_data (struct 
GNUNET_BIO_WriteHandle *h,
 }
 
 
+/**
+ * Write a float.
+ *
+ * @param h the IO handle to write to
+ * @param what what is being written (for error message creation)
+ * @param f float to write
+ */
+int
+GNUNET_BIO_write_float(struct GNUNET_BIO_WriteHandle *h,
+                       const char *what,
+                       float f)
+{
+  int32_t i = f;
+  return GNUNET_BIO_write_int32 (h, what, i);
+}
+
+
+/**
+ * Write a double.
+ *
+ * @param h the IO handle to write to
+ * @param what what is being written (for error message creation)
+ * @param f double to write
+ */
+int
+GNUNET_BIO_write_double(struct GNUNET_BIO_WriteHandle *h,
+                        const char *what,
+                        double f)
+{
+  int64_t i = f;
+  return GNUNET_BIO_write_int64 (h, what, i);
+}
+
+
 /**
  * Write an (u)int32_t.
  *
- * @param h hande to open file
+ * @param h the IO handle to write to
+ * @param what what is being written (for error message creation)
  * @param i 32-bit integer to write
  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
  */
 int
-GNUNET_BIO_write_int32 (struct GNUNET_BIO_WriteHandle *h, int32_t i)
+GNUNET_BIO_write_int32 (struct GNUNET_BIO_WriteHandle *h,
+                        const char *what,
+                        int32_t i)
 {
   int32_t big;
 
   big = htonl (i);
-  return GNUNET_BIO_write (h, &big, sizeof(int32_t));
+  return GNUNET_BIO_write (h, what, &big, sizeof(int32_t));
 }
 
 
 /**
  * Write an (u)int64_t.
  *
- * @param h hande to open file
+ * @param h the IO handle to write to
+ * @param what what is being written (for error message creation)
  * @param i 64-bit integer to write
  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
  */
 int
-GNUNET_BIO_write_int64 (struct GNUNET_BIO_WriteHandle *h, int64_t i)
+GNUNET_BIO_write_int64 (struct GNUNET_BIO_WriteHandle *h,
+                        const char *what,
+                        int64_t i)
 {
   int64_t big;
 
   big = GNUNET_htonll (i);
-  return GNUNET_BIO_write (h, &big, sizeof(int64_t));
+  return GNUNET_BIO_write (h, what, &big, sizeof(int64_t));
+}
+
+
+/**
+ * Function used internally to read some bytes from within a read spec.
+ *
+ * @param cls ignored, always NULL
+ * @param h the IO handle to read from
+ * @param what what is being read (for error message creation)
+ * @param target where to store the data
+ * @param target_size how many bytes to read
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
+ */
+static int
+read_spec_handler_object (void *cls,
+                          struct GNUNET_BIO_ReadHandle *h,
+                          const char *what,
+                          void *target,
+                          size_t target_size)
+{
+  return GNUNET_BIO_read (h, what, target, target_size);
+}
+
+
+/**
+ * Create the specification to read a certain amount of bytes.
+ *
+ * @param what describes what is being read (for error message creation)
+ * @param result the buffer to write the result to
+ * @param len the number of bytes to read
+ * @return the read spec
+ */
+struct GNUNET_BIO_ReadSpec
+GNUNET_BIO_read_spec_object (const char *what,
+                             void *result,
+                             size_t len)
+{
+  struct GNUNET_BIO_ReadSpec rs = {
+    .rh = &read_spec_handler_object,
+    .cls = NULL,
+    .what = what,
+    .target = result,
+    .size = len,
+  };
+
+  return rs;
+}
+
+
+/**
+ * Function used interally to read a string from within a read spec.
+ *
+ * @param cls ignored, always NULL
+ * @param h the IO handle to read from
+ * @param what what is being read (for error message creation)
+ * @param target where to store the data
+ * @param target_size how many bytes to read
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
+ */
+static int
+read_spec_handler_string (void *cls,
+                          struct GNUNET_BIO_ReadHandle *h,
+                          const char *what,
+                          void *target,
+                          size_t target_size)
+{
+  char **result = target;
+  return GNUNET_BIO_read_string (h, what, result, target_size);
+}
+
+
+/**
+ * Create the specification to read a 0-terminated string.
+ *
+ * @param what describes what is being read (for error message creation)
+ * @param result where to store the pointer to the (allocated) string
+ *        (note that *result could be set to NULL as well)
+ * @param max_length maximum allowed length for the string
+ * @return the read spec
+ */
+struct GNUNET_BIO_ReadSpec
+GNUNET_BIO_read_spec_string (const char *what,
+                             char **result,
+                             size_t max_length)
+{
+  struct GNUNET_BIO_ReadSpec rs = {
+    .rh = &read_spec_handler_string,
+    .cls = NULL,
+    .target = result,
+    .size = max_length,
+  };
+
+  return rs;
+}
+
+
+/**
+ * Function used internally to read a metadata container from within a read
+ * spec.
+ *
+ * @param cls ignored, always NULL
+ * @param h the IO handle to read from
+ * @param what what is being read (for error message creation)
+ * @param target where to store the data
+ * @param target_size ignored
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
+ */
+static int
+read_spec_handler_meta_data (void *cls,
+                             struct GNUNET_BIO_ReadHandle *h,
+                             const char *what,
+                             void *target,
+                             size_t target_size)
+{
+  struct GNUNET_CONTAINER_MetaData **result = target;
+  return GNUNET_BIO_read_meta_data (h, what, result);
+}
+
+
+/**
+ * Create the specification to read a metadata container.
+ *
+ * @param what describes what is being read (for error message creation)
+ * @param result the buffer to store a pointer to the (allocated) metadata
+ * @return the read spec
+ */
+struct GNUNET_BIO_ReadSpec
+GNUNET_BIO_read_spec_meta_data (const char *what,
+                                struct GNUNET_CONTAINER_MetaData **result)
+{
+  struct GNUNET_BIO_ReadSpec rs = {
+    .rh = &read_spec_handler_meta_data,
+    .cls = NULL,
+    .target = result,
+    .size = 0,
+  };
+
+  return rs;
+}
+
+
+/**
+ * Function used internally to read an (u)int32_t from within a read spec.
+ *
+ * @param cls ignored, always NULL
+ * @param h the IO handle to read from
+ * @param what what is being read (for error message creation)
+ * @param target where to store the data
+ * @param target_size ignored
+ * @retun #GNUNET_OK on success, #GNUNET_SYSERR otherwise
+ */
+static int
+read_spec_handler_int32 (void *cls,
+                         struct GNUNET_BIO_ReadHandle *h,
+                         const char *what,
+                         void *target,
+                         size_t target_size)
+{
+  int32_t *result = target;
+  return GNUNET_BIO_read_int32 (h, what, result);
+}
+
+
+/**
+ * Create the specification to read an (u)int32_t.
+ *
+ * @param what describes what is being read (for error message creation)
+ * @param i where to store the data
+ * @return the read spec
+ */
+struct GNUNET_BIO_ReadSpec
+GNUNET_BIO_read_spec_int32 (const char *what,
+                            int32_t *i)
+{
+  struct GNUNET_BIO_ReadSpec rs = {
+    .rh = &read_spec_handler_int32,
+    .cls = NULL,
+    .target = i,
+    .size = 0,
+  };
+
+  return rs;
+}
+
+
+/**
+ * Function used internally to read an (u)int64_t from within a read spec.
+ *
+ * @param cls ignored, always NULL
+ * @param h the IO handle to read from
+ * @param what what is being read (for error message creation)
+ * @param target where to store the data
+ * @param target_size ignored
+ * @retun #GNUNET_OK on success, #GNUNET_SYSERR otherwise
+ */
+static int
+read_spec_handler_int64 (void *cls,
+                         struct GNUNET_BIO_ReadHandle *h,
+                         const char *what,
+                         void *target,
+                         size_t target_size)
+{
+  int64_t *result = target;
+  return GNUNET_BIO_read_int64 (h, what, result);
+}
+
+
+/**
+ * Create the specification to read an (u)int64_t.
+ *
+ * @param what describes what is being read (for error message creation)
+ * @param i where to store the data
+ * @return the read spec
+ */
+struct GNUNET_BIO_ReadSpec
+GNUNET_BIO_read_spec_int64 (const char *what,
+                            int64_t *i)
+{
+  struct GNUNET_BIO_ReadSpec rs = {
+    .rh = &read_spec_handler_int64,
+    .cls = NULL,
+    .target = i,
+    .size = 0,
+  };
+
+  return rs;
+}
+
+
+/**
+ * Create the specification to read a float.
+ *
+ * @param what describes what is being read (for error message creation)
+ * @param f address of float to read
+ */
+struct GNUNET_BIO_ReadSpec
+GNUNET_BIO_read_spec_float(const char *what, float *f)
+{
+  struct GNUNET_BIO_ReadSpec rs = {
+    .rh = &read_spec_handler_int32,
+    .cls = NULL,
+    .target = (int32_t *) f,
+    .size = 0,
+  };
+
+  return rs;
+}
+
+
+/**
+ * Create the specification to read a double.
+ *
+ * @param what describes what is being read (for error message creation)
+ * @param f address of double to read
+ */
+struct GNUNET_BIO_ReadSpec
+GNUNET_BIO_read_spec_double(const char *what, double *f)
+{
+  struct GNUNET_BIO_ReadSpec rs = {
+    .rh = &read_spec_handler_int64,
+    .cls = NULL,
+    .target = (int64_t *) f,
+    .size = 0,
+  };
+
+  return rs;
+}
+
+
+/**
+ * Execute the read specifications in order.
+ *
+ * @param h the IO handle to read from
+ * @param rs array of read specs
+ *        the last element must be #GNUNET_BIO_read_spec_end
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
+ */
+int
+GNUNET_BIO_read_spec_commit (struct GNUNET_BIO_ReadHandle *h,
+                             struct GNUNET_BIO_ReadSpec *rs)
+{
+  int ret = GNUNET_OK;
+
+  for (size_t i=0; NULL!=rs[i].rh; ++i)
+  {
+    ret = rs[i].rh (rs[i].cls, h, rs[i].what, rs[i].target, rs[i].size);
+    if (GNUNET_OK != ret)
+      return ret;
+  }
+
+  return ret;
+}
+
+
+/**
+ * Function used internally to write some bytes from within a write spec.
+ *
+ * @param cls ignored, always NULL
+ * @param h the IO handle to write to
+ * @param what what is being written (for error message creation)
+ * @param source the data to write
+ * @param source_size how many bytes to write
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
+ */
+static int
+write_spec_handler_object (void *cls,
+                           struct GNUNET_BIO_WriteHandle *h,
+                           const char *what,
+                           void *source,
+                           size_t source_size)
+{
+  return GNUNET_BIO_write (h, what, source, source_size);
+}
+
+
+/**
+ * Create the specification to read some bytes.
+ *
+ * @param what describes what is being written (for error message creation)
+ * @param source the data to write
+ * @param size how many bytes should be written
+ * @return the write spec
+ */
+struct GNUNET_BIO_WriteSpec
+GNUNET_BIO_write_spec_object (const char *what,
+                              void *source,
+                              size_t size)
+{
+  struct GNUNET_BIO_WriteSpec ws = {
+    .wh = &write_spec_handler_object,
+    .cls = NULL,
+    .what = what,
+    .source = source,
+    .source_size = size,
+  };
+
+  return ws;
+}
+
+
+/**
+ * Function used internally to write a 0-terminated string from within a write
+ * spec.
+ *
+ * @param cls ignored, always NULL
+ * @param h the IO handle to write to
+ * @param what what is being written (for error message creation)
+ * @param source the data to write
+ * @param source_size ignored
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
+ */
+static int
+write_spec_handler_string (void *cls,
+                           struct GNUNET_BIO_WriteHandle *h,
+                           const char *what,
+                           void *source,
+                           size_t source_size)
+{
+  const char *s = source;
+  return GNUNET_BIO_write_string (h, what, s);
+}
+
+
+/**
+ * Create the specification to write a 0-terminated string.
+ *
+ * @param what describes what is being read (for error message creation)
+ * @param s string to write (can be NULL)
+ * @return the read spec
+ */
+struct GNUNET_BIO_WriteSpec
+GNUNET_BIO_write_spec_string (const char *what,
+                              const char *s)
+{
+  struct GNUNET_BIO_WriteSpec ws = {
+    .wh = &write_spec_handler_string,
+    .cls = NULL,
+    .what = what,
+    .source = (void *) s,
+    .source_size = 0,
+  };
+
+  return ws;
+}
+
+
+/**
+ * Function used internally to write a metadata container from within a write
+ * spec.
+ *
+ * @param cls ignored, always NULL
+ * @param h the IO handle to write to
+ * @param what what is being written (for error message creation)
+ * @param source the data to write
+ * @param source_size ignored
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
+ */
+static int
+write_spec_handler_meta_data (void *cls,
+                              struct GNUNET_BIO_WriteHandle *h,
+                              const char *what,
+                              void *source,
+                              size_t source_size)
+{
+  const struct GNUNET_CONTAINER_MetaData *m = source;
+  return GNUNET_BIO_write_meta_data (h, what, m);
+}
+
+
+/**
+ * Create the specification to write a metadata container.
+ *
+ * @param what what is being written (for error message creation)
+ * @param m metadata to write
+ * @return the write spec
+ */
+struct GNUNET_BIO_WriteSpec
+GNUNET_BIO_write_spec_meta_data (const char *what,
+                                 const struct GNUNET_CONTAINER_MetaData *m)
+{
+  struct GNUNET_BIO_WriteSpec ws = {
+    .wh = &write_spec_handler_meta_data,
+    .cls = NULL,
+    .what = what,
+    .source = (void *) m,
+    .source_size = 0,
+  };
+
+  return ws;
+}
+
+
+/**
+ * Function used internally to write an (u)int32_t from within a write spec.
+ *
+ * @param cls ignored, always NULL
+ * @param h the IO handle to write to
+ * @param what what is being written (for error message creation)
+ * @param source the data to write
+ * @param source_size ignored
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
+ */
+static int
+write_spec_handler_int32 (void *cls,
+                          struct GNUNET_BIO_WriteHandle *h,
+                          const char *what,
+                          void *source,
+                          size_t source_size)
+{
+  int32_t i = *(int32_t *) source;
+  return GNUNET_BIO_write_int32 (h, what, i);
+}
+
+
+/**
+ * Create the specification to write an (u)int32_t.
+ *
+ * @param what describes what is being written (for error message creation)
+ * @param i pointer to a 32-bit integer
+ * @return the write spec
+ */
+struct GNUNET_BIO_WriteSpec
+GNUNET_BIO_write_spec_int32 (const char *what,
+                             int32_t *i)
+{
+  struct GNUNET_BIO_WriteSpec ws = {
+    .wh = &write_spec_handler_int32,
+    .cls = NULL,
+    .what = what,
+    .source = i,
+    .source_size = 0,
+  };
+
+  return ws;
+}
+
+
+/**
+ * Function used internally to write an (u)int64_t from within a write spec.
+ *
+ * @param cls ignored, always NULL
+ * @param h the IO handle to write to
+ * @param what what is being written (for error message creation)
+ * @param source the data to write
+ * @param source_size ignored
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
+ */
+static int
+write_spec_handler_int64 (void *cls,
+                          struct GNUNET_BIO_WriteHandle *h,
+                          const char *what,
+                          void *source,
+                          size_t source_size)
+{
+  int64_t i = *(int64_t *) source;
+  return GNUNET_BIO_write_int64 (h, what, i);
+}
+
+
+/**
+ * Create the specification to write an (u)int64_t.
+ *
+ * @param what describes what is being written (for error message creation)
+ * @param i pointer to a 64-bit integer
+ * @return the write spec
+ */
+struct GNUNET_BIO_WriteSpec
+GNUNET_BIO_write_spec_int64 (const char *what,
+                             int64_t *i)
+{
+  struct GNUNET_BIO_WriteSpec ws = {
+    .wh = &write_spec_handler_int64,
+    .cls = NULL,
+    .what = what,
+    .source = i,
+    .source_size = 0,
+  };
+
+  return ws;
+}
+
+
+/**
+ * Create the specification to write a float.
+ *
+ * @param what describes what is being written (for error message creation)
+ * @param f pointer to a float
+ * @return the write spec
+ */
+struct GNUNET_BIO_WriteSpec
+GNUNET_BIO_write_spec_float(const char *what, float *f)
+{
+  struct GNUNET_BIO_WriteSpec ws = {
+    .wh = &write_spec_handler_int32,
+    .cls = NULL,
+    .what = what,
+    .source = (int32_t *) f,
+    .source_size = 0,
+  };
+
+  return ws;
+}
+
+
+/**
+ * Create the specification to write an double.
+ *
+ * @param what describes what is being written (for error message creation)
+ * @param f pointer to a double
+ * @return the write spec
+ */
+struct GNUNET_BIO_WriteSpec
+GNUNET_BIO_write_spec_double(const char *what, double *f)
+{
+  struct GNUNET_BIO_WriteSpec ws = {
+    .wh = &write_spec_handler_int64,
+    .cls = NULL,
+    .what = what,
+    .source = (int64_t *) f,
+    .source_size = 0,
+  };
+
+  return ws;
+}
+
+
+/**
+ * Execute the write specifications in order.
+ *
+ * @param h the IO handle to write to
+ * @param ws array of write specs
+ *        the last element must be #GNUNET_BIO_write_spec_end
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
+ */
+int
+GNUNET_BIO_write_spec_commit (struct GNUNET_BIO_WriteHandle *h,
+                              struct GNUNET_BIO_WriteSpec *ws)
+{
+  int ret = GNUNET_OK;
+
+  for (size_t i=0; NULL!=ws[i].wh; ++i)
+  {
+    ret = ws[i].wh (ws[i].cls, h, ws[i].what, ws[i].source, ws[i].source_size);
+    if (GNUNET_OK != ret)
+      return ret;
+  }
+
+  /* If it's a file-based handle, the flush makes sure that the data in the
+     buffer is actualy written to the disk. */
+  if (IO_FILE == h->type)
+    ret = GNUNET_BIO_flush (h);
+
+  return ret;
 }
 
 
diff --git a/src/util/buffer.c b/src/util/buffer.c
index dabf630c7..c865f6307 100644
--- a/src/util/buffer.c
+++ b/src/util/buffer.c
@@ -130,7 +130,26 @@ GNUNET_buffer_reap_str (struct GNUNET_Buffer *buf)
     buf->mem[buf->position++] = '\0';
   }
   res = buf->mem;
-  *buf = (struct GNUNET_Buffer) { 0 };
+  memset (buf, 0, sizeof (struct GNUNET_Buffer));
+  return res;
+}
+
+
+/**
+ * Clear the buffer and return its contents.
+ * The caller is responsible to eventually #GNUNET_free
+ * the returned data.
+ *
+ * @param buf the buffer to reap the contents from
+ * @param size where to store the size of the returned data
+ * @returns the data contained in the string
+ */
+void *
+GNUNET_buffer_reap (struct GNUNET_Buffer *buf, size_t *size)
+{
+  *size = buf->position;
+  void *res = buf->mem;
+  memset (buf, 0, sizeof (struct GNUNET_Buffer));
   return res;
 }
 
@@ -144,7 +163,7 @@ void
 GNUNET_buffer_clear (struct GNUNET_Buffer *buf)
 {
   GNUNET_free_non_null (buf->mem);
-  *buf = (struct GNUNET_Buffer) { 0 };
+  memset (buf, 0, sizeof (struct GNUNET_Buffer));
 }
 
 
diff --git a/src/util/perf_crypto_asymmetric.c 
b/src/util/perf_crypto_asymmetric.c
index 49d9ec644..8533351e1 100644
--- a/src/util/perf_crypto_asymmetric.c
+++ b/src/util/perf_crypto_asymmetric.c
@@ -62,9 +62,9 @@ int
 main (int argc, char *argv[])
 {
   int i;
-  struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe[l];
+  struct GNUNET_CRYPTO_EcdhePrivateKey ecdhe[l];
   struct GNUNET_CRYPTO_EcdhePublicKey dhpub[l];
-  struct GNUNET_CRYPTO_EddsaPrivateKey *eddsa[l];
+  struct GNUNET_CRYPTO_EddsaPrivateKey eddsa[l];
   struct GNUNET_CRYPTO_EddsaPublicKey dspub[l];
   struct TestSig sig[l];
 
@@ -82,18 +82,18 @@ main (int argc, char *argv[])
 
   start = GNUNET_TIME_absolute_get ();
   for (i = 0; i < l; i++)
-    eddsa[i] = GNUNET_CRYPTO_eddsa_key_create ();
+    GNUNET_CRYPTO_eddsa_key_create (&eddsa[i]);
   log_duration ("EdDSA", "create key");
 
   start = GNUNET_TIME_absolute_get ();
   for (i = 0; i < l; i++)
-    GNUNET_CRYPTO_eddsa_key_get_public (eddsa[i], &dspub[i]);
+    GNUNET_CRYPTO_eddsa_key_get_public (&eddsa[i], &dspub[i]);
   log_duration ("EdDSA", "get public");
 
   start = GNUNET_TIME_absolute_get ();
   for (i = 0; i < l; i++)
     GNUNET_assert (GNUNET_OK ==
-                   GNUNET_CRYPTO_eddsa_sign_ (eddsa[i],
+                   GNUNET_CRYPTO_eddsa_sign_ (&eddsa[i],
                                               &sig[i].purp,
                                               &sig[i].sig));
   log_duration ("EdDSA", "sign HashCode");
@@ -109,19 +109,19 @@ main (int argc, char *argv[])
 
   start = GNUNET_TIME_absolute_get ();
   for (i = 0; i < l; i++)
-    ecdhe[i] = GNUNET_CRYPTO_ecdhe_key_create ();
+    GNUNET_CRYPTO_ecdhe_key_create (&ecdhe[i]);
   log_duration ("ECDH", "create key");
 
   start = GNUNET_TIME_absolute_get ();
   for (i = 0; i < l; i++)
-    GNUNET_CRYPTO_ecdhe_key_get_public (ecdhe[i], &dhpub[i]);
+    GNUNET_CRYPTO_ecdhe_key_get_public (&ecdhe[i], &dhpub[i]);
   log_duration ("ECDH", "get public");
 
   start = GNUNET_TIME_absolute_get ();
   for (i = 0; i < l - 1; i += 2)
   {
-    GNUNET_CRYPTO_ecc_ecdh (ecdhe[i], &dhpub[i + 1], &sig[i].h);
-    GNUNET_CRYPTO_ecc_ecdh (ecdhe[i + 1], &dhpub[i], &sig[i + 1].h);
+    GNUNET_CRYPTO_ecc_ecdh (&ecdhe[i], &dhpub[i + 1], &sig[i].h);
+    GNUNET_CRYPTO_ecc_ecdh (&ecdhe[i + 1], &dhpub[i], &sig[i + 1].h);
   }
   log_duration ("ECDH", "do DH");
 
diff --git a/src/util/test_bio.c b/src/util/test_bio.c
index 53b45c23a..0c8453121 100644
--- a/src/util/test_bio.c
+++ b/src/util/test_bio.c
@@ -30,363 +30,406 @@
 #define TESTSTRING "testString"
 #define TESTNUMBER64 ((int64_t) 100000L)
 
+
 static int
-test_normal_rw ()
+test_normal_rw (void)
 {
-  char *msg;
-  int64_t testNum;
-  char *readResultString;
-  char *fileName = GNUNET_DISK_mktemp ("gnunet_bio");
-  struct GNUNET_BIO_WriteHandle *fileW;
-  struct GNUNET_BIO_ReadHandle *fileR;
-  struct GNUNET_CONTAINER_MetaData *metaDataW;
-  struct GNUNET_CONTAINER_MetaData *metaDataR;
-
-  metaDataW = GNUNET_CONTAINER_meta_data_create ();
-  metaDataR = NULL;
-  GNUNET_CONTAINER_meta_data_add_publication_date (metaDataW);
-
-  fileW = GNUNET_BIO_write_open (fileName);
-  GNUNET_assert (NULL != fileW);
-  GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_string (fileW, TESTSTRING));
-  GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_meta_data (fileW, metaDataW));
-  GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_int64 (fileW, TESTNUMBER64));
-  GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_close (fileW));
-
-  fileR = GNUNET_BIO_read_open (fileName);
-  GNUNET_assert (NULL != fileR);
-  readResultString = NULL;
-  GNUNET_assert (GNUNET_OK ==
-                 GNUNET_BIO_read_string (fileR, "Read string error",
-                                         &readResultString, 200));
-  GNUNET_assert (NULL != readResultString);
-  GNUNET_assert (0 == strcmp (TESTSTRING, readResultString));
-  GNUNET_free (readResultString);
+  struct GNUNET_BIO_WriteHandle *wh;
+  struct GNUNET_BIO_ReadHandle *rh;
+  void *buffer;
+  size_t buffer_size = 0;
+  char *filename = GNUNET_DISK_mktemp ("gnunet-bio");
+  struct GNUNET_CONTAINER_MetaData *mdW;
+  struct GNUNET_CONTAINER_MetaData *mdR = NULL;
+  char *rString = NULL;
+  int64_t wNum = TESTNUMBER64;
+  int64_t rNum = 0;
+
+  mdW = GNUNET_CONTAINER_meta_data_create ();
+  GNUNET_CONTAINER_meta_data_add_publication_date (mdW);
+
+  struct GNUNET_BIO_WriteSpec ws[] = {
+    GNUNET_BIO_write_spec_string ("test-normal-rw-string", TESTSTRING),
+    GNUNET_BIO_write_spec_meta_data ("test-normal-rw-metadata", mdW),
+    GNUNET_BIO_write_spec_int64 ("test-normal-rw-int64", &wNum),
+    GNUNET_BIO_write_spec_end(),
+  };
+
+  struct GNUNET_BIO_ReadSpec rs[] = {
+    GNUNET_BIO_read_spec_string ("test-normal-rw-string", &rString, 200),
+    GNUNET_BIO_read_spec_meta_data ("test-normal-rw-metadata", &mdR),
+    GNUNET_BIO_read_spec_int64 ("test-normal-rw-int64", &rNum),
+    GNUNET_BIO_read_spec_end(),
+  };
+
+  /* I/O on file */
+  wh = GNUNET_BIO_write_open_file (filename);
+  GNUNET_assert (NULL != wh);
+  GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_spec_commit (wh, ws));
+  GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_close (wh, NULL));
+
+  rh = GNUNET_BIO_read_open_file (filename);
+  GNUNET_assert (NULL != rh);
+  GNUNET_assert (GNUNET_OK == GNUNET_BIO_read_spec_commit (rh, rs));
+  GNUNET_assert (GNUNET_OK == GNUNET_BIO_read_close (rh, NULL));
+  GNUNET_assert (0 == strcmp (TESTSTRING, rString));
+  GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_meta_data_test_equal (mdR, 
mdW));
+  GNUNET_assert (wNum == rNum);
+
+  GNUNET_CONTAINER_meta_data_destroy (mdR);
+  GNUNET_assert (GNUNET_OK == GNUNET_DISK_directory_remove (filename));
+  GNUNET_free(filename);
+
+  /* I/O on buffer */
+  wh = GNUNET_BIO_write_open_buffer ();
+  GNUNET_assert (NULL != wh);
+  GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_spec_commit (wh, ws));
   GNUNET_assert (GNUNET_OK ==
-                 GNUNET_BIO_read_meta_data (fileR, "Read meta error",
-                                            &metaDataR));
-  GNUNET_assert (GNUNET_YES ==
-                 GNUNET_CONTAINER_meta_data_test_equal (metaDataR, metaDataW));
-  GNUNET_assert (GNUNET_OK == GNUNET_BIO_read_int64 (fileR, &testNum));
-  GNUNET_BIO_read_close (fileR, &msg);
-  GNUNET_CONTAINER_meta_data_destroy (metaDataW);
-  GNUNET_CONTAINER_meta_data_destroy (metaDataR);
-  GNUNET_assert (GNUNET_OK == GNUNET_DISK_directory_remove (fileName));
-  GNUNET_free (fileName);
+                 GNUNET_BIO_get_buffer_contents (wh,
+                                                 NULL,
+                                                 &buffer,
+                                                 &buffer_size));
+  GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_close (wh, NULL));
+
+  rh = GNUNET_BIO_read_open_buffer (buffer, buffer_size);
+  GNUNET_assert (NULL != rh);
+  GNUNET_assert (GNUNET_OK == GNUNET_BIO_read_spec_commit (rh, rs));
+  GNUNET_assert (GNUNET_OK == GNUNET_BIO_read_close (rh, NULL));
+  GNUNET_assert (0 == strcmp (TESTSTRING, rString));
+  GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_meta_data_test_equal (mdR, 
mdW));
+  GNUNET_assert (wNum == rNum);
+
+  GNUNET_free (buffer);
+
+  GNUNET_CONTAINER_meta_data_destroy (mdW);
+  GNUNET_CONTAINER_meta_data_destroy (mdR);
   return 0;
 }
 
 
 static int
-test_nullstring_rw ()
+test_nullstring_rw (void)
 {
-  char *msg;
-  char *readResultString = (char *) "not null";
-  struct GNUNET_BIO_WriteHandle *fileW;
-  struct GNUNET_BIO_ReadHandle *fileR;
-  char *fileName = GNUNET_DISK_mktemp ("gnunet_bio");
-
-  fileW = GNUNET_BIO_write_open (fileName);
-  GNUNET_assert (NULL != fileW);
-  GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_string (fileW, NULL));
-  GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_close (fileW));
-
-  fileR = GNUNET_BIO_read_open (fileName);
-  GNUNET_assert (NULL != fileR);
-  GNUNET_assert (GNUNET_OK ==
-                 GNUNET_BIO_read_string (fileR, "Read string error",
-                                         &readResultString, 200));
-  GNUNET_assert (NULL == readResultString);
-  GNUNET_BIO_read_close (fileR, &msg);
-  GNUNET_assert (GNUNET_OK == GNUNET_DISK_directory_remove (fileName));
-  GNUNET_free (fileName);
-
+  struct GNUNET_BIO_WriteHandle *wh;
+  struct GNUNET_BIO_ReadHandle *rh;
+  char *filename = GNUNET_DISK_mktemp ("gnunet_bio");
+  char *rString = "not null";
+
+  wh = GNUNET_BIO_write_open_file (filename);
+  GNUNET_assert (NULL != wh);
+  GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_string (wh,
+                                                       "test-nullstring-rw",
+                                                       NULL));
+  GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_close (wh, NULL));
+
+  rh = GNUNET_BIO_read_open_file (filename);
+  GNUNET_assert (NULL != rh);
+  GNUNET_assert (GNUNET_OK == GNUNET_BIO_read_string (rh,
+                                                      "test-nullstring-rw",
+                                                      &rString, 200));
+  GNUNET_assert (GNUNET_OK == GNUNET_BIO_read_close (rh, NULL));
+
+  GNUNET_assert (NULL == rString);
+
+  GNUNET_assert (GNUNET_OK == GNUNET_DISK_directory_remove (filename));
+  GNUNET_free (filename);
   return 0;
 }
 
 
 static int
-test_emptystring_rw ()
+test_emptystring_rw (void)
 {
-  char *msg;
-  char *readResultString;
-  struct GNUNET_BIO_WriteHandle *fileW;
-  struct GNUNET_BIO_ReadHandle *fileR;
-  char *fileName = GNUNET_DISK_mktemp ("gnunet_bio");
-
-  fileW = GNUNET_BIO_write_open (fileName);
-  GNUNET_assert (NULL != fileW);
-  GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_string (fileW, ""));
-  GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_close (fileW));
-
-  fileR = GNUNET_BIO_read_open (fileName);
-  GNUNET_assert (NULL != fileR);
-  readResultString = NULL;
-  GNUNET_assert (GNUNET_OK ==
-                 GNUNET_BIO_read_string (fileR, "Read string error",
-                                         &readResultString, 200));
-  GNUNET_free (readResultString);
-  GNUNET_BIO_read_close (fileR, &msg);
-  GNUNET_assert (GNUNET_OK == GNUNET_DISK_directory_remove (fileName));
-  GNUNET_free (fileName);
+  struct GNUNET_BIO_WriteHandle *wh;
+  struct GNUNET_BIO_ReadHandle *rh;
+  char *filename = GNUNET_DISK_mktemp ("gnunet_bio");
+  char *rString = NULL;
+
+  wh = GNUNET_BIO_write_open_file (filename);
+  GNUNET_assert (NULL != wh);
+  GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_string (wh,
+                                                       "test-emptystring-rw",
+                                                       ""));
+  GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_close (wh, NULL));
+
+  rh = GNUNET_BIO_read_open_file (filename);
+  GNUNET_assert (NULL != rh);
+  GNUNET_assert (GNUNET_OK == GNUNET_BIO_read_string (rh,
+                                                      "test-emptystring-rw",
+                                                      &rString, 200));
+  GNUNET_assert (GNUNET_OK == GNUNET_BIO_read_close (rh, NULL));
+
+  GNUNET_free (rString);
+
+  GNUNET_assert (GNUNET_OK == GNUNET_DISK_directory_remove (filename));
+  GNUNET_free (filename);
   return 0;
 }
 
 
 static int
-test_bigstring_rw ()
+test_bigstring_rw (void)
 {
-  char *msg;
-  char *readResultString;
-  struct GNUNET_BIO_WriteHandle *fileW;
-  struct GNUNET_BIO_ReadHandle *fileR;
-  char *fileName = GNUNET_DISK_mktemp ("gnunet_bio");
-
-  fileW = GNUNET_BIO_write_open (fileName);
-  GNUNET_assert (NULL != fileW);
-  GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_string (fileW, TESTSTRING));
-  GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_close (fileW));
-
-  fileR = GNUNET_BIO_read_open (fileName);
-  GNUNET_assert (NULL != fileR);
-  readResultString = NULL;
-  GNUNET_assert (GNUNET_SYSERR ==
-                 GNUNET_BIO_read_string (fileR, "Read string error",
-                                         &readResultString, 1));
-  GNUNET_assert (NULL == readResultString);
-  msg = NULL;
-  GNUNET_BIO_read_close (fileR, &msg);
-  GNUNET_free (msg);
-  GNUNET_assert (GNUNET_OK == GNUNET_DISK_directory_remove (fileName));
-  GNUNET_free (fileName);
+  struct GNUNET_BIO_WriteHandle *wh;
+  struct GNUNET_BIO_ReadHandle *rh;
+  char *filename = GNUNET_DISK_mktemp ("gnunet_bio");
+  char *rString = NULL;
+
+  wh = GNUNET_BIO_write_open_file (filename);
+  GNUNET_assert (NULL != wh);
+  GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_string (wh,
+                                                       "test-bigstring-rw",
+                                                       TESTSTRING));
+  GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_close (wh, NULL));
+
+  rh = GNUNET_BIO_read_open_file (filename);
+  GNUNET_assert (NULL != rh);
+  GNUNET_assert (GNUNET_SYSERR == GNUNET_BIO_read_string (rh,
+                                                          "test-bigstring-rw",
+                                                          &rString, 1));
+  GNUNET_assert (GNUNET_SYSERR == GNUNET_BIO_read_close (rh, NULL));
+
+  GNUNET_assert (NULL == rString);
+
+  GNUNET_assert (GNUNET_OK == GNUNET_DISK_directory_remove (filename));
+  GNUNET_free (filename);
   return 0;
 }
 
 
 static int
-test_bigmeta_rw ()
+test_bigmeta_rw (void)
 {
-  char *msg;
   static char meta[1024 * 1024 * 10];
-  struct GNUNET_BIO_WriteHandle *fileW;
-  struct GNUNET_BIO_ReadHandle *fileR;
-  char *fileName = GNUNET_DISK_mktemp ("gnunet_bio");
-  struct GNUNET_CONTAINER_MetaData *metaDataR;
-
-  memset (meta, 'b', sizeof(meta));
-  meta[sizeof(meta) - 1] = '\0';
-  fileW = GNUNET_BIO_write_open (fileName);
-  GNUNET_assert (NULL != fileW);
-  GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_int32 (fileW, sizeof(meta)));
-  GNUNET_assert (GNUNET_OK == GNUNET_BIO_write (fileW, meta, sizeof(meta)));
-  GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_close (fileW));
-
-  fileR = GNUNET_BIO_read_open (fileName);
-  GNUNET_assert (NULL != fileR);
-  metaDataR = NULL;
+  struct GNUNET_BIO_WriteHandle *wh;
+  struct GNUNET_BIO_ReadHandle *rh;
+  char *filename = GNUNET_DISK_mktemp ("gnunet_bio");
+  struct GNUNET_CONTAINER_MetaData *mdR = NULL;
+
+  memset (meta, 'b', sizeof (meta));
+  meta[sizeof (meta) - 1] = '\0';
+
+  wh = GNUNET_BIO_write_open_file (filename);
+  GNUNET_assert (NULL != wh);
+  GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_int32 (wh,
+                                                      "test-bigmeta-rw-int32",
+                                                      sizeof (meta)));
+  GNUNET_assert (GNUNET_OK == GNUNET_BIO_write (wh,
+                                                "test-bigmeta-rw-bytes",
+                                                meta,
+                                                sizeof (meta)));
+  GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_close (wh, NULL));
+
+  rh = GNUNET_BIO_read_open_file (filename);
+  GNUNET_assert (NULL != rh);
   GNUNET_assert (GNUNET_SYSERR ==
-                 GNUNET_BIO_read_meta_data (fileR, "Read meta error",
-                                            &metaDataR));
-  msg = NULL;
-  GNUNET_BIO_read_close (fileR, &msg);
-  GNUNET_free (msg);
-  GNUNET_assert (GNUNET_OK == GNUNET_DISK_directory_remove (fileName));
-  GNUNET_assert (NULL == metaDataR);
-  GNUNET_free (fileName);
+                 GNUNET_BIO_read_meta_data (rh,
+                                            "test-bigmeta-rw-metadata",
+                                            &mdR));
+  GNUNET_assert (GNUNET_SYSERR == GNUNET_BIO_read_close (rh, NULL));
+
+  GNUNET_assert (NULL == mdR);
+
+  GNUNET_assert (GNUNET_OK == GNUNET_DISK_directory_remove (filename));
+  GNUNET_free (filename);
   return 0;
 }
 
 
 static int
-test_directory_r ()
+test_directory_r (void)
 {
-#ifdef __linux__
-  char *msg;
-  char readResult[200];
-  struct GNUNET_BIO_ReadHandle *fileR;
-
-  fileR = GNUNET_BIO_read_open ("/dev");
-  GNUNET_assert (NULL != fileR);
-  GNUNET_assert (GNUNET_SYSERR ==
-                 GNUNET_BIO_read (fileR, "Read error", readResult,
-                                  sizeof(readResult)));
-  msg = NULL;
-  GNUNET_BIO_read_close (fileR, &msg);
-  GNUNET_free (msg);
+#ifdef LINUX
+  struct GNUNET_BIO_ReadHandle *rh;
+  char rString[200];
+
+  rh = GNUNET_BIO_read_open_file ("/dev");
+  GNUNET_assert (NULL != rh);
+  GNUNET_assert (GNUNET_SYSERR == GNUNET_BIO_read (rh,
+                                                   "test-directory-r",
+                                                   rString,
+                                                   sizeof (rString)));
+  GNUNET_assert (GNUNET_SYSERR == GNUNET_BIO_read_close (rh, NULL));
 #endif
   return 0;
 }
 
 
 static int
-test_nullfile_rw ()
+test_nullfile_rw (void)
 {
-  static char fileNameNO[102401];
-  struct GNUNET_BIO_WriteHandle *fileWNO;
-  struct GNUNET_BIO_ReadHandle *fileRNO;
+  static char filename[102401];
+  struct GNUNET_BIO_WriteHandle *wh;
+  struct GNUNET_BIO_ReadHandle *rh;
 
-  memset (fileNameNO, 'a', sizeof(fileNameNO));
-  fileNameNO[sizeof(fileNameNO) - 1] = '\0';
+  memset (filename, 'a', sizeof (filename));
+  filename[sizeof (filename) - 1] = '\0';
 
-  GNUNET_log_skip (1, GNUNET_NO);
-  fileWNO = GNUNET_BIO_write_open (fileNameNO);
+  GNUNET_log_skip (2, GNUNET_NO);
+  wh = GNUNET_BIO_write_open_file (filename);
   GNUNET_log_skip (0, GNUNET_YES);
-  GNUNET_assert (NULL == fileWNO);
+  GNUNET_assert (NULL == wh);
 
-  GNUNET_log_skip (1, GNUNET_NO);
-  fileRNO = GNUNET_BIO_read_open (fileNameNO);
+  GNUNET_log_skip (2, GNUNET_NO);
+  rh = GNUNET_BIO_read_open_file (filename);
   GNUNET_log_skip (0, GNUNET_YES);
-  GNUNET_assert (NULL == fileRNO);
+  GNUNET_assert (NULL == rh);
+
   return 0;
 }
 
 
 static int
-test_fullfile_rw ()
+test_fullfile_rw (void)
 {
-#ifdef __linux__
-  /* /dev/full only seems to exist on Linux */
-  char *msg;
-  int64_t testNum;
-  char *readResultString;
-  char readResult[200];
-  struct GNUNET_BIO_WriteHandle *fileW;
-  struct GNUNET_BIO_ReadHandle *fileR;
-  struct GNUNET_CONTAINER_MetaData *metaDataW;
-  struct GNUNET_CONTAINER_MetaData *metaDataR;
-
-  metaDataW = GNUNET_CONTAINER_meta_data_create ();
-  GNUNET_CONTAINER_meta_data_add_publication_date (metaDataW);
-
-  fileW = GNUNET_BIO_write_open ("/dev/full");
-  GNUNET_assert (NULL != fileW);
-  (void) GNUNET_BIO_write (fileW, TESTSTRING, strlen (TESTSTRING));
-  (void) GNUNET_BIO_write_string (fileW, TESTSTRING);
-  (void) GNUNET_BIO_write_meta_data (fileW, metaDataW);
-  GNUNET_assert (GNUNET_SYSERR == GNUNET_BIO_write_close (fileW));
-  GNUNET_CONTAINER_meta_data_destroy (metaDataW);
-
-  fileW = GNUNET_BIO_write_open ("/dev/full");
-  GNUNET_assert (NULL != fileW);
-  GNUNET_assert (GNUNET_SYSERR == GNUNET_BIO_write_close (fileW));
-
-  fileR = GNUNET_BIO_read_open ("/dev/null");
-  GNUNET_assert (NULL != fileR);
-  GNUNET_assert (GNUNET_SYSERR ==
-                 GNUNET_BIO_read (fileR, "Read error", readResult,
-                                  sizeof(readResult)));
-  readResultString = NULL;
-  GNUNET_assert (GNUNET_SYSERR ==
-                 GNUNET_BIO_read_string (fileR, "Read string error",
-                                         &readResultString, 200));
-  GNUNET_assert (NULL == readResultString);
-  GNUNET_assert (GNUNET_SYSERR == GNUNET_BIO_read_int64 (fileR, &testNum));
-  metaDataR = NULL;
-  GNUNET_assert (GNUNET_SYSERR ==
-                 GNUNET_BIO_read_meta_data (fileR, "Read meta error",
-                                            &metaDataR));
-  msg = NULL;
-  GNUNET_BIO_read_close (fileR, &msg);
-  GNUNET_free (msg);
-  GNUNET_assert (NULL == metaDataR);
+#ifdef LINUX
+  /* /dev/full doesn't exist on every platform */
+  struct GNUNET_BIO_WriteHandle *wh;
+  struct GNUNET_BIO_ReadHandle *rh;
+  char *rString = NULL;
+  char rResult[200];
+  struct GNUNET_CONTAINER_MetaData *mdW;
+  struct GNUNET_CONTAINER_MetaData *mdR = NULL;
+
+  mdW = GNUNET_CONTAINER_meta_data_create ();
+  GNUNET_CONTAINER_meta_data_add_publication_date (mdW);
+
+  struct GNUNET_BIO_WriteSpec ws[] = {
+    GNUNET_BIO_write_spec_object ("test-fullfile-rw-bytes",
+                                  TESTSTRING,
+                                  strlen (TESTSTRING)),
+    GNUNET_BIO_write_spec_string ("test-fullfile-rw-string",
+                                  TESTSTRING),
+    GNUNET_BIO_write_spec_meta_data ("test-fullfile-rw-metadata",
+                                     mdW),
+    GNUNET_BIO_write_spec_end (),
+  };
+
+  struct GNUNET_BIO_ReadSpec rs[] = {
+    GNUNET_BIO_read_spec_object ("test-fullfile-rw-bytes",
+                                 rResult,
+                                 sizeof (rResult)),
+    GNUNET_BIO_read_spec_string ("test-fullfile-rw-string",
+                                 &rString,
+                                 200),
+    GNUNET_BIO_read_spec_meta_data ("test-fullfile-rw-metadata",
+                                    &mdR),
+    GNUNET_BIO_read_spec_end(),
+  };
+
+  wh = GNUNET_BIO_write_open_file ("/dev/full");
+  GNUNET_assert (NULL != wh);
+  GNUNET_assert (GNUNET_SYSERR == GNUNET_BIO_write_spec_commit (wh, ws));
+  GNUNET_assert (GNUNET_SYSERR == GNUNET_BIO_write_close (wh, NULL));
+
+  rh = GNUNET_BIO_read_open_file ("/dev/null");
+  GNUNET_assert (NULL != rh);
+  GNUNET_assert (GNUNET_SYSERR == GNUNET_BIO_read_spec_commit (rh, rs));
+  GNUNET_assert (GNUNET_SYSERR == GNUNET_BIO_read_close (rh, NULL));
+
+  GNUNET_assert (NULL == rString);
+  GNUNET_assert (NULL == mdR);
 #endif
   return 0;
 }
 
 
 static int
-test_fakestring_rw ()
+test_fakestring_rw (void)
 {
-  char *msg;
-  int32_t tmpInt = 2;
-  char *readResult;
-  struct GNUNET_BIO_WriteHandle *fileW;
-  struct GNUNET_BIO_ReadHandle *fileR;
-  char *fileName = GNUNET_DISK_mktemp ("gnunet_bio");
-
-  fileW = GNUNET_BIO_write_open (fileName);
-  GNUNET_assert (NULL != fileW);
-  GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_int32 (fileW, tmpInt));
-  GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_close (fileW));
-
-  fileR = GNUNET_BIO_read_open (fileName);
-  GNUNET_assert (NULL != fileR);
+  struct GNUNET_BIO_WriteHandle *wh;
+  struct GNUNET_BIO_ReadHandle *rh;
+  char *filename = GNUNET_DISK_mktemp ("gnunet_bio");
+  char *rString = NULL;
+
+  wh = GNUNET_BIO_write_open_file (filename);
+  GNUNET_assert (NULL != wh);
+  GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_int32 (wh,
+                                                      
"test-fakestring-rw-int32",
+                                                      2));
+  GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_close (wh, NULL));
+
+  rh = GNUNET_BIO_read_open_file (filename);
+  GNUNET_assert (NULL != rh);
   GNUNET_assert (GNUNET_SYSERR ==
-                 GNUNET_BIO_read_string (fileR, "Read string error",
-                                         &readResult, 200));
-  msg = NULL;
-  GNUNET_BIO_read_close (fileR, &msg);
-  GNUNET_free (msg);
-  GNUNET_assert (GNUNET_OK == GNUNET_DISK_directory_remove (fileName));
-  GNUNET_free (fileName);
+                 GNUNET_BIO_read_string (rh,
+                                         "test-fakestring-rw-string",
+                                         &rString, 200));
+  GNUNET_assert (GNUNET_SYSERR == GNUNET_BIO_read_close (rh, NULL));
+
+  GNUNET_assert (NULL == rString);
+
+  GNUNET_assert (GNUNET_OK == GNUNET_DISK_directory_remove (filename));
+  GNUNET_free (filename);
   return 0;
 }
 
 
 static int
-test_fakemeta_rw ()
+test_fakemeta_rw (void)
 {
-  char *msg;
-  int32_t tmpInt = 2;
-  struct GNUNET_BIO_WriteHandle *fileW;
-  struct GNUNET_BIO_ReadHandle *fileR;
-  char *fileName = GNUNET_DISK_mktemp ("gnunet_bio");
-  struct GNUNET_CONTAINER_MetaData *metaDataR;
-
-  fileW = GNUNET_BIO_write_open (fileName);
-  GNUNET_assert (NULL != fileW);
-  GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_int32 (fileW, tmpInt));
-  GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_close (fileW));
-
-  fileR = GNUNET_BIO_read_open (fileName);
-  GNUNET_assert (NULL != fileR);
-  metaDataR = NULL;
+  struct GNUNET_BIO_WriteHandle *wh;
+  struct GNUNET_BIO_ReadHandle *rh;
+  char *filename = GNUNET_DISK_mktemp ("gnunet_bio");
+  struct GNUNET_CONTAINER_MetaData *mdR = NULL;
+
+  wh = GNUNET_BIO_write_open_file (filename);
+  GNUNET_assert (NULL != wh);
+  GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_int32 (wh,
+                                                      
"test-fakestring-rw-int32",
+                                                      2));
+  GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_close (wh, NULL));
+
+  rh = GNUNET_BIO_read_open_file (filename);
+  GNUNET_assert (NULL != rh);
   GNUNET_assert (GNUNET_SYSERR ==
-                 GNUNET_BIO_read_meta_data (fileR, "Read meta error",
-                                            &metaDataR));
-  GNUNET_assert (NULL == metaDataR);
-  msg = NULL;
-  GNUNET_BIO_read_close (fileR, &msg);
-  GNUNET_free (msg);
-  GNUNET_assert (GNUNET_OK == GNUNET_DISK_directory_remove (fileName));
-  GNUNET_free (fileName);
+                 GNUNET_BIO_read_meta_data (rh,
+                                            "test-fakestring-rw-metadata",
+                                            &mdR));
+  GNUNET_assert (GNUNET_SYSERR == GNUNET_BIO_read_close (rh, NULL));
+
+  GNUNET_assert (NULL == mdR);
+
+  GNUNET_assert (GNUNET_OK == GNUNET_DISK_directory_remove (filename));
+  GNUNET_free (filename);
   return 0;
 }
 
 
 static int
-test_fakebigmeta_rw ()
+test_fakebigmeta_rw (void)
 {
-  char *msg;
-  int32_t tmpInt = 1024 * 1024 * 10;
-  struct GNUNET_BIO_WriteHandle *fileW;
-  struct GNUNET_BIO_ReadHandle *fileR;
-  char *fileName = GNUNET_DISK_mktemp ("gnunet_bio");
-  struct GNUNET_CONTAINER_MetaData *metaDataR;
-
-  fileW = GNUNET_BIO_write_open (fileName);
-  GNUNET_assert (NULL != fileW);
-  GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_int32 (fileW, tmpInt));
-  GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_close (fileW));
-
-  fileR = GNUNET_BIO_read_open (fileName);
-  GNUNET_assert (NULL != fileR);
-  metaDataR = NULL;
+  struct GNUNET_BIO_WriteHandle *wh;
+  struct GNUNET_BIO_ReadHandle *rh;
+  char *filename = GNUNET_DISK_mktemp ("gnunet_bio");
+  struct GNUNET_CONTAINER_MetaData *mdR = NULL;
+  int32_t wNum = 1024 * 1024 * 10;
+
+  wh = GNUNET_BIO_write_open_file (filename);
+  GNUNET_assert (NULL != wh);
+  GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_int32 (wh,
+                                                      
"test-fakebigmeta-rw-int32",
+                                                      wNum));
+  GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_close (wh, NULL));
+
+  rh = GNUNET_BIO_read_open_file (filename);
+  GNUNET_assert (NULL != rh);
   GNUNET_assert (GNUNET_SYSERR ==
-                 GNUNET_BIO_read_meta_data (fileR, "Read meta error",
-                                            &metaDataR));
-  msg = NULL;
-  GNUNET_BIO_read_close (fileR, &msg);
-  GNUNET_free (msg);
-  GNUNET_assert (GNUNET_OK == GNUNET_DISK_directory_remove (fileName));
-  GNUNET_assert (NULL == metaDataR);
-  GNUNET_free (fileName);
+                 GNUNET_BIO_read_meta_data (rh,
+                                            "test-fakebigmeta-rw-metadata",
+                                            &mdR));
+  GNUNET_assert (GNUNET_SYSERR == GNUNET_BIO_read_close (rh, NULL));
+
+  GNUNET_assert (NULL == mdR);
+
+  GNUNET_assert (GNUNET_OK == GNUNET_DISK_directory_remove (filename));
+  GNUNET_free (filename);
   return 0;
 }
 
 
 static int
-check_string_rw ()
+check_string_rw (void)
 {
   GNUNET_assert (0 == test_nullstring_rw ());
   GNUNET_assert (0 == test_emptystring_rw ());
@@ -397,7 +440,7 @@ check_string_rw ()
 
 
 static int
-check_metadata_rw ()
+check_metadata_rw (void)
 {
   GNUNET_assert (0 == test_fakebigmeta_rw ());
   GNUNET_assert (0 == test_fakemeta_rw ());
@@ -407,7 +450,7 @@ check_metadata_rw ()
 
 
 static int
-check_file_rw ()
+check_file_rw (void)
 {
   GNUNET_assert (0 == test_normal_rw ());
   GNUNET_assert (0 == test_nullfile_rw ());

-- 
To stop receiving notification emails like this one, please contact
address@hidden.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]