+ clen = 0;
+ cdata = NULL;
+ left = size;
+ i = 0;
+ pos = md->items;
+ while (pos != NULL)
+ {
+ comp = GNUNET_NO;
+ if (0 == (opt & GNUNET_CONTAINER_META_DATA_SERIALIZE_NO_COMPRESS))
+ comp = try_compression ((const char*) &ent[i],
+ left,
+ &cdata,
+ &clen);
+
+ if ( (md->sbuf == NULL) &&
+ (i == 0) )
+ {
+ /* fill 'sbuf'; this "modifies" md, but since this is only
+ an internal cache we will cast away the 'const' instead
+ of making the API look strange. */
+ vmd = (struct GNUNET_CONTAINER_MetaData*) md;
+ hdr = GNUNET_malloc (left + sizeof (struct MetaDataHeader));
+ hdr->size = htonl (left);
+ hdr->entries = htonl (md->item_count);
+ if (GNUNET_YES == comp)
+ {
+ GNUNET_assert (clen < left);
+ hdr->version = htonl (2 | HEADER_COMPRESSED);
+ memcpy (&hdr[1],
+ cdata,
+ clen);
+ vmd->sbuf_size = clen + sizeof (struct MetaDataHeader);
+ }
+ else
+ {
+ hdr->version = htonl (2);
+ memcpy (&hdr[1],
+ &ent[0],
+ left);
+ vmd->sbuf_size = left + sizeof (struct MetaDataHeader);
+ }
+ vmd->sbuf = (char*) hdr;
+ }
+
+ if ( ( (left + sizeof (struct MetaDataHeader)) <= max) ||
+ ( (comp == GNUNET_YES) &&
+ (clen <= max)) )
+ {
+ /* success, this now fits! */
+ if (GNUNET_YES == comp)
+ {
+ if (dst == NULL)
+ dst = GNUNET_malloc (clen + sizeof (struct MetaDataHeader));
+ hdr = (struct MetaDataHeader*) dst;
+ hdr->version = htonl (2 | HEADER_COMPRESSED);
+ hdr->size = htonl (left);
+ hdr->entries = htonl (md->item_count - i);
+ memcpy (&dst[sizeof(struct MetaDataHeader)],
+ cdata,
+ clen);
+ GNUNET_free (cdata);
+ GNUNET_free (ent);
+ rlen = clen + sizeof (struct MetaDataHeader);
+ }
+ else
+ {
+ if (dst == NULL)
+ dst = GNUNET_malloc (left + sizeof (struct MetaDataHeader));
+ hdr = (struct MetaDataHeader*) dst;
+ hdr->version = htonl (2);
+ hdr->entries = htonl (md->item_count - i);
+ hdr->size = htonl (left);
+ memcpy (&dst[sizeof(struct MetaDataHeader)],
+ &ent[i],
+ left);
+ GNUNET_free (ent);
+ rlen = left + sizeof (struct MetaDataHeader);
+ }
+ if (NULL != *target)
+ {
+ memcpy (*target, dst, clen + sizeof (struct MetaDataHeader));
+ GNUNET_free (dst);
+ }
+ else
+ {
+ *target = dst;
+ }
+ return rlen;
+ }
+
+ if (0 == (opt & GNUNET_CONTAINER_META_DATA_SERIALIZE_PART))
+ {
+ /* does not fit! */
+ GNUNET_free (ent);
+ return GNUNET_SYSERR;