/** * Print an entry in a directory. * * @param cls closure (not used) * @param filename name of the file in the directory * @param uri URI of the file * @param meta metadata for the file; metadata for * the directory if everything else is NULL/zero * @param length length of the available data for the file * (of type size_t since data must certainly fit * into memory; if files are larger than size_t * permits, then they will certainly not be * embedded with the directory itself). * @param data data available for the file (length bytes) */ static void print_entry (void *cls, const char *filename, const struct GNUNET_FS_Uri *uri, const struct GNUNET_CONTAINER_MetaData *meta, size_t length, const void *data) { char *string; char *name; name = GNUNET_CONTAINER_meta_data_get_by_type (meta, EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME); if (uri == NULL) { printf (_("Directory `%s' meta data:\n"), name); GNUNET_CONTAINER_meta_data_iterate (meta, &item_printer, NULL); printf ("\n"); printf (_("Directory `%s' contents:\n"), name); GNUNET_free (name); return; } string = GNUNET_FS_uri_to_string (uri); printf ("%s (%s):\n", name, string); GNUNET_free (string); GNUNET_CONTAINER_meta_data_iterate (meta, &item_printer, NULL); printf ("\n"); GNUNET_free (name); }
static int testKeyword () { char *uri; struct GNUNET_FS_Uri *ret; char *emsg; if (NULL != (ret = GNUNET_FS_uri_parse ("gnunet://fs/ksk/++", &emsg))) { GNUNET_FS_uri_destroy (ret); GNUNET_assert (0); } GNUNET_free (emsg); ret = GNUNET_FS_uri_parse ("gnunet://fs/ksk/foo+bar", &emsg); if (NULL == ret) { GNUNET_free (emsg); GNUNET_assert (0); } if (! GNUNET_FS_uri_test_ksk (ret)) { GNUNET_FS_uri_destroy (ret); GNUNET_assert (0); } if ((2 != ret->data.ksk.keywordCount) || (0 != strcmp (" foo", ret->data.ksk.keywords[0])) || (0 != strcmp (" bar", ret->data.ksk.keywords[1]))) { GNUNET_FS_uri_destroy (ret); GNUNET_assert (0); } uri = GNUNET_FS_uri_to_string (ret); if (0 != strcmp (uri, "gnunet://fs/ksk/foo+bar")) { GNUNET_free (uri); GNUNET_FS_uri_destroy (ret); GNUNET_assert (0); } GNUNET_free (uri); GNUNET_FS_uri_destroy (ret); return 0; }
/** * Publish a UBlock. * * @param h handle to the file sharing subsystem * @param dsh datastore handle to use for storage operation * @param label identifier to use * @param ulabel update label to use, may be an empty string for none * @param ns namespace to publish in * @param meta metadata to use * @param uri URI to refer to in the UBlock * @param bo per-block options * @param options publication options * @param cont continuation * @param cont_cls closure for @a cont * @return NULL on error (@a cont will still be called) */ struct GNUNET_FS_PublishUblockContext * GNUNET_FS_publish_ublock_ (struct GNUNET_FS_Handle *h, struct GNUNET_DATASTORE_Handle *dsh, const char *label, const char *ulabel, const struct GNUNET_CRYPTO_EcdsaPrivateKey *ns, const struct GNUNET_CONTAINER_MetaData *meta, const struct GNUNET_FS_Uri *uri, const struct GNUNET_FS_BlockOptions *bo, enum GNUNET_FS_PublishOptions options, GNUNET_FS_UBlockContinuation cont, void *cont_cls) { struct GNUNET_FS_PublishUblockContext *uc; struct GNUNET_HashCode query; struct GNUNET_CRYPTO_SymmetricInitializationVector iv; struct GNUNET_CRYPTO_SymmetricSessionKey skey; struct GNUNET_CRYPTO_EcdsaPrivateKey *nsd; struct GNUNET_CRYPTO_EcdsaPublicKey pub; char *uris; size_t size; char *kbe; char *sptr; ssize_t mdsize; size_t slen; size_t ulen; struct UBlock *ub_plain; struct UBlock *ub_enc; /* compute ublock to publish */ if (NULL == meta) mdsize = 0; else mdsize = GNUNET_CONTAINER_meta_data_get_serialized_size (meta); GNUNET_assert (mdsize >= 0); uris = GNUNET_FS_uri_to_string (uri); slen = strlen (uris) + 1; if (NULL == ulabel) ulen = 1; else ulen = strlen (ulabel) + 1; size = mdsize + sizeof (struct UBlock) + slen + ulen; if (size > MAX_UBLOCK_SIZE) { size = MAX_UBLOCK_SIZE; mdsize = size - sizeof (struct UBlock) - (slen + ulen); } ub_plain = GNUNET_malloc (size); kbe = (char *) &ub_plain[1]; if (NULL != ulabel) memcpy (kbe, ulabel, ulen); kbe += ulen; memcpy (kbe, uris, slen); kbe += slen; GNUNET_free (uris); sptr = kbe; if (NULL != meta) mdsize = GNUNET_CONTAINER_meta_data_serialize (meta, &sptr, mdsize, GNUNET_CONTAINER_META_DATA_SERIALIZE_PART); if (-1 == mdsize) { GNUNET_break (0); GNUNET_free (ub_plain); cont (cont_cls, _("Internal error.")); return NULL; } size = sizeof (struct UBlock) + slen + mdsize + ulen; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Publishing under identifier `%s'\n", label); /* get public key of the namespace */ GNUNET_CRYPTO_ecdsa_key_get_public (ns, &pub); derive_ublock_encryption_key (&skey, &iv, label, &pub); /* encrypt ublock */ ub_enc = GNUNET_malloc (size); GNUNET_CRYPTO_symmetric_encrypt (&ub_plain[1], ulen + slen + mdsize, &skey, &iv, &ub_enc[1]); GNUNET_free (ub_plain); ub_enc->purpose.size = htonl (ulen + slen + mdsize + sizeof (struct UBlock) - sizeof (struct GNUNET_CRYPTO_EcdsaSignature)); ub_enc->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_FS_UBLOCK); /* derive signing-key from 'label' and public key of the namespace */ nsd = GNUNET_CRYPTO_ecdsa_private_key_derive (ns, label, "fs-ublock"); GNUNET_CRYPTO_ecdsa_key_get_public (nsd, &ub_enc->verification_key); GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdsa_sign (nsd, &ub_enc->purpose, &ub_enc->signature)); GNUNET_CRYPTO_hash (&ub_enc->verification_key, sizeof (ub_enc->verification_key), &query); GNUNET_free (nsd); uc = GNUNET_new (struct GNUNET_FS_PublishUblockContext); uc->cont = cont; uc->cont_cls = cont_cls; uc->qre = GNUNET_DATASTORE_put (dsh, 0, &query, ulen + slen + mdsize + sizeof (struct UBlock), ub_enc, GNUNET_BLOCK_TYPE_FS_UBLOCK, bo->content_priority, bo->anonymity_level, bo->replication_level, bo->expiration_time, -2, 1, GNUNET_CONSTANTS_SERVICE_TIMEOUT, &ublock_put_cont, uc); return uc; }
static int testLocation () { struct GNUNET_FS_Uri *uri; char *uric; struct GNUNET_FS_Uri *uri2; struct GNUNET_FS_Uri *baseURI; char *emsg; struct GNUNET_CRYPTO_EddsaPrivateKey *pk; baseURI = GNUNET_FS_uri_parse ("gnunet://fs/chk/4QZP479A9SKGFNMQ2ZBCYE71YV2QMTVGWTVPB6A10ASVCKXDHB05DKPSC7ZF6E9P9W1VE47394EQY7NXA47Q6R35M7P1MJPGP59D1Z8.D54QD1K5XCG5878T6YZ19AM60MQ6FC0YNVK7QY08KK0KM0FJJ3KQWYG112FN5T07KN7J0X35DF6WVBT9B8ZMZ3X2BXJ22X3KFQ6MV2G.15999", &emsg); GNUNET_assert (baseURI != NULL); GNUNET_assert (emsg == NULL); pk = GNUNET_CRYPTO_eddsa_key_create (); uri = GNUNET_FS_uri_loc_create (baseURI, pk, GNUNET_TIME_absolute_get ()); GNUNET_free (pk); if (NULL == uri) { GNUNET_break (0); GNUNET_FS_uri_destroy (baseURI); return 1; } if (! GNUNET_FS_uri_test_loc (uri)) { GNUNET_break (0); GNUNET_FS_uri_destroy (uri); GNUNET_FS_uri_destroy (baseURI); return 1; } uri2 = GNUNET_FS_uri_loc_get_uri (uri); if (! GNUNET_FS_uri_test_equal (baseURI, uri2)) { GNUNET_break (0); GNUNET_FS_uri_destroy (uri); GNUNET_FS_uri_destroy (uri2); GNUNET_FS_uri_destroy (baseURI); return 1; } GNUNET_FS_uri_destroy (uri2); GNUNET_FS_uri_destroy (baseURI); uric = GNUNET_FS_uri_to_string (uri); #if 0 /* not for the faint of heart: */ printf ("URI: `%s'\n", uric); #endif uri2 = GNUNET_FS_uri_parse (uric, &emsg); GNUNET_free (uric); if (uri2 == NULL) { fprintf (stderr, "URI parsing failed: %s\n", emsg); GNUNET_break (0); GNUNET_FS_uri_destroy (uri); GNUNET_free (emsg); return 1; } GNUNET_assert (NULL == emsg); if (GNUNET_YES != GNUNET_FS_uri_test_equal (uri, uri2)) { GNUNET_break (0); GNUNET_FS_uri_destroy (uri); GNUNET_FS_uri_destroy (uri2); return 1; } GNUNET_FS_uri_destroy (uri2); GNUNET_FS_uri_destroy (uri); return 0; }
static int testFile (int i) { char *uri; struct GNUNET_FS_Uri *ret; char *emsg; if (NULL != (ret = GNUNET_FS_uri_parse ("gnunet://fs/chk/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820.RNVVVVOOLCLK065B5D04HTNVNSIB2AI022RG8200HSLK1CO1000ATQ98824DMA2032LIMG50CG0K057NVUVG200000H00000440000.42", &emsg))) { GNUNET_FS_uri_destroy (ret); GNUNET_assert (0); } GNUNET_free (emsg); if (NULL != (ret = GNUNET_FS_uri_parse ("gnunet://fs/chk/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820.RNVVVVOOLCLK065B5D04HTNVNSIB2AI022RG8200HSLK1CO1000ATQ98824DMA2032LIMG50CG0K057NVUVG200000H000004400000", &emsg))) { GNUNET_FS_uri_destroy (ret); GNUNET_assert (0); } GNUNET_free (emsg); if (NULL != (ret = GNUNET_FS_uri_parse ("gnunet://fs/chk/C282GG70GKK41O4551011DO413KFBVTVMQG1OG30I0K4045N0G41HAPB82G680A02JRVVFO8URVRU2F159011DO41000000022RG820.RNVVVVOOLCLK065B5D04HTNVNSIB2AI022RG8200HSLK1CO1000ATQ98824DMA2032LIMG50CG0K057NVUVG200000H000004400000.FGH", &emsg))) { GNUNET_FS_uri_destroy (ret); GNUNET_assert (0); } GNUNET_free (emsg); ret = GNUNET_FS_uri_parse ("gnunet://fs/chk/4QZP479A9SKGFNMQ2ZBCYE71YV2QMTVGWTVPB6A10ASVCKXDHB05DKPSC7ZF6E9P9W1VE47394EQY7NXA47Q6R35M7P1MJPGP59D1Z8.D54QD1K5XCG5878T6YZ19AM60MQ6FC0YNVK7QY08KK0KM0FJJ3KQWYG112FN5T07KN7J0X35DF6WVBT9B8ZMZ3X2BXJ22X3KFQ6MV2G.42", &emsg); if (ret == NULL) { GNUNET_free (emsg); GNUNET_assert (0); } if (GNUNET_FS_uri_test_ksk (ret)) { GNUNET_FS_uri_destroy (ret); GNUNET_assert (0); } if (GNUNET_FS_uri_test_sks (ret)) { GNUNET_FS_uri_destroy (ret); GNUNET_assert (0); } if (GNUNET_ntohll (ret->data.chk.file_length) != 42) { GNUNET_FS_uri_destroy (ret); GNUNET_assert (0); } uri = GNUNET_FS_uri_to_string (ret); if (0 != strcmp (uri, "gnunet://fs/chk/4QZP479A9SKGFNMQ2ZBCYE71YV2QMTVGWTVPB6A10ASVCKXDHB05DKPSC7ZF6E9P9W1VE47394EQY7NXA47Q6R35M7P1MJPGP59D1Z8.D54QD1K5XCG5878T6YZ19AM60MQ6FC0YNVK7QY08KK0KM0FJJ3KQWYG112FN5T07KN7J0X35DF6WVBT9B8ZMZ3X2BXJ22X3KFQ6MV2G.42")) { GNUNET_free (uri); GNUNET_FS_uri_destroy (ret); GNUNET_assert (0); } GNUNET_free (uri); GNUNET_FS_uri_destroy (ret); return 0; }
static int testNamespace (int i) { char *uri; struct GNUNET_FS_Uri *ret; char *emsg; struct GNUNET_CRYPTO_EcdsaPrivateKey *ph; struct GNUNET_CRYPTO_EcdsaPublicKey id; char buf[1024]; char ubuf[1024]; char *sret; if (NULL != (ret = GNUNET_FS_uri_parse ("gnunet://fs/sks/D1KJS9H2A82Q65VKQ0ML3RFU6U1D3VUK", &emsg))) { GNUNET_FS_uri_destroy (ret); GNUNET_assert (0); } GNUNET_free (emsg); if (NULL != (ret = GNUNET_FS_uri_parse ("gnunet://fs/sks/XQHH4R288W26EBV369F6RCE0PJVJTX2Y74Q2FJPMPGA31HJX2JG/this", &emsg))) { GNUNET_FS_uri_destroy (ret); GNUNET_assert (0); } GNUNET_free (emsg); if (NULL != (ret = GNUNET_FS_uri_parse ("gnunet://fs/sks/test", &emsg))) { GNUNET_FS_uri_destroy (ret); GNUNET_assert (0); } GNUNET_free (emsg); ph = GNUNET_CRYPTO_ecdsa_key_create (); GNUNET_CRYPTO_ecdsa_key_get_public (ph, &id); sret = GNUNET_STRINGS_data_to_string (&id, sizeof (id), ubuf, sizeof (ubuf) - 1); GNUNET_assert (NULL != sret); sret[0] = '\0'; GNUNET_snprintf (buf, sizeof (buf), "gnunet://fs/sks/%s/test", ubuf); ret = GNUNET_FS_uri_parse (buf, &emsg); if (NULL == ret) { GNUNET_free (emsg); GNUNET_assert (0); } if (GNUNET_FS_uri_test_ksk (ret)) { GNUNET_FS_uri_destroy (ret); GNUNET_assert (0); } if (!GNUNET_FS_uri_test_sks (ret)) { GNUNET_FS_uri_destroy (ret); GNUNET_assert (0); } uri = GNUNET_FS_uri_to_string (ret); if (0 != strcmp (uri, buf)) { GNUNET_FS_uri_destroy (ret); GNUNET_free (uri); GNUNET_assert (0); } GNUNET_free (uri); GNUNET_FS_uri_destroy (ret); return 0; }
/** * Publish a CHK under various keywords on GNUnet. * * @param h handle to the file sharing subsystem * @param ksk_uri keywords to use * @param meta metadata to use * @param uri URI to refer to in the KBlock * @param bo per-block options * @param options publication options * @param cont continuation * @param cont_cls closure for cont * @return NULL on error ('cont' will still be called) */ struct GNUNET_FS_PublishKskContext * GNUNET_FS_publish_ksk (struct GNUNET_FS_Handle *h, const struct GNUNET_FS_Uri *ksk_uri, const struct GNUNET_CONTAINER_MetaData *meta, const struct GNUNET_FS_Uri *uri, const struct GNUNET_FS_BlockOptions *bo, enum GNUNET_FS_PublishOptions options, GNUNET_FS_PublishContinuation cont, void *cont_cls) { struct GNUNET_FS_PublishKskContext *pkc; char *uris; size_t size; char *kbe; char *sptr; GNUNET_assert (NULL != uri); pkc = GNUNET_malloc (sizeof (struct GNUNET_FS_PublishKskContext)); pkc->h = h; pkc->bo = *bo; pkc->cont = cont; pkc->cont_cls = cont_cls; if (0 == (options & GNUNET_FS_PUBLISH_OPTION_SIMULATE_ONLY)) { pkc->dsh = GNUNET_DATASTORE_connect (h->cfg); if (NULL == pkc->dsh) { cont (cont_cls, NULL, _("Could not connect to datastore.")); GNUNET_free (pkc); return NULL; } } if (meta == NULL) pkc->mdsize = 0; else pkc->mdsize = GNUNET_CONTAINER_meta_data_get_serialized_size (meta); GNUNET_assert (pkc->mdsize >= 0); uris = GNUNET_FS_uri_to_string (uri); pkc->slen = strlen (uris) + 1; size = pkc->mdsize + sizeof (struct KBlock) + pkc->slen; if (size > MAX_KBLOCK_SIZE) { size = MAX_KBLOCK_SIZE; pkc->mdsize = size - sizeof (struct KBlock) - pkc->slen; } pkc->kb = GNUNET_malloc (size); kbe = (char *) &pkc->kb[1]; memcpy (kbe, uris, pkc->slen); GNUNET_free (uris); sptr = &kbe[pkc->slen]; if (meta != NULL) pkc->mdsize = GNUNET_CONTAINER_meta_data_serialize (meta, &sptr, pkc->mdsize, GNUNET_CONTAINER_META_DATA_SERIALIZE_PART); if (-1 == pkc->mdsize) { GNUNET_break (0); GNUNET_free (pkc->kb); if (pkc->dsh != NULL) { GNUNET_DATASTORE_disconnect (pkc->dsh, GNUNET_NO); pkc->dsh = NULL; } GNUNET_free (pkc); cont (cont_cls, NULL, _("Internal error.")); return NULL; } size = sizeof (struct KBlock) + pkc->slen + pkc->mdsize; pkc->cpy = GNUNET_malloc (size); pkc->cpy->purpose.size = htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) + sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) + pkc->mdsize + pkc->slen); pkc->cpy->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_FS_KBLOCK); pkc->ksk_uri = GNUNET_FS_uri_dup (ksk_uri); pkc->ksk_task = GNUNET_SCHEDULER_add_now (&publish_ksk_cont, pkc); return pkc; }
/** * Called by FS client to give information about the progress of an * operation. * * @param cls closure * @param info details about the event, specifying the event type * and various bits about the event * @return client-context (for the next progress call * for this operation; should be set to NULL for * SUSPEND and STOPPED events). The value returned * will be passed to future callbacks in the respective * field in the GNUNET_FS_ProgressInfo struct. */ static void * progress_cb (void *cls, const struct GNUNET_FS_ProgressInfo *info) { static unsigned int cnt; int is_directory; char *uri; char *filename; switch (info->status) { case GNUNET_FS_STATUS_SEARCH_START: break; case GNUNET_FS_STATUS_SEARCH_RESULT: if (db != NULL) GNUNET_FS_directory_builder_add (db, info->value.search.specifics.result.uri, info->value.search.specifics.result.meta, NULL); uri = GNUNET_FS_uri_to_string (info->value.search.specifics.result.uri); printf ("#%u:\n", cnt++); filename = GNUNET_CONTAINER_meta_data_get_by_type (info->value.search. specifics.result.meta, EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME); is_directory = GNUNET_FS_meta_data_test_for_directory (info->value.search. specifics.result.meta); if (filename != NULL) { GNUNET_DISK_filename_canonicalize (filename); if (GNUNET_YES == is_directory) printf ("gnunet-download -o \"%s%s\" -R %s\n", filename, GNUNET_FS_DIRECTORY_EXT, uri); else printf ("gnunet-download -o \"%s\" %s\n", filename, uri); } else if (GNUNET_YES == is_directory) printf ("gnunet-download -o \"collection%s\" -R %s\n", GNUNET_FS_DIRECTORY_EXT, uri); else printf ("gnunet-download %s\n", uri); if (verbose) GNUNET_CONTAINER_meta_data_iterate (info->value.search.specifics. result.meta, &item_printer, NULL); printf ("\n"); fflush (stdout); GNUNET_free_non_null (filename); GNUNET_free (uri); results++; if ((results_limit > 0) && (results >= results_limit)) GNUNET_SCHEDULER_shutdown (); break; case GNUNET_FS_STATUS_SEARCH_UPDATE: break; case GNUNET_FS_STATUS_SEARCH_RESULT_STOPPED: /* ignore */ break; case GNUNET_FS_STATUS_SEARCH_ERROR: FPRINTF (stderr, _("Error searching: %s.\n"), info->value.search.specifics.error.message); GNUNET_SCHEDULER_shutdown (); break; case GNUNET_FS_STATUS_SEARCH_STOPPED: GNUNET_SCHEDULER_add_now (&clean_task, NULL); break; default: FPRINTF (stderr, _("Unexpected status: %d\n"), info->status); break; } return NULL; }
/** * Add an entry to a directory. * * @param bld directory to extend * @param uri uri of the entry (must not be a KSK) * @param md metadata of the entry * @param data raw data of the entry, can be NULL, otherwise * data must point to exactly the number of bytes specified * by the uri which must be of type LOC or CHK */ void GNUNET_FS_directory_builder_add (struct GNUNET_FS_DirectoryBuilder *bld, const struct GNUNET_FS_Uri *uri, const struct GNUNET_CONTAINER_MetaData *md, const void *data) { struct GNUNET_FS_Uri *curi; struct BuilderEntry *e; uint64_t fsize; uint32_t big; ssize_t ret; size_t mds; size_t mdxs; char *uris; char *ser; char *sptr; size_t slen; struct GNUNET_CONTAINER_MetaData *meta; const struct GNUNET_CONTAINER_MetaData *meta_use; GNUNET_assert (!GNUNET_FS_uri_test_ksk (uri)); if (NULL != data) { GNUNET_assert (!GNUNET_FS_uri_test_sks (uri)); if (GNUNET_FS_uri_test_chk (uri)) { fsize = GNUNET_FS_uri_chk_get_file_size (uri); } else { curi = GNUNET_FS_uri_loc_get_uri (uri); GNUNET_assert (NULL != curi); fsize = GNUNET_FS_uri_chk_get_file_size (curi); GNUNET_FS_uri_destroy (curi); } } else { fsize = 0; /* not given */ } if (fsize > MAX_INLINE_SIZE) fsize = 0; /* too large */ uris = GNUNET_FS_uri_to_string (uri); slen = strlen (uris) + 1; mds = GNUNET_CONTAINER_meta_data_get_serialized_size (md); meta_use = md; meta = NULL; if (fsize > 0) { meta = GNUNET_CONTAINER_meta_data_duplicate (md); GNUNET_CONTAINER_meta_data_insert (meta, "<gnunet>", EXTRACTOR_METATYPE_GNUNET_FULL_DATA, EXTRACTOR_METAFORMAT_BINARY, NULL, data, fsize); mdxs = GNUNET_CONTAINER_meta_data_get_serialized_size (meta); if ((slen + sizeof (uint32_t) + mdxs - 1) / DBLOCK_SIZE == (slen + sizeof (uint32_t) + mds - 1) / DBLOCK_SIZE) { /* adding full data would not cause us to cross * additional blocks, so add it! */ meta_use = meta; mds = mdxs; } } if (mds > GNUNET_MAX_MALLOC_CHECKED / 2) mds = GNUNET_MAX_MALLOC_CHECKED / 2; e = GNUNET_malloc (sizeof (struct BuilderEntry) + slen + mds + sizeof (uint32_t)); ser = (char *) &e[1]; memcpy (ser, uris, slen); GNUNET_free (uris); sptr = &ser[slen + sizeof (uint32_t)]; ret = GNUNET_CONTAINER_meta_data_serialize (meta_use, &sptr, mds, GNUNET_CONTAINER_META_DATA_SERIALIZE_PART); if (NULL != meta) GNUNET_CONTAINER_meta_data_destroy (meta); if (ret == -1) mds = 0; else mds = ret; big = htonl (mds); memcpy (&ser[slen], &big, sizeof (uint32_t)); e->len = slen + sizeof (uint32_t) + mds; e->next = bld->head; bld->head = e; bld->count++; }