GNUnet  0.10.x
container_meta_data.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009, 2010 GNUnet e.V.
4 
5  GNUnet is free software: you can redistribute it and/or modify it
6  under the terms of the GNU Affero General Public License as published
7  by the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  GNUnet is distributed in the hope that it will be useful, but
11  WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Affero General Public License for more details.
14 
15  You should have received a copy of the GNU Affero General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  SPDX-License-Identifier: AGPL3.0-or-later
19 */
20 
27 #include "platform.h"
28 #include "gnunet_util_lib.h"
29 #if HAVE_EXTRACTOR_H
30 #include <extractor.h>
31 #endif
32 #include <zlib.h>
33 
34 #define LOG(kind,...) GNUNET_log_from (kind, "util-container-meta-data", __VA_ARGS__)
35 
36 
37 
53 int
55  size_t old_size,
56  char **result,
57  size_t *new_size)
58 {
59  char *tmp;
60  uLongf dlen;
61 
62  *result = NULL;
63  *new_size = 0;
64 #ifdef compressBound
65  dlen = compressBound (old_size);
66 #else
67  dlen = old_size + (old_size / 100) + 20;
68  /* documentation says 100.1% oldSize + 12 bytes, but we
69  * should be able to overshoot by more to be safe */
70 #endif
71  tmp = GNUNET_malloc (dlen);
72  if (Z_OK ==
73  compress2 ((Bytef *) tmp,
74  &dlen,
75  (const Bytef *) data,
76  old_size, 9))
77  {
78  if (dlen < old_size)
79  {
80  *result = tmp;
81  *new_size = dlen;
82  return GNUNET_YES;
83  }
84  }
85  GNUNET_free (tmp);
86  return GNUNET_NO;
87 }
88 
89 
100 char *
101 GNUNET_decompress (const char *input,
102  size_t input_size,
103  size_t output_size)
104 {
105  char *output;
106  uLongf olen;
107 
108  olen = output_size;
109  output = GNUNET_malloc (olen);
110  if (Z_OK ==
111  uncompress ((Bytef *) output,
112  &olen,
113  (const Bytef *) input,
114  input_size))
115  return output;
116  GNUNET_free (output);
117  return NULL;
118 }
119 
120 
124 struct MetaItem
125 {
129  struct MetaItem *next;
130 
134  struct MetaItem *prev;
135 
139  char *plugin_name;
140 
144  char *mime_type;
145 
149  char *data;
150 
154  size_t data_size;
155 
160 
165 
166 };
167 
172 {
177 
182 
187  char *sbuf;
188 
192  size_t sbuf_size;
193 
197  unsigned int item_count;
198 
199 };
200 
201 
209 {
210  return GNUNET_new (struct GNUNET_CONTAINER_MetaData);
211 }
212 
213 
219 static void
221 {
225  GNUNET_free (mi);
226 }
227 
228 
235 static void
237 {
238  if (NULL == md->sbuf)
239  return;
240  GNUNET_free (md->sbuf);
241  md->sbuf = NULL;
242  md->sbuf_size = 0;
243 }
244 
245 
251 void
253 {
254  struct MetaItem *pos;
255 
256  if (NULL == md)
257  return;
258  while (NULL != (pos = md->items_head))
259  {
261  meta_item_free (pos);
262  }
264  GNUNET_free (md);
265 }
266 
267 
273 void
275 {
276  struct MetaItem *mi;
277 
278  if (NULL == md)
279  return;
280  while (NULL != (mi = md->items_head))
281  {
283  meta_item_free (mi);
284  }
286  memset (md, 0, sizeof (struct GNUNET_CONTAINER_MetaData));
287 }
288 
289 
300 int
302  *md1,
303  const struct GNUNET_CONTAINER_MetaData
304  *md2)
305 {
306  struct MetaItem *i;
307  struct MetaItem *j;
308  int found;
309 
310  if (md1 == md2)
311  return GNUNET_YES;
312  if (md1->item_count != md2->item_count)
313  return GNUNET_NO;
314  for (i = md1->items_head; NULL != i; i = i->next)
315  {
316  found = GNUNET_NO;
317  for (j = md2->items_head; NULL != j; j = j->next)
318  {
319  if ((i->type == j->type) && (i->format == j->format) &&
320  (i->data_size == j->data_size) &&
321  (0 == memcmp (i->data, j->data, i->data_size)))
322  {
323  found = GNUNET_YES;
324  break;
325  }
326  if (j->data_size < i->data_size)
327  break; /* elements are sorted by (decreasing) size... */
328  }
329  if (GNUNET_NO == found)
330  return GNUNET_NO;
331  }
332  return GNUNET_YES;
333 }
334 
335 
354 int
356  const char *plugin_name,
359  const char *data_mime_type, const char *data,
360  size_t data_size)
361 {
362  struct MetaItem *pos;
363  struct MetaItem *mi;
364  char *p;
365 
366  if ((EXTRACTOR_METAFORMAT_UTF8 == format) ||
367  (EXTRACTOR_METAFORMAT_C_STRING == format))
368  GNUNET_break ('\0' == data[data_size - 1]);
369 
370  for (pos = md->items_head; NULL != pos; pos = pos->next)
371  {
372  if (pos->data_size < data_size)
373  break; /* elements are sorted by size in the list */
374  if ((pos->type == type) && (pos->data_size == data_size) &&
375  (0 == memcmp (pos->data, data, data_size)))
376  {
377  if ((NULL == pos->mime_type) && (NULL != data_mime_type))
378  {
379  pos->mime_type = GNUNET_strdup (data_mime_type);
380  invalidate_sbuf (md);
381  }
382  if ((EXTRACTOR_METAFORMAT_C_STRING == pos->format) &&
383  (EXTRACTOR_METAFORMAT_UTF8 == format))
384  {
386  invalidate_sbuf (md);
387  }
388  return GNUNET_SYSERR;
389  }
390  }
391  md->item_count++;
392  mi = GNUNET_new (struct MetaItem);
393  mi->type = type;
394  mi->format = format;
395  mi->data_size = data_size;
396  if (NULL == pos)
398  md->items_tail,
399  mi);
400  else
402  md->items_tail,
403  pos->prev,
404  mi);
405  mi->mime_type =
406  (NULL == data_mime_type) ? NULL : GNUNET_strdup (data_mime_type);
407  mi->plugin_name = (NULL == plugin_name) ? NULL : GNUNET_strdup (plugin_name);
408  mi->data = GNUNET_malloc (data_size);
409  GNUNET_memcpy (mi->data, data, data_size);
410  /* change all dir separators to POSIX style ('/') */
411  if ( (EXTRACTOR_METATYPE_FILENAME == type) ||
413  {
414  p = mi->data;
415  while (('\0' != *p) && (p < mi->data + data_size))
416  {
417  if ('\\' == *p)
418  *p = '/';
419  p++;
420  }
421  }
422  invalidate_sbuf (md);
423  return GNUNET_OK;
424 }
425 
426 
443 static int
444 merge_helper (void *cls, const char *plugin_name, enum EXTRACTOR_MetaType type,
445  enum EXTRACTOR_MetaFormat format, const char *data_mime_type,
446  const char *data, size_t data_size)
447 {
448  struct GNUNET_CONTAINER_MetaData *md = cls;
449 
450  (void) GNUNET_CONTAINER_meta_data_insert (md, plugin_name, type, format,
451  data_mime_type, data, data_size);
452  return 0;
453 }
454 
455 
463 void
465  const struct GNUNET_CONTAINER_MetaData *in)
466 {
468 }
469 
470 
481 int
484  const char *data, size_t data_size)
485 {
486  struct MetaItem *pos;
487 
488  for (pos = md->items_head; NULL != pos; pos = pos->next)
489  {
490  if (pos->data_size < data_size)
491  break; /* items are sorted by (decreasing) size */
492  if ((pos->type == type) &&
493  ((NULL == data) ||
494  ((pos->data_size == data_size) &&
495  (0 == memcmp (pos->data, data, data_size)))))
496  {
498  meta_item_free (pos);
499  md->item_count--;
500  invalidate_sbuf (md);
501  return GNUNET_OK;
502  }
503  }
504  return GNUNET_SYSERR;
505 }
506 
507 
514 void
517 {
518  const char *dat;
519  struct GNUNET_TIME_Absolute t;
520 
524  NULL, 0);
526  GNUNET_CONTAINER_meta_data_insert (md, "<gnunet>",
528  EXTRACTOR_METAFORMAT_UTF8, "text/plain",
529  dat, strlen (dat) + 1);
530 }
531 
532 
541 int
544  void *iter_cls)
545 {
546  struct MetaItem *pos;
547 
548  if (NULL == md)
549  return 0;
550  if (NULL == iter)
551  return md->item_count;
552  for (pos = md->items_head; NULL != pos; pos = pos->next)
553  if (0 !=
554  iter (iter_cls, pos->plugin_name, pos->type, pos->format,
555  pos->mime_type, pos->data, pos->data_size))
556  return md->item_count;
557  return md->item_count;
558 }
559 
560 
571 char *
574 {
575  struct MetaItem *pos;
576 
577  if (NULL == md)
578  return NULL;
579  for (pos = md->items_head; NULL != pos; pos = pos->next)
580  if ((type == pos->type) &&
581  ((pos->format == EXTRACTOR_METAFORMAT_UTF8) ||
583  return GNUNET_strdup (pos->data);
584  return NULL;
585 }
586 
587 
599 char *
602  ...)
603 {
604  char *ret;
605  va_list args;
606  int type;
607 
608  if (NULL == md)
609  return NULL;
610  ret = NULL;
611  va_start (args, md);
612  while (1)
613  {
614  type = va_arg (args, int);
615  if (-1 == type)
616  break;
617  if (NULL != (ret = GNUNET_CONTAINER_meta_data_get_by_type (md, type)))
618  break;
619  }
620  va_end (args);
621  return ret;
622 }
623 
624 
633 size_t
635  * md, unsigned char **thumb)
636 {
637  struct MetaItem *pos;
638  struct MetaItem *match;
639 
640  if (NULL == md)
641  return 0;
642  match = NULL;
643  for (pos = md->items_head; NULL != pos; pos = pos->next)
644  {
645  if ((NULL != pos->mime_type) &&
646  (0 == strncasecmp ("image/", pos->mime_type, strlen ("image/"))) &&
648  {
649  if (NULL == match)
650  match = pos;
651  else if ((match->type != EXTRACTOR_METATYPE_THUMBNAIL) &&
653  match = pos;
654  }
655  }
656  if ((NULL == match) || (0 == match->data_size))
657  return 0;
658  *thumb = GNUNET_malloc (match->data_size);
659  GNUNET_memcpy (*thumb, match->data, match->data_size);
660  return match->data_size;
661 }
662 
663 
672  *md)
673 {
675  struct MetaItem *pos;
676 
677  if (NULL == md)
678  return NULL;
680  for (pos = md->items_tail; NULL != pos; pos = pos->prev)
682  pos->format, pos->mime_type, pos->data,
683  pos->data_size);
684  return ret;
685 }
686 
687 
691 #define HEADER_COMPRESSED 0x80000000
692 
693 
697 #define HEADER_VERSION_MASK 0x7FFFFFFF
698 
699 
704 {
714  uint32_t version;
715 
719  uint32_t entries;
720 
724  uint32_t size;
725 
731 };
732 
733 
738 {
742  uint32_t type;
743 
747  uint32_t format;
748 
752  uint32_t data_size;
753 
757  uint32_t plugin_name_len;
758 
762  uint32_t mime_type_len;
763 
764 };
765 
766 
781 ssize_t
783  *md, char **target, size_t max,
784  enum
786  opt)
787 {
788  struct GNUNET_CONTAINER_MetaData *vmd;
789  struct MetaItem *pos;
790  struct MetaDataHeader ihdr;
791  struct MetaDataHeader *hdr;
792  struct MetaDataEntry *ent;
793  char *dst;
794  unsigned int i;
795  uint64_t msize;
796  size_t off;
797  char *mdata;
798  char *cdata;
799  size_t mlen;
800  size_t plen;
801  size_t size;
802  size_t left;
803  size_t clen;
804  size_t rlen;
805  int comp;
806 
807  if (max < sizeof (struct MetaDataHeader))
808  return GNUNET_SYSERR; /* far too small */
809  if (NULL == md)
810  return 0;
811 
812  if (NULL != md->sbuf)
813  {
814  /* try to use serialization cache */
815  if (md->sbuf_size <= max)
816  {
817  if (NULL == *target)
818  *target = GNUNET_malloc (md->sbuf_size);
819  GNUNET_memcpy (*target, md->sbuf, md->sbuf_size);
820  return md->sbuf_size;
821  }
823  return GNUNET_SYSERR; /* can say that this will fail */
824  /* need to compute a partial serialization, sbuf useless ... */
825  }
826  dst = NULL;
827  msize = 0;
828  for (pos = md->items_tail; NULL != pos; pos = pos->prev)
829  {
830  msize += sizeof (struct MetaDataEntry);
831  msize += pos->data_size;
832  if (NULL != pos->plugin_name)
833  msize += strlen (pos->plugin_name) + 1;
834  if (NULL != pos->mime_type)
835  msize += strlen (pos->mime_type) + 1;
836  }
837  size = (size_t) msize;
838  if (size != msize)
839  {
840  GNUNET_break (0); /* integer overflow */
841  return GNUNET_SYSERR;
842  }
843  if (size >= GNUNET_MAX_MALLOC_CHECKED)
844  {
845  /* too large to be processed */
846  return GNUNET_SYSERR;
847  }
848  ent = GNUNET_malloc (size);
849  mdata = (char *) &ent[md->item_count];
850  off = size - (md->item_count * sizeof (struct MetaDataEntry));
851  i = 0;
852  for (pos = md->items_head; NULL != pos; pos = pos->next)
853  {
854  ent[i].type = htonl ((uint32_t) pos->type);
855  ent[i].format = htonl ((uint32_t) pos->format);
856  ent[i].data_size = htonl ((uint32_t) pos->data_size);
857  if (NULL == pos->plugin_name)
858  plen = 0;
859  else
860  plen = strlen (pos->plugin_name) + 1;
861  ent[i].plugin_name_len = htonl ((uint32_t) plen);
862  if (NULL == pos->mime_type)
863  mlen = 0;
864  else
865  mlen = strlen (pos->mime_type) + 1;
866  ent[i].mime_type_len = htonl ((uint32_t) mlen);
867  off -= pos->data_size;
868  if ((EXTRACTOR_METAFORMAT_UTF8 == pos->format) ||
870  GNUNET_break ('\0' == pos->data[pos->data_size - 1]);
871  GNUNET_memcpy (&mdata[off], pos->data, pos->data_size);
872  off -= plen;
873  if (NULL != pos->plugin_name)
874  GNUNET_memcpy (&mdata[off], pos->plugin_name, plen);
875  off -= mlen;
876  if (NULL != pos->mime_type)
877  GNUNET_memcpy (&mdata[off], pos->mime_type, mlen);
878  i++;
879  }
880  GNUNET_assert (0 == off);
881 
882  clen = 0;
883  cdata = NULL;
884  left = size;
885  i = 0;
886  for (pos = md->items_head; NULL != pos; pos = pos->next)
887  {
888  comp = GNUNET_NO;
890  comp = GNUNET_try_compression ((const char *) &ent[i],
891  left,
892  &cdata,
893  &clen);
894 
895  if ((NULL == md->sbuf) && (0 == i))
896  {
897  /* fill 'sbuf'; this "modifies" md, but since this is only
898  * an internal cache we will cast away the 'const' instead
899  * of making the API look strange. */
900  vmd = (struct GNUNET_CONTAINER_MetaData *) md;
901  hdr = GNUNET_malloc (left + sizeof (struct MetaDataHeader));
902  hdr->size = htonl (left);
903  hdr->entries = htonl (md->item_count);
904  if (GNUNET_YES == comp)
905  {
906  GNUNET_assert (clen < left);
907  hdr->version = htonl (2 | HEADER_COMPRESSED);
908  GNUNET_memcpy (&hdr[1], cdata, clen);
909  vmd->sbuf_size = clen + sizeof (struct MetaDataHeader);
910  }
911  else
912  {
913  hdr->version = htonl (2);
914  GNUNET_memcpy (&hdr[1], &ent[0], left);
915  vmd->sbuf_size = left + sizeof (struct MetaDataHeader);
916  }
917  vmd->sbuf = (char *) hdr;
918  }
919 
920  if (((left + sizeof (struct MetaDataHeader)) <= max) ||
921  ((GNUNET_YES == comp) && (clen <= max)))
922  {
923  /* success, this now fits! */
924  if (GNUNET_YES == comp)
925  {
926  if (NULL == dst)
927  dst = GNUNET_malloc (clen + sizeof (struct MetaDataHeader));
928  hdr = (struct MetaDataHeader *) dst;
929  hdr->version = htonl (2 | HEADER_COMPRESSED);
930  hdr->size = htonl (left);
931  hdr->entries = htonl (md->item_count - i);
932  GNUNET_memcpy (&dst[sizeof (struct MetaDataHeader)], cdata, clen);
933  GNUNET_free (cdata);
934  cdata = NULL;
935  GNUNET_free (ent);
936  rlen = clen + sizeof (struct MetaDataHeader);
937  }
938  else
939  {
940  if (NULL == dst)
941  dst = GNUNET_malloc (left + sizeof (struct MetaDataHeader));
942  hdr = (struct MetaDataHeader *) dst;
943  hdr->version = htonl (2);
944  hdr->entries = htonl (md->item_count - i);
945  hdr->size = htonl (left);
946  GNUNET_memcpy (&dst[sizeof (struct MetaDataHeader)], &ent[i], left);
947  GNUNET_free (ent);
948  rlen = left + sizeof (struct MetaDataHeader);
949  }
950  if (NULL != *target)
951  {
952  if (GNUNET_YES == comp)
953  GNUNET_memcpy (*target, dst, clen + sizeof (struct MetaDataHeader));
954  else
955  GNUNET_memcpy (*target, dst, left + sizeof (struct MetaDataHeader));
956  GNUNET_free (dst);
957  }
958  else
959  {
960  *target = dst;
961  }
962  return rlen;
963  }
964 
966  {
967  /* does not fit! */
968  GNUNET_free (ent);
969  return GNUNET_SYSERR;
970  }
971 
972  /* next iteration: ignore the corresponding meta data at the
973  * end and try again without it */
974  left -= sizeof (struct MetaDataEntry);
975  left -= pos->data_size;
976  if (NULL != pos->plugin_name)
977  left -= strlen (pos->plugin_name) + 1;
978  if (NULL != pos->mime_type)
979  left -= strlen (pos->mime_type) + 1;
980 
981  GNUNET_free_non_null (cdata);
982  cdata = NULL;
983 
984  i++;
985  }
986  GNUNET_free (ent);
987 
988  /* nothing fit, only write header! */
989  ihdr.version = htonl (2);
990  ihdr.entries = htonl (0);
991  ihdr.size = htonl (0);
992  if (NULL == *target)
993  *target = (char *) GNUNET_new (struct MetaDataHeader);
994  GNUNET_memcpy (*target, &ihdr, sizeof (struct MetaDataHeader));
995  return sizeof (struct MetaDataHeader);
996 }
997 
998 
1005 ssize_t
1008 {
1009  ssize_t ret;
1010  char *ptr;
1011 
1012  if (NULL != md->sbuf)
1013  return md->sbuf_size;
1014  ptr = NULL;
1015  ret =
1018  if (-1 != ret)
1019  GNUNET_free (ptr);
1020  return ret;
1021 }
1022 
1023 
1034 {
1035  struct GNUNET_CONTAINER_MetaData *md;
1036  struct MetaDataHeader hdr;
1037  struct MetaDataEntry ent;
1038  uint32_t ic;
1039  uint32_t i;
1040  char *data;
1041  const char *cdata;
1042  uint32_t version;
1043  uint32_t dataSize;
1044  int compressed;
1045  size_t left;
1046  uint32_t mlen;
1047  uint32_t plen;
1048  uint32_t dlen;
1049  const char *mdata;
1050  const char *meta_data;
1051  const char *plugin_name;
1052  const char *mime_type;
1054 
1055  if (size < sizeof (struct MetaDataHeader))
1056  return NULL;
1057  GNUNET_memcpy (&hdr, input, sizeof (struct MetaDataHeader));
1058  version = ntohl (hdr.version) & HEADER_VERSION_MASK;
1059  compressed = (ntohl (hdr.version) & HEADER_COMPRESSED) != 0;
1060 
1061  if (1 == version)
1062  return NULL; /* null pointer */
1063  if (2 != version)
1064  {
1065  GNUNET_break_op (0); /* unsupported version */
1066  return NULL;
1067  }
1068 
1069  ic = ntohl (hdr.entries);
1070  dataSize = ntohl (hdr.size);
1071  if ( ((sizeof (struct MetaDataEntry) * ic) > dataSize) ||
1072  ( (0 != ic) &&
1073  (dataSize / ic < sizeof (struct MetaDataEntry)) ) )
1074  {
1075  GNUNET_break_op (0);
1076  return NULL;
1077  }
1078 
1079  if (compressed)
1080  {
1081  if (dataSize >= GNUNET_MAX_MALLOC_CHECKED)
1082  {
1083  /* make sure we don't blow our memory limit because of a mal-formed
1084  * message... */
1085  GNUNET_break_op (0);
1086  return NULL;
1087  }
1088  data =
1089  GNUNET_decompress ((const char *) &input[sizeof (struct MetaDataHeader)],
1090  size - sizeof (struct MetaDataHeader),
1091  dataSize);
1092  if (NULL == data)
1093  {
1094  GNUNET_break_op (0);
1095  return NULL;
1096  }
1097  cdata = data;
1098  }
1099  else
1100  {
1101  data = NULL;
1102  cdata = (const char *) &input[sizeof (struct MetaDataHeader)];
1103  if (dataSize != size - sizeof (struct MetaDataHeader))
1104  {
1105  GNUNET_break_op (0);
1106  return NULL;
1107  }
1108  }
1109 
1111  left = dataSize - ic * sizeof (struct MetaDataEntry);
1112  mdata = &cdata[ic * sizeof (struct MetaDataEntry)];
1113  for (i = 0; i < ic; i++)
1114  {
1115  GNUNET_memcpy (&ent, &cdata[i * sizeof (struct MetaDataEntry)],
1116  sizeof (struct MetaDataEntry));
1117  format = (enum EXTRACTOR_MetaFormat) ntohl (ent.format);
1118  if ((EXTRACTOR_METAFORMAT_UTF8 != format) &&
1120  (EXTRACTOR_METAFORMAT_BINARY != format))
1121  {
1122  GNUNET_break_op (0);
1123  break;
1124  }
1125  dlen = ntohl (ent.data_size);
1126  plen = ntohl (ent.plugin_name_len);
1127  mlen = ntohl (ent.mime_type_len);
1128  if (dlen > left)
1129  {
1130  GNUNET_break_op (0);
1131  break;
1132  }
1133  left -= dlen;
1134  meta_data = &mdata[left];
1135  if ((EXTRACTOR_METAFORMAT_UTF8 == format) ||
1136  (EXTRACTOR_METAFORMAT_C_STRING == format))
1137  {
1138  if (0 == dlen)
1139  {
1140  GNUNET_break_op (0);
1141  break;
1142  }
1143  if ('\0' != meta_data[dlen - 1])
1144  {
1145  GNUNET_break_op (0);
1146  break;
1147  }
1148  }
1149  if (plen > left)
1150  {
1151  GNUNET_break_op (0);
1152  break;
1153  }
1154  left -= plen;
1155  if ((plen > 0) && ('\0' != mdata[left + plen - 1]))
1156  {
1157  GNUNET_break_op (0);
1158  break;
1159  }
1160  if (0 == plen)
1161  plugin_name = NULL;
1162  else
1163  plugin_name = &mdata[left];
1164 
1165  if (mlen > left)
1166  {
1167  GNUNET_break_op (0);
1168  break;
1169  }
1170  left -= mlen;
1171  if ((mlen > 0) && ('\0' != mdata[left + mlen - 1]))
1172  {
1173  GNUNET_break_op (0);
1174  break;
1175  }
1176  if (0 == mlen)
1177  mime_type = NULL;
1178  else
1179  mime_type = &mdata[left];
1180  GNUNET_CONTAINER_meta_data_insert (md, plugin_name,
1181  (enum EXTRACTOR_MetaType)
1182  ntohl (ent.type), format, mime_type,
1183  meta_data, dlen);
1184  }
1185  GNUNET_free_non_null (data);
1186  return md;
1187 }
1188 
1189 
1190 /* end of container_meta_data.c */
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
ssize_t GNUNET_CONTAINER_meta_data_get_serialized_size(const struct GNUNET_CONTAINER_MetaData *md)
Get the size of the full meta-data in serialized form.
EXTRACTOR_MetaFormat
Format in which the extracted meta data is presented.
void GNUNET_CONTAINER_meta_data_clear(struct GNUNET_CONTAINER_MetaData *md)
Remove all items in the container.
ssize_t GNUNET_CONTAINER_meta_data_serialize(const struct GNUNET_CONTAINER_MetaData *md, char **target, size_t max, enum GNUNET_CONTAINER_MetaDataSerializationOptions opt)
Serialize meta-data to target.
If not enough space is available, it is acceptable to only serialize some of the metadata.
#define HEADER_COMPRESSED
Flag in &#39;version&#39; that indicates compressed meta-data.
Some kind of binary format, see given Mime type.
char * data
The actual meta data.
struct MetaItem * items_head
Head of linked list of the meta data items.
void GNUNET_CONTAINER_meta_data_add_publication_date(struct GNUNET_CONTAINER_MetaData *md)
Add the current time as the publication date to the meta-data.
GNUNET_CONTAINER_MetaDataSerializationOptions
Options for metadata serialization.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
size_t GNUNET_CONTAINER_meta_data_get_thumbnail(const struct GNUNET_CONTAINER_MetaData *md, unsigned char **thumb)
Get a thumbnail from the meta-data (if present).
enum EXTRACTOR_MetaType type
Type of the meta data.
struct GNUNET_CONTAINER_MetaData * GNUNET_CONTAINER_meta_data_deserialize(const char *input, size_t size)
Deserialize meta-data.
static int merge_helper(void *cls, const char *plugin_name, enum EXTRACTOR_MetaType type, enum EXTRACTOR_MetaFormat format, const char *data_mime_type, const char *data, size_t data_size)
Merge given meta data.
0-terminated, UTF-8 encoded string.
#define GNUNET_NO
Definition: gnunet_common.h:81
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
char * GNUNET_CONTAINER_meta_data_get_by_type(const struct GNUNET_CONTAINER_MetaData *md, enum EXTRACTOR_MetaType type)
Get the first MD entry of the given type.
EXTRACTOR_MetaType
Enumeration defining various sources of keywords.
static int ret
Final status code.
Definition: gnunet-arm.c:89
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
struct MetaItem * prev
This is a doubly linked list.
char * GNUNET_CONTAINER_meta_data_get_first_by_types(const struct GNUNET_CONTAINER_MetaData *md,...)
Get the first matching MD entry of the given types.
size_t data_size
Number of bytes in &#39;data&#39;.
uint32_t size
Size of the decompressed meta data.
char * plugin_name
Name of the extracting plugin.
Meta data to associate with a file, directory or namespace.
int(* EXTRACTOR_MetaDataProcessor)(void *cls, const char *plugin_name, enum EXTRACTOR_MetaType type, enum EXTRACTOR_MetaFormat format, const char *data_mime_type, const char *data, size_t data_len)
Type of a function that libextractor calls for each meta data item found.
char * mime_type
Mime-type of data.
#define GNUNET_memcpy(dst, src, n)
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-qr.c:59
void GNUNET_CONTAINER_meta_data_merge(struct GNUNET_CONTAINER_MetaData *md, const struct GNUNET_CONTAINER_MetaData *in)
Extend metadata.
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
struct GNUNET_CONTAINER_MetaData * GNUNET_CONTAINER_meta_data_create()
Create a fresh struct CONTAINER_MetaData token.
uint32_t version
The version of the MD serialization.
Speed is of the essence, do not allow compression.
void GNUNET_CONTAINER_meta_data_destroy(struct GNUNET_CONTAINER_MetaData *md)
Free meta data.
static int result
Global testing status.
#define GNUNET_CONTAINER_DLL_insert_after(head, tail, other, element)
Insert an element into a DLL after the given other element.
size_t sbuf_size
Number of bytes in &#39;sbuf&#39;.
uint32_t mime_type_len
Number of bytes in the mime type including 0-terminator.
char * sbuf
Complete serialized and compressed buffer of the items.
#define HEADER_VERSION_MASK
Bits in &#39;version&#39; that give the version number.
int GNUNET_CONTAINER_meta_data_insert(struct GNUNET_CONTAINER_MetaData *md, const char *plugin_name, enum EXTRACTOR_MetaType type, enum EXTRACTOR_MetaFormat format, const char *data_mime_type, const char *data, size_t data_size)
Extend metadata.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:118
int GNUNET_CONTAINER_meta_data_delete(struct GNUNET_CONTAINER_MetaData *md, enum EXTRACTOR_MetaType type, const char *data, size_t data_size)
Remove an item.
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
char * GNUNET_decompress(const char *input, size_t input_size, size_t output_size)
Decompress input, return the decompressed data as output.
static unsigned int size
Size of the "table".
Definition: peer.c:67
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
struct MetaItem * next
This is a doubly linked list.
#define GNUNET_MAX_MALLOC_CHECKED
Maximum allocation with GNUNET_malloc macro.
int GNUNET_CONTAINER_meta_data_test_equal(const struct GNUNET_CONTAINER_MetaData *md1, const struct GNUNET_CONTAINER_MetaData *md2)
Test if two MDs are equal.
Meta data item.
Header for serialized meta data.
uint32_t plugin_name_len
Number of bytes in the plugin name including 0-terminator.
int GNUNET_CONTAINER_meta_data_iterate(const struct GNUNET_CONTAINER_MetaData *md, EXTRACTOR_MetaDataProcessor iter, void *iter_cls)
Iterate over MD entries.
static void meta_item_free(struct MetaItem *mi)
Free meta data item.
unsigned int item_count
Number of items in the linked list.
static void invalidate_sbuf(struct GNUNET_CONTAINER_MetaData *md)
The meta data has changed, invalidate its serialization buffer.
uint32_t format
Meta data format.
Time for absolute times used by GNUnet, in microseconds.
#define GNUNET_YES
Definition: gnunet_common.h:80
uint32_t type
Meta data type.
uint32_t data_size
Number of bytes of meta data.
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
Like asctime, except for GNUnet time.
Definition: strings.c:792
Entry of serialized meta data.
int GNUNET_try_compression(const char *data, size_t old_size, char **result, size_t *new_size)
Try to compress the given block of data using libz.
enum EXTRACTOR_MetaFormat format
Format of the meta data.
uint32_t data
The data value.
struct MetaItem * items_tail
Tail of linked list of the meta data items.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
uint32_t entries
How many MD entries are there?
struct GNUNET_CONTAINER_MetaData * GNUNET_CONTAINER_meta_data_duplicate(const struct GNUNET_CONTAINER_MetaData *md)
Duplicate a struct GNUNET_CONTAINER_MetaData.