From f4771fcc1c3fda21a46d0cb85d8b29e012254696 Mon Sep 17 00:00:00 2001 From: Alessio Vanni Date: Thu, 14 May 2020 16:03:10 +0200 Subject: 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 --- 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 *)×_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, ×_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 ()); -- cgit v1.2.3