GNUnet  0.19.3
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, 2022 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 
29 #include "platform.h"
30 #include "gnunet_util_lib.h"
31 
32 #include "gnunet_fs_service.h"
33 
38 #define MAX_META_DATA (1024 * 1024)
39 
40 
41 #define LOG(kind, ...) GNUNET_log_from (kind, "fs-meta-data", \
42  __VA_ARGS__)
43 
44 
45 
49 struct MetaItem
50 {
54  struct MetaItem *next;
55 
59  struct MetaItem *prev;
60 
64  char *plugin_name;
65 
69  char *mime_type;
70 
74  char *data;
75 
79  size_t data_size;
80 
84  enum EXTRACTOR_MetaType type;
85 
89  enum EXTRACTOR_MetaFormat format;
90 };
91 
96 {
101 
106 
111  char *sbuf;
112 
116  size_t sbuf_size;
117 
121  unsigned int item_count;
122 };
123 
124 
130 struct GNUNET_FS_MetaData *
132 {
133  return GNUNET_new (struct GNUNET_FS_MetaData);
134 }
135 
136 
142 static void
144 {
145  GNUNET_free (mi->plugin_name);
146  GNUNET_free (mi->mime_type);
147  GNUNET_free (mi->data);
148  GNUNET_free (mi);
149 }
150 
151 
158 static void
160 {
161  if (NULL == md->sbuf)
162  return;
163  GNUNET_free (md->sbuf);
164  md->sbuf = NULL;
165  md->sbuf_size = 0;
166 }
167 
168 
169 void
171 {
172  struct MetaItem *pos;
173 
174  if (NULL == md)
175  return;
176  while (NULL != (pos = md->items_head))
177  {
179  meta_item_free (pos);
180  }
181  GNUNET_free (md->sbuf);
182  GNUNET_free (md);
183 }
184 
185 
186 void
188 {
189  struct MetaItem *mi;
190 
191  if (NULL == md)
192  return;
193  while (NULL != (mi = md->items_head))
194  {
196  meta_item_free (mi);
197  }
198  GNUNET_free (md->sbuf);
199  memset (md, 0, sizeof(struct GNUNET_FS_MetaData));
200 }
201 
202 
203 int
205  *md1,
206  const struct GNUNET_FS_MetaData
207  *md2)
208 {
209  struct MetaItem *i;
210  struct MetaItem *j;
211  int found;
212 
213  if (md1 == md2)
214  return GNUNET_YES;
215  if (md1->item_count != md2->item_count)
216  return GNUNET_NO;
217  for (i = md1->items_head; NULL != i; i = i->next)
218  {
219  found = GNUNET_NO;
220  for (j = md2->items_head; NULL != j; j = j->next)
221  {
222  if ((i->type == j->type) && (i->format == j->format) &&
223  (i->data_size == j->data_size) &&
224  (0 == memcmp (i->data, j->data, i->data_size)))
225  {
226  found = GNUNET_YES;
227  break;
228  }
229  if (j->data_size < i->data_size)
230  break; /* elements are sorted by (decreasing) size... */
231  }
232  if (GNUNET_NO == found)
233  return GNUNET_NO;
234  }
235  return GNUNET_YES;
236 }
237 
238 
257 int
259  const char *plugin_name,
260  enum EXTRACTOR_MetaType type,
261  enum EXTRACTOR_MetaFormat format,
262  const char *data_mime_type, const char *data,
263  size_t data_size)
264 {
265  struct MetaItem *pos;
266  struct MetaItem *mi;
267  char *p;
268 
269  if ((EXTRACTOR_METAFORMAT_UTF8 == format) ||
270  (EXTRACTOR_METAFORMAT_C_STRING == format))
271  GNUNET_break ('\0' == data[data_size - 1]);
272 
273  for (pos = md->items_head; NULL != pos; pos = pos->next)
274  {
275  if (pos->data_size < data_size)
276  break; /* elements are sorted by size in the list */
277  if ((pos->type == type) && (pos->data_size == data_size) &&
278  (0 == memcmp (pos->data, data, data_size)))
279  {
280  if ((NULL == pos->mime_type) && (NULL != data_mime_type))
281  {
282  pos->mime_type = GNUNET_strdup (data_mime_type);
283  invalidate_sbuf (md);
284  }
285  if ((EXTRACTOR_METAFORMAT_C_STRING == pos->format) &&
286  (EXTRACTOR_METAFORMAT_UTF8 == format))
287  {
288  pos->format = EXTRACTOR_METAFORMAT_UTF8;
289  invalidate_sbuf (md);
290  }
291  return GNUNET_SYSERR;
292  }
293  }
294  md->item_count++;
295  mi = GNUNET_new (struct MetaItem);
296  mi->type = type;
297  mi->format = format;
298  mi->data_size = data_size;
299  if (NULL == pos)
301  md->items_tail,
302  mi);
303  else
305  md->items_tail,
306  pos->prev,
307  mi);
308  mi->mime_type =
309  (NULL == data_mime_type) ? NULL : GNUNET_strdup (data_mime_type);
310  mi->plugin_name = (NULL == plugin_name) ? NULL : GNUNET_strdup (plugin_name);
311  mi->data = GNUNET_malloc (data_size);
313  /* change all dir separators to POSIX style ('/') */
314  if ((EXTRACTOR_METATYPE_FILENAME == type) ||
316  {
317  p = mi->data;
318  while (('\0' != *p) && (p < mi->data + data_size))
319  {
320  if ('\\' == *p)
321  *p = '/';
322  p++;
323  }
324  }
325  invalidate_sbuf (md);
326  return GNUNET_OK;
327 }
328 
329 
346 static int
347 merge_helper (void *cls, const char *plugin_name, enum EXTRACTOR_MetaType type,
348  enum EXTRACTOR_MetaFormat format, const char *data_mime_type,
349  const char *data, size_t data_size)
350 {
351  struct GNUNET_FS_MetaData *md = cls;
352 
353  (void) GNUNET_FS_meta_data_insert (md, plugin_name, type, format,
354  data_mime_type, data, data_size);
355  return 0;
356 }
357 
358 
359 void
361  const struct GNUNET_FS_MetaData *in)
362 {
364 }
365 
366 
367 int
369  enum EXTRACTOR_MetaType type,
370  const char *data, size_t data_size)
371 {
372  struct MetaItem *pos;
373 
374  for (pos = md->items_head; NULL != pos; pos = pos->next)
375  {
376  if (pos->data_size < data_size)
377  break; /* items are sorted by (decreasing) size */
378  if ((pos->type == type) &&
379  ((NULL == data) ||
380  ((pos->data_size == data_size) &&
381  (0 == memcmp (pos->data, data, data_size)))))
382  {
384  meta_item_free (pos);
385  md->item_count--;
386  invalidate_sbuf (md);
387  return GNUNET_OK;
388  }
389  }
390  return GNUNET_SYSERR;
391 }
392 
393 
394 void
396  GNUNET_FS_MetaData *md)
397 {
398  const char *dat;
399  struct GNUNET_TIME_Absolute t;
400 
403  EXTRACTOR_METATYPE_PUBLICATION_DATE,
404  NULL, 0);
406  GNUNET_FS_meta_data_insert (md, "<gnunet>",
407  EXTRACTOR_METATYPE_PUBLICATION_DATE,
408  EXTRACTOR_METAFORMAT_UTF8, "text/plain",
409  dat, strlen (dat) + 1);
410 }
411 
412 
421 int
423  EXTRACTOR_MetaDataProcessor iter,
424  void *iter_cls)
425 {
426  struct MetaItem *pos;
427 
428  if (NULL == md)
429  return 0;
430  if (NULL == iter)
431  return md->item_count;
432  for (pos = md->items_head; NULL != pos; pos = pos->next)
433  if (0 !=
434  iter (iter_cls, pos->plugin_name, pos->type, pos->format,
435  pos->mime_type, pos->data, pos->data_size))
436  return md->item_count;
437  return md->item_count;
438 }
439 
440 
441 char *
443  GNUNET_FS_MetaData *md,
444  enum EXTRACTOR_MetaType type)
445 {
446  struct MetaItem *pos;
447 
448  if (NULL == md)
449  return NULL;
450  for (pos = md->items_head; NULL != pos; pos = pos->next)
451  if ((type == pos->type) &&
452  ((pos->format == EXTRACTOR_METAFORMAT_UTF8) ||
453  (pos->format == EXTRACTOR_METAFORMAT_C_STRING)))
454  return GNUNET_strdup (pos->data);
455  return NULL;
456 }
457 
458 
459 char *
461  GNUNET_FS_MetaData *md,
462  ...)
463 {
464  char *ret;
465  va_list args;
466  int type;
467 
468  if (NULL == md)
469  return NULL;
470  ret = NULL;
471  va_start (args, md);
472  while (1)
473  {
474  type = va_arg (args, int);
475  if (-1 == type)
476  break;
477  if (NULL != (ret = GNUNET_FS_meta_data_get_by_type (md, type)))
478  break;
479  }
480  va_end (args);
481  return ret;
482 }
483 
484 
493 size_t
495  *md, unsigned char **thumb)
496 {
497  struct MetaItem *pos;
498  struct MetaItem *match;
499 
500  if (NULL == md)
501  return 0;
502  match = NULL;
503  for (pos = md->items_head; NULL != pos; pos = pos->next)
504  {
505  if ((NULL != pos->mime_type) &&
506  (0 == strncasecmp ("image/", pos->mime_type, strlen ("image/"))) &&
507  (EXTRACTOR_METAFORMAT_BINARY == pos->format))
508  {
509  if (NULL == match)
510  match = pos;
511  else if ((match->type != EXTRACTOR_METATYPE_THUMBNAIL) &&
512  (pos->type == EXTRACTOR_METATYPE_THUMBNAIL))
513  match = pos;
514  }
515  }
516  if ((NULL == match) || (0 == match->data_size))
517  return 0;
518  *thumb = GNUNET_malloc (match->data_size);
519  GNUNET_memcpy (*thumb, match->data, match->data_size);
520  return match->data_size;
521 }
522 
523 
530 struct GNUNET_FS_MetaData *
532  *md)
533 {
534  struct GNUNET_FS_MetaData *ret;
535  struct MetaItem *pos;
536 
537  if (NULL == md)
538  return NULL;
540  for (pos = md->items_tail; NULL != pos; pos = pos->prev)
542  pos->format, pos->mime_type, pos->data,
543  pos->data_size);
544  return ret;
545 }
546 
547 
551 #define HEADER_COMPRESSED 0x80000000
552 
553 
557 #define HEADER_VERSION_MASK 0x7FFFFFFF
558 
559 
564 {
574  uint32_t version;
575 
579  uint32_t entries;
580 
584  uint32_t size;
585 
591 };
592 
593 
598 {
602  uint32_t type;
603 
607  uint32_t format;
608 
612  uint32_t data_size;
613 
617  uint32_t plugin_name_len;
618 
622  uint32_t mime_type_len;
623 };
624 
625 
640 ssize_t
642  *md, char **target, size_t max,
643  enum
645  opt)
646 {
647  struct GNUNET_FS_MetaData *vmd;
648  struct MetaItem *pos;
649  struct MetaDataHeader ihdr;
650  struct MetaDataHeader *hdr;
651  struct MetaDataEntry *ent;
652  char *dst;
653  unsigned int i;
654  uint64_t msize;
655  size_t off;
656  char *mdata;
657  char *cdata;
658  size_t mlen;
659  size_t plen;
660  size_t size;
661  size_t left;
662  size_t clen;
663  size_t rlen;
664  int comp;
665 
666  if (max < sizeof(struct MetaDataHeader))
667  return GNUNET_SYSERR; /* far too small */
668  if (NULL == md)
669  return 0;
670 
671  if (NULL != md->sbuf)
672  {
673  /* try to use serialization cache */
674  if (md->sbuf_size <= max)
675  {
676  if (NULL == *target)
677  *target = GNUNET_malloc (md->sbuf_size);
678  GNUNET_memcpy (*target, md->sbuf, md->sbuf_size);
679  return md->sbuf_size;
680  }
681  if (0 == (opt & GNUNET_FS_META_DATA_SERIALIZE_PART))
682  return GNUNET_SYSERR; /* can say that this will fail */
683  /* need to compute a partial serialization, sbuf useless ... */
684  }
685  dst = NULL;
686  msize = 0;
687  for (pos = md->items_tail; NULL != pos; pos = pos->prev)
688  {
689  msize += sizeof(struct MetaDataEntry);
690  msize += pos->data_size;
691  if (NULL != pos->plugin_name)
692  msize += strlen (pos->plugin_name) + 1;
693  if (NULL != pos->mime_type)
694  msize += strlen (pos->mime_type) + 1;
695  }
696  size = (size_t) msize;
697  if (size != msize)
698  {
699  GNUNET_break (0); /* integer overflow */
700  return GNUNET_SYSERR;
701  }
703  {
704  /* too large to be processed */
705  return GNUNET_SYSERR;
706  }
707  ent = GNUNET_malloc (size);
708  mdata = (char *) &ent[md->item_count];
709  off = size - (md->item_count * sizeof(struct MetaDataEntry));
710  i = 0;
711  for (pos = md->items_head; NULL != pos; pos = pos->next)
712  {
713  ent[i].type = htonl ((uint32_t) pos->type);
714  ent[i].format = htonl ((uint32_t) pos->format);
715  ent[i].data_size = htonl ((uint32_t) pos->data_size);
716  if (NULL == pos->plugin_name)
717  plen = 0;
718  else
719  plen = strlen (pos->plugin_name) + 1;
720  ent[i].plugin_name_len = htonl ((uint32_t) plen);
721  if (NULL == pos->mime_type)
722  mlen = 0;
723  else
724  mlen = strlen (pos->mime_type) + 1;
725  ent[i].mime_type_len = htonl ((uint32_t) mlen);
726  off -= pos->data_size;
727  if ((EXTRACTOR_METAFORMAT_UTF8 == pos->format) ||
728  (EXTRACTOR_METAFORMAT_C_STRING == pos->format))
729  GNUNET_break ('\0' == pos->data[pos->data_size - 1]);
730  GNUNET_memcpy (&mdata[off], pos->data, pos->data_size);
731  off -= plen;
732  if (NULL != pos->plugin_name)
733  GNUNET_memcpy (&mdata[off], pos->plugin_name, plen);
734  off -= mlen;
735  if (NULL != pos->mime_type)
736  GNUNET_memcpy (&mdata[off], pos->mime_type, mlen);
737  i++;
738  }
739  GNUNET_assert (0 == off);
740 
741  clen = 0;
742  cdata = NULL;
743  left = size;
744  i = 0;
745  for (pos = md->items_head; NULL != pos; pos = pos->next)
746  {
747  comp = GNUNET_NO;
749  comp = GNUNET_try_compression ((const char *) &ent[i],
750  left,
751  &cdata,
752  &clen);
753 
754  if ((NULL == md->sbuf) && (0 == i))
755  {
756  /* fill 'sbuf'; this "modifies" md, but since this is only
757  * an internal cache we will cast away the 'const' instead
758  * of making the API look strange. */
759  vmd = (struct GNUNET_FS_MetaData *) md;
760  hdr = GNUNET_malloc (left + sizeof(struct MetaDataHeader));
761  hdr->size = htonl (left);
762  hdr->entries = htonl (md->item_count);
763  if (GNUNET_YES == comp)
764  {
765  GNUNET_assert (clen < left);
766  hdr->version = htonl (2 | HEADER_COMPRESSED);
767  GNUNET_memcpy (&hdr[1], cdata, clen);
768  vmd->sbuf_size = clen + sizeof(struct MetaDataHeader);
769  }
770  else
771  {
772  hdr->version = htonl (2);
773  GNUNET_memcpy (&hdr[1], &ent[0], left);
774  vmd->sbuf_size = left + sizeof(struct MetaDataHeader);
775  }
776  vmd->sbuf = (char *) hdr;
777  }
778 
779  if (((left + sizeof(struct MetaDataHeader)) <= max) ||
780  ((GNUNET_YES == comp) && (clen <= max)))
781  {
782  /* success, this now fits! */
783  if (GNUNET_YES == comp)
784  {
785  if (NULL == dst)
786  dst = GNUNET_malloc (clen + sizeof(struct MetaDataHeader));
787  hdr = (struct MetaDataHeader *) dst;
788  hdr->version = htonl (2 | HEADER_COMPRESSED);
789  hdr->size = htonl (left);
790  hdr->entries = htonl (md->item_count - i);
791  GNUNET_memcpy (&dst[sizeof(struct MetaDataHeader)], cdata, clen);
792  GNUNET_free (cdata);
793  cdata = NULL;
794  GNUNET_free (ent);
795  rlen = clen + sizeof(struct MetaDataHeader);
796  }
797  else
798  {
799  if (NULL == dst)
800  dst = GNUNET_malloc (left + sizeof(struct MetaDataHeader));
801  hdr = (struct MetaDataHeader *) dst;
802  hdr->version = htonl (2);
803  hdr->entries = htonl (md->item_count - i);
804  hdr->size = htonl (left);
805  GNUNET_memcpy (&dst[sizeof(struct MetaDataHeader)], &ent[i], left);
806  GNUNET_free (ent);
807  rlen = left + sizeof(struct MetaDataHeader);
808  }
809  if (NULL != *target)
810  {
811  if (GNUNET_YES == comp)
812  GNUNET_memcpy (*target, dst, clen + sizeof(struct MetaDataHeader));
813  else
814  GNUNET_memcpy (*target, dst, left + sizeof(struct MetaDataHeader));
815  GNUNET_free (dst);
816  }
817  else
818  {
819  *target = dst;
820  }
821  return rlen;
822  }
823 
824  if (0 == (opt & GNUNET_FS_META_DATA_SERIALIZE_PART))
825  {
826  /* does not fit! */
827  GNUNET_free (ent);
828  if (NULL != cdata)
829  GNUNET_free (cdata);
830  cdata = NULL;
831  return GNUNET_SYSERR;
832  }
833 
834  /* next iteration: ignore the corresponding meta data at the
835  * end and try again without it */
836  left -= sizeof(struct MetaDataEntry);
837  left -= pos->data_size;
838  if (NULL != pos->plugin_name)
839  left -= strlen (pos->plugin_name) + 1;
840  if (NULL != pos->mime_type)
841  left -= strlen (pos->mime_type) + 1;
842 
843  if (NULL != cdata)
844  GNUNET_free (cdata);
845  cdata = NULL;
846  i++;
847  }
848  GNUNET_free (ent);
849 
850  /* nothing fit, only write header! */
851  ihdr.version = htonl (2);
852  ihdr.entries = htonl (0);
853  ihdr.size = htonl (0);
854  if (NULL == *target)
855  *target = (char *) GNUNET_new (struct MetaDataHeader);
856  GNUNET_memcpy (*target, &ihdr, sizeof(struct MetaDataHeader));
857  return sizeof(struct MetaDataHeader);
858 }
859 
860 
861 ssize_t
863  GNUNET_FS_MetaData *md)
864 {
865  ssize_t ret;
866  char *ptr;
867 
868  if (NULL != md->sbuf)
869  return md->sbuf_size;
870  ptr = NULL;
871  ret =
874  if (-1 != ret)
875  GNUNET_free (ptr);
876  return ret;
877 }
878 
879 
888 struct GNUNET_FS_MetaData *
889 GNUNET_FS_meta_data_deserialize (const char *input, size_t size)
890 {
891  struct GNUNET_FS_MetaData *md;
892  struct MetaDataHeader hdr;
893  struct MetaDataEntry ent;
894  uint32_t ic;
895  uint32_t i;
896  char *data;
897  const char *cdata;
898  uint32_t version;
899  uint32_t dataSize;
900  int compressed;
901  size_t left;
902  uint32_t mlen;
903  uint32_t plen;
904  uint32_t dlen;
905  const char *mdata;
906  const char *meta_data;
907  const char *plugin_name;
908  const char *mime_type;
909  enum EXTRACTOR_MetaFormat format;
910 
911  if (size < sizeof(struct MetaDataHeader))
912  return NULL;
913  GNUNET_memcpy (&hdr, input, sizeof(struct MetaDataHeader));
914  version = ntohl (hdr.version) & HEADER_VERSION_MASK;
915  compressed = (ntohl (hdr.version) & HEADER_COMPRESSED) != 0;
916 
917  if (1 == version)
918  return NULL; /* null pointer */
919  if (2 != version)
920  {
921  GNUNET_break_op (0); /* unsupported version */
922  return NULL;
923  }
924 
925  ic = ntohl (hdr.entries);
926  dataSize = ntohl (hdr.size);
927  if (((sizeof(struct MetaDataEntry) * ic) > dataSize) ||
928  ((0 != ic) &&
929  (dataSize / ic < sizeof(struct MetaDataEntry))))
930  {
931  GNUNET_break_op (0);
932  return NULL;
933  }
934 
935  if (compressed)
936  {
937  if (dataSize >= GNUNET_MAX_MALLOC_CHECKED)
938  {
939  /* make sure we don't blow our memory limit because of a mal-formed
940  * message... */
941  GNUNET_break_op (0);
942  return NULL;
943  }
944  data =
945  GNUNET_decompress ((const char *) &input[sizeof(struct MetaDataHeader)],
946  size - sizeof(struct MetaDataHeader),
947  dataSize);
948  if (NULL == data)
949  {
950  GNUNET_break_op (0);
951  return NULL;
952  }
953  cdata = data;
954  }
955  else
956  {
957  data = NULL;
958  cdata = (const char *) &input[sizeof(struct MetaDataHeader)];
959  if (dataSize != size - sizeof(struct MetaDataHeader))
960  {
961  GNUNET_break_op (0);
962  return NULL;
963  }
964  }
965 
967  left = dataSize - ic * sizeof(struct MetaDataEntry);
968  mdata = &cdata[ic * sizeof(struct MetaDataEntry)];
969  for (i = 0; i < ic; i++)
970  {
971  GNUNET_memcpy (&ent, &cdata[i * sizeof(struct MetaDataEntry)],
972  sizeof(struct MetaDataEntry));
973  format = (enum EXTRACTOR_MetaFormat) ntohl (ent.format);
974  if ((EXTRACTOR_METAFORMAT_UTF8 != format) &&
975  (EXTRACTOR_METAFORMAT_C_STRING != format) &&
976  (EXTRACTOR_METAFORMAT_BINARY != format))
977  {
978  GNUNET_break_op (0);
979  break;
980  }
981  dlen = ntohl (ent.data_size);
982  plen = ntohl (ent.plugin_name_len);
983  mlen = ntohl (ent.mime_type_len);
984  if (dlen > left)
985  {
986  GNUNET_break_op (0);
987  break;
988  }
989  left -= dlen;
990  meta_data = &mdata[left];
991  if ((EXTRACTOR_METAFORMAT_UTF8 == format) ||
992  (EXTRACTOR_METAFORMAT_C_STRING == format))
993  {
994  if (0 == dlen)
995  {
996  GNUNET_break_op (0);
997  break;
998  }
999  if ('\0' != meta_data[dlen - 1])
1000  {
1001  GNUNET_break_op (0);
1002  break;
1003  }
1004  }
1005  if (plen > left)
1006  {
1007  GNUNET_break_op (0);
1008  break;
1009  }
1010  left -= plen;
1011  if ((plen > 0) && ('\0' != mdata[left + plen - 1]))
1012  {
1013  GNUNET_break_op (0);
1014  break;
1015  }
1016  if (0 == plen)
1017  plugin_name = NULL;
1018  else
1019  plugin_name = &mdata[left];
1020 
1021  if (mlen > left)
1022  {
1023  GNUNET_break_op (0);
1024  break;
1025  }
1026  left -= mlen;
1027  if ((mlen > 0) && ('\0' != mdata[left + mlen - 1]))
1028  {
1029  GNUNET_break_op (0);
1030  break;
1031  }
1032  if (0 == mlen)
1033  mime_type = NULL;
1034  else
1035  mime_type = &mdata[left];
1037  (enum EXTRACTOR_MetaType)
1038  ntohl (ent.type), format, mime_type,
1039  meta_data, dlen);
1040  }
1041  GNUNET_free (data);
1042  return md;
1043 }
1044 
1053 int
1055  const char *what,
1056  struct GNUNET_FS_MetaData **result)
1057 {
1058  uint32_t size;
1059  char *buf;
1060  char *emsg;
1061  struct GNUNET_FS_MetaData *meta;
1062 
1064  _ ("metadata length"),
1065  (int32_t *) &size))
1066  return GNUNET_SYSERR;
1067  if (0 == size)
1068  {
1069  *result = NULL;
1070  return GNUNET_OK;
1071  }
1072  if (MAX_META_DATA < size)
1073  {
1074  GNUNET_asprintf (&emsg,
1075  _ (
1076  "Serialized metadata `%s' larger than allowed (%u > %u)\n"),
1077  what,
1078  size,
1079  MAX_META_DATA);
1080  GNUNET_BIO_read_set_error (h, emsg);
1081  GNUNET_free (emsg);
1082  return GNUNET_SYSERR;
1083  }
1084  buf = GNUNET_malloc (size);
1085  if (GNUNET_OK != GNUNET_BIO_read (h, what, buf, size))
1086  {
1087  GNUNET_free (buf);
1088  return GNUNET_SYSERR;
1089  }
1091  if (NULL == meta)
1092  {
1093  GNUNET_free (buf);
1095  _ ("Failed to deserialize metadata `%s'"), what);
1096  return GNUNET_SYSERR;
1097  }
1098  GNUNET_free (buf);
1099  *result = meta;
1100  return GNUNET_OK;
1101 }
1102 
1113  const char *what,
1114  const struct GNUNET_FS_MetaData *m)
1115 {
1116  ssize_t size;
1117  char *buf;
1118 
1119  if (m == NULL)
1120  return GNUNET_BIO_write_int32 (h, _ ("metadata length"), 0);
1121  buf = NULL;
1123  &buf,
1124  MAX_META_DATA,
1127  _ ("Serialized %ld bytes of metadata"),
1128  size);
1129 
1130  if (-1 == size)
1131  {
1132  GNUNET_free (buf);
1134  _ ("Failed to serialize metadata `%s'"),
1135  what);
1136  return GNUNET_SYSERR;
1137  }
1139  _ ("metadata length"),
1140  (uint32_t) size))
1141  || (GNUNET_OK != GNUNET_BIO_write (h, what, buf, size)))
1142  {
1143  GNUNET_free (buf);
1144  return GNUNET_SYSERR;
1145  }
1146  GNUNET_free (buf);
1147  return GNUNET_OK;
1148 }
1149 
1161 static int
1163  struct GNUNET_BIO_ReadHandle *h,
1164  const char *what,
1165  void *target,
1166  size_t target_size)
1167 {
1168  struct GNUNET_FS_MetaData **result = target;
1169  return GNUNET_FS_read_meta_data (h, what, result);
1170 }
1171 
1179 struct GNUNET_BIO_ReadSpec
1180 GNUNET_FS_read_spec_meta_data (const char *what,
1181  struct GNUNET_FS_MetaData **result)
1182 {
1183  struct GNUNET_BIO_ReadSpec rs = {
1185  .cls = NULL,
1186  .target = result,
1187  .size = 0,
1188  };
1189 
1190  return rs;
1191 }
1192 
1204 static int
1206  struct GNUNET_BIO_WriteHandle *h,
1207  const char *what,
1208  void *source,
1209  size_t source_size)
1210 {
1211  const struct GNUNET_FS_MetaData *m = source;
1212  return GNUNET_FS_write_meta_data (h, what, m);
1213 }
1214 
1215 
1216 struct GNUNET_BIO_WriteSpec
1218  const struct GNUNET_FS_MetaData *m)
1219 {
1220  struct GNUNET_BIO_WriteSpec ws = {
1222  .cls = NULL,
1223  .what = what,
1224  .source = (void *) m,
1225  .source_size = 0,
1226  };
1227 
1228  return ws;
1229 }
1230 
1231 
1232 /* end of meta_data.c */
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
static size_t data_size
Number of bytes in data.
Definition: gnunet-abd.c:187
static struct GNUNET_ARM_MonitorHandle * m
Monitor connection with ARM.
Definition: gnunet-arm.c:104
static struct GNUNET_ARM_Handle * h
Connection with ARM.
Definition: gnunet-arm.c:99
static GstElement * source
Appsrc instance into which we write data for the pipeline.
uint32_t data
The data value.
static struct GNUNET_FS_MetaData * meta
Meta-data provided via command-line option.
static int result
Global testing status.
static char * plugin_name
Name of our plugin.
static char buf[2048]
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-uri.c:38
static struct GNUNET_SCHEDULER_Task * t
Main task.
API for file sharing via GNUnet.
int GNUNET_BIO_read_int32(struct GNUNET_BIO_ReadHandle *h, const char *what, int32_t *i)
Read an (u)int32_t.
Definition: bio.c:427
int GNUNET_BIO_write(struct GNUNET_BIO_WriteHandle *h, const char *what, const void *buffer, size_t n)
Write a buffer to a handle.
Definition: bio.c:752
int GNUNET_BIO_write_int32(struct GNUNET_BIO_WriteHandle *h, const char *what, int32_t i)
Write an (u)int32_t.
Definition: bio.c:847
void GNUNET_BIO_read_set_error(struct GNUNET_BIO_ReadHandle *h, const char *emsg)
Set read error to handle.
Definition: bio.c:187
int GNUNET_BIO_read(struct GNUNET_BIO_ReadHandle *h, const char *what, void *result, size_t len)
Read some contents into a buffer.
Definition: bio.c:291
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_DLL_insert_after(head, tail, other, element)
Insert an element into a DLL after the given other element.
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
#define EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME
enum GNUNET_GenericReturnValue GNUNET_FS_write_meta_data(struct GNUNET_BIO_WriteHandle *h, const char *what, const struct GNUNET_FS_MetaData *m)
Write a metadata container.
Definition: meta_data.c:1112
int GNUNET_FS_read_meta_data(struct GNUNET_BIO_ReadHandle *h, const char *what, struct GNUNET_FS_MetaData **result)
Read a metadata container.
Definition: meta_data.c:1054
struct GNUNET_BIO_ReadSpec GNUNET_FS_read_spec_meta_data(const char *what, struct GNUNET_FS_MetaData **result)
Create the specification to read a metadata container.
Definition: meta_data.c:1180
struct GNUNET_BIO_WriteSpec GNUNET_FS_write_spec_meta_data(const char *what, const struct GNUNET_FS_MetaData *m)
Create the specification to write a metadata container.
Definition: meta_data.c:1217
char * GNUNET_decompress(const char *input, size_t input_size, size_t output_size)
Decompress input, return the decompressed data as output.
Definition: compress.c:70
#define GNUNET_log(kind,...)
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.
Definition: compress.c:33
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
GNUNET_GenericReturnValue
Named constants for return values.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
@ GNUNET_ERROR_TYPE_ERROR
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_MAX_MALLOC_CHECKED
Maximum allocation with GNUNET_malloc macro.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
int GNUNET_FS_meta_data_iterate(const struct GNUNET_FS_MetaData *md, EXTRACTOR_MetaDataProcessor iter, void *iter_cls)
Iterate over MD entries.
Definition: meta_data.c:422
void GNUNET_FS_meta_data_add_publication_date(struct GNUNET_FS_MetaData *md)
Add the current time as the publication date to the meta-data.
Definition: meta_data.c:395
ssize_t GNUNET_FS_meta_data_get_serialized_size(const struct GNUNET_FS_MetaData *md)
Get the size of the full meta-data in serialized form.
Definition: meta_data.c:862
size_t GNUNET_FS_meta_data_get_thumbnail(const struct GNUNET_FS_MetaData *md, unsigned char **thumb)
Get a thumbnail from the meta-data (if present).
Definition: meta_data.c:494
GNUNET_FS_MetaDataSerializationOptions
Options for metadata serialization.
ssize_t GNUNET_FS_meta_data_serialize(const struct GNUNET_FS_MetaData *md, char **target, size_t max, enum GNUNET_FS_MetaDataSerializationOptions opt)
Serialize meta-data to target.
Definition: meta_data.c:641
void GNUNET_FS_meta_data_merge(struct GNUNET_FS_MetaData *md, const struct GNUNET_FS_MetaData *in)
Extend metadata.
Definition: meta_data.c:360
struct GNUNET_FS_MetaData * GNUNET_FS_meta_data_create()
Create a fresh struct FS_MetaData token.
Definition: meta_data.c:131
char * GNUNET_FS_meta_data_get_by_type(const struct GNUNET_FS_MetaData *md, enum EXTRACTOR_MetaType type)
Get the first MD entry of the given type.
Definition: meta_data.c:442
struct GNUNET_FS_MetaData * GNUNET_FS_meta_data_duplicate(const struct GNUNET_FS_MetaData *md)
Duplicate a struct GNUNET_FS_MetaData.
Definition: meta_data.c:531
int GNUNET_FS_meta_data_insert(struct GNUNET_FS_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.
Definition: meta_data.c:258
void GNUNET_FS_meta_data_destroy(struct GNUNET_FS_MetaData *md)
Free meta data.
Definition: meta_data.c:170
int GNUNET_FS_meta_data_test_equal(const struct GNUNET_FS_MetaData *md1, const struct GNUNET_FS_MetaData *md2)
Test if two MDs are equal.
Definition: meta_data.c:204
void GNUNET_FS_meta_data_clear(struct GNUNET_FS_MetaData *md)
Remove all items in the container.
Definition: meta_data.c:187
int GNUNET_FS_meta_data_delete(struct GNUNET_FS_MetaData *md, enum EXTRACTOR_MetaType type, const char *data, size_t data_size)
Remove an item.
Definition: meta_data.c:368
struct GNUNET_FS_MetaData * GNUNET_FS_meta_data_deserialize(const char *input, size_t size)
Deserialize meta-data.
Definition: meta_data.c:889
char * GNUNET_FS_meta_data_get_first_by_types(const struct GNUNET_FS_MetaData *md,...)
Get the first matching MD entry of the given types.
Definition: meta_data.c:460
@ GNUNET_FS_META_DATA_SERIALIZE_FULL
Serialize all of the data.
@ GNUNET_FS_META_DATA_SERIALIZE_PART
If not enough space is available, it is acceptable to only serialize some of the metadata.
@ GNUNET_FS_META_DATA_SERIALIZE_NO_COMPRESS
Speed is of the essence, do not allow compression.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:111
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
Like asctime, except for GNUnet time.
Definition: strings.c:616
#define max(x, y)
static void meta_item_free(struct MetaItem *mi)
Free meta data item.
Definition: meta_data.c:143
static int write_spec_handler_meta_data(void *cls, struct GNUNET_BIO_WriteHandle *h, const char *what, void *source, size_t source_size)
Function used internally to write a metadata container from within a write spec.
Definition: meta_data.c:1205
#define HEADER_VERSION_MASK
Bits in 'version' that give the version number.
Definition: meta_data.c:557
static int read_spec_handler_meta_data(void *cls, struct GNUNET_BIO_ReadHandle *h, const char *what, void *target, size_t target_size)
Function used internally to read a metadata container from within a read spec.
Definition: meta_data.c:1162
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.
Definition: meta_data.c:347
#define MAX_META_DATA
Maximum size allowed for meta data written/read from disk.
Definition: meta_data.c:38
static void invalidate_sbuf(struct GNUNET_FS_MetaData *md)
The meta data has changed, invalidate its serialization buffer.
Definition: meta_data.c:159
#define HEADER_COMPRESSED
Flag in 'version' that indicates compressed meta-data.
Definition: meta_data.c:551
static unsigned int size
Size of the "table".
Definition: peer.c:68
#define _(String)
GNU gettext support macro.
Definition: platform.h:177
Handle for buffered reading.
Definition: bio.c:69
Structure specifying a reading operation on an IO handle.
void * cls
Closure for rh.
const char * what
What is being read (for error message creation)
GNUNET_BIO_ReadHandler rh
Function performing data deserialization.
Handle for buffered writing.
Definition: bio.c:466
Structure specifying a writing operation on an IO handle.
GNUNET_BIO_WriteHandler wh
Function performing data serialization.
size_t source_size
Size of source.
const char * what
What is being read (for error message creation)
Meta data to associate with a file, directory or namespace.
Definition: meta_data.c:96
size_t sbuf_size
Number of bytes in 'sbuf'.
Definition: meta_data.c:116
struct MetaItem * items_head
Head of linked list of the meta data items.
Definition: meta_data.c:100
unsigned int item_count
Number of items in the linked list.
Definition: meta_data.c:121
struct MetaItem * items_tail
Tail of linked list of the meta data items.
Definition: meta_data.c:105
char * sbuf
Complete serialized and compressed buffer of the items.
Definition: meta_data.c:111
Time for absolute times used by GNUnet, in microseconds.
Entry of serialized meta data.
Definition: meta_data.c:598
uint32_t plugin_name_len
Number of bytes in the plugin name including 0-terminator.
Definition: meta_data.c:617
uint32_t mime_type_len
Number of bytes in the mime type including 0-terminator.
Definition: meta_data.c:622
uint32_t type
Meta data type.
Definition: meta_data.c:602
uint32_t data_size
Number of bytes of meta data.
Definition: meta_data.c:612
uint32_t format
Meta data format.
Definition: meta_data.c:607
Header for serialized meta data.
Definition: meta_data.c:564
uint32_t entries
How many MD entries are there?
Definition: meta_data.c:579
uint32_t size
Size of the decompressed meta data.
Definition: meta_data.c:584
uint32_t version
The version of the MD serialization.
Definition: meta_data.c:574
Meta data item.
Definition: meta_data.c:50
struct MetaItem * prev
This is a doubly linked list.
Definition: meta_data.c:59
struct MetaItem * next
This is a doubly linked list.
Definition: meta_data.c:54
enum EXTRACTOR_MetaType type
Type of the meta data.
Definition: meta_data.c:84
size_t data_size
Number of bytes in 'data'.
Definition: meta_data.c:79
char * mime_type
Mime-type of data.
Definition: meta_data.c:69
enum EXTRACTOR_MetaFormat format
Format of the meta data.
Definition: meta_data.c:89
char * data
The actual meta data.
Definition: meta_data.c:74
char * plugin_name
Name of the extracting plugin.
Definition: meta_data.c:64
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model