gnunet-svn
[Top][All Lists]
Advanced

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

[gnunet] 02/03: Improved BIO API


From: gnunet
Subject: [gnunet] 02/03: Improved BIO API
Date: Tue, 19 May 2020 02:47:06 +0200

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

grothoff pushed a commit to branch master
in repository gnunet.

commit f4771fcc1c3fda21a46d0cb85d8b29e012254696
Author: Alessio Vanni <address@hidden>
AuthorDate: Thu May 14 16:03:10 2020 +0200

    Improved BIO API
    
    BIO now supports reading from and writing to in-memory buffers.
    
    For reading, an allocated buffer (array) and a size is passed as arguments 
to
    the function opening the handle.
    For writing, a GNUNET_Buffer is created and used internally. The buffer
    contents can be extracted using the relevant function.
    
    There is a new API in addition to the existing read/write: this new API is
    more "declarative" in nature and is meant to mimic APIs like GNUNET_SQ.
    The read/write operations are defined in an array of specs which are then
    "commited" in a single (non-atomic) operation, rather than explicitly
    executing multiple function calls and checking their return value.
    
    Also there are small changes to GNUNET_Buffer to account for BIO's new
    features.
    
    Signed-off-by: Christian Grothoff <address@hidden>
---
 src/fs/fs_api.c                                    |  447 ++++---
 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/test_bio.c                                |  601 +++++-----
 14 files changed, 2279 insertions(+), 735 deletions(-)

diff --git a/src/fs/fs_api.c b/src/fs/fs_api.c
index e04a93f9c..39e3add63 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,29 @@ 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)
+  };
+  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 +1817,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 +1857,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 +1893,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 +1914,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 +1949,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 +2084,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 +2095,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 +2132,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 +2142,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 +2190,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 +2221,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 +2239,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 +2284,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 +2307,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 +2337,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 +2346,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 +2544,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 +2579,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 +2854,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 +2940,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 +3091,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 +3159,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 +3202,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/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]