GNUnet  0.20.0
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 "gnunet_common.h"
30 #include "platform.h"
31 #include "gnunet_util_lib.h"
32 
33 #include "gnunet_fs_service.h"
34 
39 #define MAX_META_DATA (1024 * 1024)
40 
41 
42 #define LOG(kind, ...) GNUNET_log_from (kind, "fs-meta-data", \
43  __VA_ARGS__)
44 
45 
46 
50 struct MetaItem
51 {
55  struct MetaItem *next;
56 
60  struct MetaItem *prev;
61 
65  char *plugin_name;
66 
70  char *mime_type;
71 
75  char *data;
76 
80  size_t data_size;
81 
85  enum EXTRACTOR_MetaType type;
86 
90  enum EXTRACTOR_MetaFormat format;
91 };
92 
97 {
102 
107 
112  char *sbuf;
113 
117  size_t sbuf_size;
118 
122  unsigned int item_count;
123 };
124 
125 
131 struct GNUNET_FS_MetaData *
133 {
134  return GNUNET_new (struct GNUNET_FS_MetaData);
135 }
136 
137 
143 static void
145 {
146  GNUNET_free (mi->plugin_name);
147  GNUNET_free (mi->mime_type);
148  GNUNET_free (mi->data);
149  GNUNET_free (mi);
150 }
151 
152 
159 static void
161 {
162  if (NULL == md->sbuf)
163  return;
164  GNUNET_free (md->sbuf);
165  md->sbuf = NULL;
166  md->sbuf_size = 0;
167 }
168 
169 
170 void
172 {
173  struct MetaItem *pos;
174 
175  if (NULL == md)
176  return;
177  while (NULL != (pos = md->items_head))
178  {
180  meta_item_free (pos);
181  }
182  GNUNET_free (md->sbuf);
183  GNUNET_free (md);
184 }
185 
186 
187 void
189 {
190  struct MetaItem *mi;
191 
192  if (NULL == md)
193  return;
194  while (NULL != (mi = md->items_head))
195  {
197  meta_item_free (mi);
198  }
199  GNUNET_free (md->sbuf);
200  memset (md, 0, sizeof(struct GNUNET_FS_MetaData));
201 }
202 
203 
204 int
206  *md1,
207  const struct GNUNET_FS_MetaData
208  *md2)
209 {
210  struct MetaItem *i;
211  struct MetaItem *j;
212  int found;
213 
214  if (md1 == md2)
215  return GNUNET_YES;
216  if (md1->item_count != md2->item_count)
217  return GNUNET_NO;
218  for (i = md1->items_head; NULL != i; i = i->next)
219  {
220  found = GNUNET_NO;
221  for (j = md2->items_head; NULL != j; j = j->next)
222  {
223  if ((i->type == j->type) && (i->format == j->format) &&
224  (i->data_size == j->data_size) &&
225  (0 == memcmp (i->data, j->data, i->data_size)))
226  {
227  found = GNUNET_YES;
228  break;
229  }
230  if (j->data_size < i->data_size)
231  break; /* elements are sorted by (decreasing) size... */
232  }
233  if (GNUNET_NO == found)
234  return GNUNET_NO;
235  }
236  return GNUNET_YES;
237 }
238 
239 
258 int
260  const char *plugin_name,
261  enum EXTRACTOR_MetaType type,
262  enum EXTRACTOR_MetaFormat format,
263  const char *data_mime_type, const char *data,
264  size_t data_size)
265 {
266  struct MetaItem *pos;
267  struct MetaItem *mi;
268  char *p;
269 
270  if ((EXTRACTOR_METAFORMAT_UTF8 == format) ||
271  (EXTRACTOR_METAFORMAT_C_STRING == format))
272  GNUNET_break ('\0' == data[data_size - 1]);
273 
274  for (pos = md->items_head; NULL != pos; pos = pos->next)
275  {
276  if (pos->data_size < data_size)
277  break; /* elements are sorted by size in the list */
278  if ((pos->type == type) && (pos->data_size == data_size) &&
279  (0 == memcmp (pos->data, data, data_size)))
280  {
281  if ((NULL == pos->mime_type) && (NULL != data_mime_type))
282  {
283  pos->mime_type = GNUNET_strdup (data_mime_type);
284  invalidate_sbuf (md);
285  }
286  if ((EXTRACTOR_METAFORMAT_C_STRING == pos->format) &&
287  (EXTRACTOR_METAFORMAT_UTF8 == format))
288  {
289  pos->format = EXTRACTOR_METAFORMAT_UTF8;
290  invalidate_sbuf (md);
291  }
292  return GNUNET_SYSERR;
293  }
294  }
295  md->item_count++;
296  mi = GNUNET_new (struct MetaItem);
297  mi->type = type;
298  mi->format = format;
299  mi->data_size = data_size;
300  if (NULL == pos)
302  md->items_tail,
303  mi);
304  else
306  md->items_tail,
307  pos->prev,
308  mi);
309  mi->mime_type =
310  (NULL == data_mime_type) ? NULL : GNUNET_strdup (data_mime_type);
311  mi->plugin_name = (NULL == plugin_name) ? NULL : GNUNET_strdup (plugin_name);
312  mi->data = GNUNET_malloc (data_size);
314  /* change all dir separators to POSIX style ('/') */
315  if ((EXTRACTOR_METATYPE_FILENAME == type) ||
317  {
318  p = mi->data;
319  while (('\0' != *p) && (p < mi->data + data_size))
320  {
321  if ('\\' == *p)
322  *p = '/';
323  p++;
324  }
325  }
326  invalidate_sbuf (md);
327  return GNUNET_OK;
328 }
329 
330 
347 static int
348 merge_helper (void *cls, const char *plugin_name, enum EXTRACTOR_MetaType type,
349  enum EXTRACTOR_MetaFormat format, const char *data_mime_type,
350  const char *data, size_t data_size)
351 {
352  struct GNUNET_FS_MetaData *md = cls;
353 
354  (void) GNUNET_FS_meta_data_insert (md, plugin_name, type, format,
355  data_mime_type, data, data_size);
356  return 0;
357 }
358 
359 
360 void
362  const struct GNUNET_FS_MetaData *in)
363 {
365 }
366 
367 
368 int
370  enum EXTRACTOR_MetaType type,
371  const char *data, size_t data_size)
372 {
373  struct MetaItem *pos;
374 
375  for (pos = md->items_head; NULL != pos; pos = pos->next)
376  {
377  if (pos->data_size < data_size)
378  break; /* items are sorted by (decreasing) size */
379  if ((pos->type == type) &&
380  ((NULL == data) ||
381  ((pos->data_size == data_size) &&
382  (0 == memcmp (pos->data, data, data_size)))))
383  {
385  meta_item_free (pos);
386  md->item_count--;
387  invalidate_sbuf (md);
388  return GNUNET_OK;
389  }
390  }
391  return GNUNET_SYSERR;
392 }
393 
394 
395 void
397  GNUNET_FS_MetaData *md)
398 {
399  const char *dat;
400  struct GNUNET_TIME_Absolute t;
401 
404  EXTRACTOR_METATYPE_PUBLICATION_DATE,
405  NULL, 0);
407  GNUNET_FS_meta_data_insert (md, "<gnunet>",
408  EXTRACTOR_METATYPE_PUBLICATION_DATE,
409  EXTRACTOR_METAFORMAT_UTF8, "text/plain",
410  dat, strlen (dat) + 1);
411 }
412 
413 
422 int
424  EXTRACTOR_MetaDataProcessor iter,
425  void *iter_cls)
426 {
427  struct MetaItem *pos;
428 
429  if (NULL == md)
430  return 0;
431  if (NULL == iter)
432  return md->item_count;
433  for (pos = md->items_head; NULL != pos; pos = pos->next)
434  if (0 !=
435  iter (iter_cls, pos->plugin_name, pos->type, pos->format,
436  pos->mime_type, pos->data, pos->data_size))
437  return md->item_count;
438  return md->item_count;
439 }
440 
441 
442 char *
444  GNUNET_FS_MetaData *md,
445  enum EXTRACTOR_MetaType type)
446 {
447  struct MetaItem *pos;
448 
449  if (NULL == md)
450  return NULL;
451  for (pos = md->items_head; NULL != pos; pos = pos->next)
452  if ((type == pos->type) &&
453  ((pos->format == EXTRACTOR_METAFORMAT_UTF8) ||
454  (pos->format == EXTRACTOR_METAFORMAT_C_STRING)))
455  return GNUNET_strdup (pos->data);
456  return NULL;
457 }
458 
459 
460 char *
462  GNUNET_FS_MetaData *md,
463  ...)
464 {
465  char *ret;
466  va_list args;
467  int type;
468 
469  if (NULL == md)
470  return NULL;
471  ret = NULL;
472  va_start (args, md);
473  while (1)
474  {
475  type = va_arg (args, int);
476  if (-1 == type)
477  break;
478  if (NULL != (ret = GNUNET_FS_meta_data_get_by_type (md, type)))
479  break;
480  }
481  va_end (args);
482  return ret;
483 }
484 
485 
494 size_t
496  *md, unsigned char **thumb)
497 {
498  struct MetaItem *pos;
499  struct MetaItem *match;
500 
501  if (NULL == md)
502  return 0;
503  match = NULL;
504  for (pos = md->items_head; NULL != pos; pos = pos->next)
505  {
506  if ((NULL != pos->mime_type) &&
507  (0 == strncasecmp ("image/", pos->mime_type, strlen ("image/"))) &&
508  (EXTRACTOR_METAFORMAT_BINARY == pos->format))
509  {
510  if (NULL == match)
511  match = pos;
512  else if ((match->type != EXTRACTOR_METATYPE_THUMBNAIL) &&
513  (pos->type == EXTRACTOR_METATYPE_THUMBNAIL))
514  match = pos;
515  }
516  }
517  if ((NULL == match) || (0 == match->data_size))
518  return 0;
519  *thumb = GNUNET_malloc (match->data_size);
520  GNUNET_memcpy (*thumb, match->data, match->data_size);
521  return match->data_size;
522 }
523 
524 
531 struct GNUNET_FS_MetaData *
533  *md)
534 {
535  struct GNUNET_FS_MetaData *ret;
536  struct MetaItem *pos;
537 
538  if (NULL == md)
539  return NULL;
541  for (pos = md->items_tail; NULL != pos; pos = pos->prev)
543  pos->format, pos->mime_type, pos->data,
544  pos->data_size);
545  return ret;
546 }
547 
548 
552 #define HEADER_COMPRESSED 0x80000000
553 
554 
558 #define HEADER_VERSION_MASK 0x7FFFFFFF
559 
560 
565 {
575  uint32_t version;
576 
580  uint32_t entries;
581 
585  uint32_t size;
586 
592 };
593 
594 
599 {
603  uint32_t type;
604 
608  uint32_t format;
609 
613  uint32_t data_size;
614 
618  uint32_t plugin_name_len;
619 
623  uint32_t mime_type_len;
624 };
625 
626 
641 ssize_t
643  *md, char **target, size_t max,
644  enum
646  opt)
647 {
648  struct GNUNET_FS_MetaData *vmd;
649  struct MetaItem *pos;
650  struct MetaDataHeader ihdr;
651  struct MetaDataHeader *hdr;
652  struct MetaDataEntry *ent;
653  char *dst;
654  unsigned int i;
655  uint64_t msize;
656  size_t off;
657  char *mdata;
658  char *cdata;
659  size_t mlen;
660  size_t plen;
661  size_t size;
662  size_t left;
663  size_t clen;
664  size_t rlen;
665  int comp;
666 
667  if (max < sizeof(struct MetaDataHeader))
668  return GNUNET_SYSERR; /* far too small */
669  if (NULL == md)
670  return 0;
671 
672  if (NULL != md->sbuf)
673  {
674  /* try to use serialization cache */
675  if (md->sbuf_size <= max)
676  {
677  if (NULL == *target)
678  *target = GNUNET_malloc (md->sbuf_size);
679  GNUNET_memcpy (*target, md->sbuf, md->sbuf_size);
680  return md->sbuf_size;
681  }
682  if (0 == (opt & GNUNET_FS_META_DATA_SERIALIZE_PART))
683  return GNUNET_SYSERR; /* can say that this will fail */
684  /* need to compute a partial serialization, sbuf useless ... */
685  }
686  dst = NULL;
687  msize = 0;
688  for (pos = md->items_tail; NULL != pos; pos = pos->prev)
689  {
690  msize += sizeof(struct MetaDataEntry);
691  msize += pos->data_size;
692  if (NULL != pos->plugin_name)
693  msize += strlen (pos->plugin_name) + 1;
694  if (NULL != pos->mime_type)
695  msize += strlen (pos->mime_type) + 1;
696  }
697  size = (size_t) msize;
698  if (size != msize)
699  {
700  GNUNET_break (0); /* integer overflow */
701  return GNUNET_SYSERR;
702  }
704  {
705  /* too large to be processed */
706  return GNUNET_SYSERR;
707  }
708  ent = GNUNET_malloc (size);
709  mdata = (char *) &ent[md->item_count];
710  off = size - (md->item_count * sizeof(struct MetaDataEntry));
711  i = 0;
712  for (pos = md->items_head; NULL != pos; pos = pos->next)
713  {
714  ent[i].type = htonl ((uint32_t) pos->type);
715  ent[i].format = htonl ((uint32_t) pos->format);
716  ent[i].data_size = htonl ((uint32_t) pos->data_size);
717  if (NULL == pos->plugin_name)
718  plen = 0;
719  else
720  plen = strlen (pos->plugin_name) + 1;
721  ent[i].plugin_name_len = htonl ((uint32_t) plen);
722  if (NULL == pos->mime_type)
723  mlen = 0;
724  else
725  mlen = strlen (pos->mime_type) + 1;
726  ent[i].mime_type_len = htonl ((uint32_t) mlen);
727  off -= pos->data_size;
728  if ((EXTRACTOR_METAFORMAT_UTF8 == pos->format) ||
729  (EXTRACTOR_METAFORMAT_C_STRING == pos->format))
730  GNUNET_break ('\0' == pos->data[pos->data_size - 1]);
731  GNUNET_memcpy (&mdata[off], pos->data, pos->data_size);
732  off -= plen;
733  if (NULL != pos->plugin_name)
734  GNUNET_memcpy (&mdata[off], pos->plugin_name, plen);
735  off -= mlen;
736  if (NULL != pos->mime_type)
737  GNUNET_memcpy (&mdata[off], pos->mime_type, mlen);
738  i++;
739  }
740  GNUNET_assert (0 == off);
741 
742  clen = 0;
743  cdata = NULL;
744  left = size;
745  i = 0;
746  for (pos = md->items_head; NULL != pos; pos = pos->next)
747  {
748  comp = GNUNET_NO;
750  comp = GNUNET_try_compression ((const char *) &ent[i],
751  left,
752  &cdata,
753  &clen);
754 
755  if ((NULL == md->sbuf) && (0 == i))
756  {
757  /* fill 'sbuf'; this "modifies" md, but since this is only
758  * an internal cache we will cast away the 'const' instead
759  * of making the API look strange. */
760  vmd = (struct GNUNET_FS_MetaData *) md;
761  hdr = GNUNET_malloc (left + sizeof(struct MetaDataHeader));
762  hdr->size = htonl (left);
763  hdr->entries = htonl (md->item_count);
764  if (GNUNET_YES == comp)
765  {
766  GNUNET_assert (clen < left);
767  hdr->version = htonl (2 | HEADER_COMPRESSED);
768  GNUNET_memcpy (&hdr[1], cdata, clen);
769  vmd->sbuf_size = clen + sizeof(struct MetaDataHeader);
770  }
771  else
772  {
773  hdr->version = htonl (2);
774  GNUNET_memcpy (&hdr[1], &ent[0], left);
775  vmd->sbuf_size = left + sizeof(struct MetaDataHeader);
776  }
777  vmd->sbuf = (char *) hdr;
778  }
779 
780  if (((left + sizeof(struct MetaDataHeader)) <= max) ||
781  ((GNUNET_YES == comp) && (clen <= max)))
782  {
783  /* success, this now fits! */
784  if (GNUNET_YES == comp)
785  {
786  if (NULL == dst)
787  dst = GNUNET_malloc (clen + sizeof(struct MetaDataHeader));
788  hdr = (struct MetaDataHeader *) dst;
789  hdr->version = htonl (2 | HEADER_COMPRESSED);
790  hdr->size = htonl (left);
791  hdr->entries = htonl (md->item_count - i);
792  GNUNET_memcpy (&dst[sizeof(struct MetaDataHeader)], cdata, clen);
793  GNUNET_free (cdata);
794  cdata = NULL;
795  GNUNET_free (ent);
796  rlen = clen + sizeof(struct MetaDataHeader);
797  }
798  else
799  {
800  if (NULL == dst)
801  dst = GNUNET_malloc (left + sizeof(struct MetaDataHeader));
802  hdr = (struct MetaDataHeader *) dst;
803  hdr->version = htonl (2);
804  hdr->entries = htonl (md->item_count - i);
805  hdr->size = htonl (left);
806  GNUNET_memcpy (&dst[sizeof(struct MetaDataHeader)], &ent[i], left);
807  GNUNET_free (ent);
808  rlen = left + sizeof(struct MetaDataHeader);
809  }
810  if (NULL != *target)
811  {
812  if (GNUNET_YES == comp)
813  GNUNET_memcpy (*target, dst, clen + sizeof(struct MetaDataHeader));
814  else
815  GNUNET_memcpy (*target, dst, left + sizeof(struct MetaDataHeader));
816  GNUNET_free (dst);
817  }
818  else
819  {
820  *target = dst;
821  }
822  return rlen;
823  }
824 
825  if (0 == (opt & GNUNET_FS_META_DATA_SERIALIZE_PART))
826  {
827  /* does not fit! */
828  GNUNET_free (ent);
829  if (NULL != cdata)
830  GNUNET_free (cdata);
831  cdata = NULL;
832  return GNUNET_SYSERR;
833  }
834 
835  /* next iteration: ignore the corresponding meta data at the
836  * end and try again without it */
837  left -= sizeof(struct MetaDataEntry);
838  left -= pos->data_size;
839  if (NULL != pos->plugin_name)
840  left -= strlen (pos->plugin_name) + 1;
841  if (NULL != pos->mime_type)
842  left -= strlen (pos->mime_type) + 1;
843 
844  if (NULL != cdata)
845  GNUNET_free (cdata);
846  cdata = NULL;
847  i++;
848  }
849  GNUNET_free (ent);
850 
851  /* nothing fit, only write header! */
852  ihdr.version = htonl (2);
853  ihdr.entries = htonl (0);
854  ihdr.size = htonl (0);
855  if (NULL == *target)
856  *target = (char *) GNUNET_new (struct MetaDataHeader);
857  GNUNET_memcpy (*target, &ihdr, sizeof(struct MetaDataHeader));
858  return sizeof(struct MetaDataHeader);
859 }
860 
861 
862 ssize_t
864  GNUNET_FS_MetaData *md)
865 {
866  ssize_t ret;
867  char *ptr;
868 
869  if (NULL != md->sbuf)
870  return md->sbuf_size;
871  ptr = NULL;
872  ret =
875  if (-1 != ret)
876  GNUNET_free (ptr);
877  return ret;
878 }
879 
880 
889 struct GNUNET_FS_MetaData *
890 GNUNET_FS_meta_data_deserialize (const char *input, size_t size)
891 {
892  struct GNUNET_FS_MetaData *md;
893  struct MetaDataHeader hdr;
894  struct MetaDataEntry ent;
895  uint32_t ic;
896  uint32_t i;
897  char *data;
898  const char *cdata;
899  uint32_t version;
900  uint32_t dataSize;
901  int compressed;
902  size_t left;
903  uint32_t mlen;
904  uint32_t plen;
905  uint32_t dlen;
906  const char *mdata;
907  const char *meta_data;
908  const char *plugin_name;
909  const char *mime_type;
910  enum EXTRACTOR_MetaFormat format;
911 
912  if (size < sizeof(struct MetaDataHeader))
913  return NULL;
914  GNUNET_memcpy (&hdr, input, sizeof(struct MetaDataHeader));
915  version = ntohl (hdr.version) & HEADER_VERSION_MASK;
916  compressed = (ntohl (hdr.version) & HEADER_COMPRESSED) != 0;
917 
918  if (1 == version)
919  return NULL; /* null pointer */
920  if (2 != version)
921  {
922  GNUNET_break_op (0); /* unsupported version */
923  return NULL;
924  }
925 
926  ic = ntohl (hdr.entries);
927  dataSize = ntohl (hdr.size);
928  if (((sizeof(struct MetaDataEntry) * ic) > dataSize) ||
929  ((0 != ic) &&
930  (dataSize / ic < sizeof(struct MetaDataEntry))))
931  {
932  GNUNET_break_op (0);
933  return NULL;
934  }
935 
936  if (compressed)
937  {
938  if (dataSize >= GNUNET_MAX_MALLOC_CHECKED)
939  {
940  /* make sure we don't blow our memory limit because of a mal-formed
941  * message... */
942  GNUNET_break_op (0);
943  return NULL;
944  }
945  data =
946  GNUNET_decompress ((const char *) &input[sizeof(struct MetaDataHeader)],
947  size - sizeof(struct MetaDataHeader),
948  dataSize);
949  if (NULL == data)
950  {
951  GNUNET_break_op (0);
952  return NULL;
953  }
954  cdata = data;
955  }
956  else
957  {
958  data = NULL;
959  cdata = (const char *) &input[sizeof(struct MetaDataHeader)];
960  if (dataSize != size - sizeof(struct MetaDataHeader))
961  {
962  GNUNET_break_op (0);
963  return NULL;
964  }
965  }
966 
968  left = dataSize - ic * sizeof(struct MetaDataEntry);
969  mdata = &cdata[ic * sizeof(struct MetaDataEntry)];
970  for (i = 0; i < ic; i++)
971  {
972  GNUNET_memcpy (&ent, &cdata[i * sizeof(struct MetaDataEntry)],
973  sizeof(struct MetaDataEntry));
974  format = (enum EXTRACTOR_MetaFormat) ntohl (ent.format);
975  if ((EXTRACTOR_METAFORMAT_UTF8 != format) &&
976  (EXTRACTOR_METAFORMAT_C_STRING != format) &&
977  (EXTRACTOR_METAFORMAT_BINARY != format))
978  {
979  GNUNET_break_op (0);
980  break;
981  }
982  dlen = ntohl (ent.data_size);
983  plen = ntohl (ent.plugin_name_len);
984  mlen = ntohl (ent.mime_type_len);
985  if (dlen > left)
986  {
987  GNUNET_break_op (0);
988  break;
989  }
990  left -= dlen;
991  meta_data = &mdata[left];
992  if ((EXTRACTOR_METAFORMAT_UTF8 == format) ||
993  (EXTRACTOR_METAFORMAT_C_STRING == format))
994  {
995  if (0 == dlen)
996  {
997  GNUNET_break_op (0);
998  break;
999  }
1000  if ('\0' != meta_data[dlen - 1])
1001  {
1002  GNUNET_break_op (0);
1003  break;
1004  }
1005  }
1006  if (plen > left)
1007  {
1008  GNUNET_break_op (0);
1009  break;
1010  }
1011  left -= plen;
1012  if ((plen > 0) && ('\0' != mdata[left + plen - 1]))
1013  {
1014  GNUNET_break_op (0);
1015  break;
1016  }
1017  if (0 == plen)
1018  plugin_name = NULL;
1019  else
1020  plugin_name = &mdata[left];
1021 
1022  if (mlen > left)
1023  {
1024  GNUNET_break_op (0);
1025  break;
1026  }
1027  left -= mlen;
1028  if ((mlen > 0) && ('\0' != mdata[left + mlen - 1]))
1029  {
1030  GNUNET_break_op (0);
1031  break;
1032  }
1033  if (0 == mlen)
1034  mime_type = NULL;
1035  else
1036  mime_type = &mdata[left];
1038  (enum EXTRACTOR_MetaType)
1039  ntohl (ent.type), format, mime_type,
1040  meta_data, dlen);
1041  }
1042  GNUNET_free (data);
1043  return md;
1044 }
1045 
1056  const char *what,
1057  struct GNUNET_FS_MetaData **result)
1058 {
1059  uint32_t size;
1060  char *buf;
1061  char *emsg;
1062  struct GNUNET_FS_MetaData *meta;
1063 
1065  _ ("metadata length"),
1066  (int32_t *) &size))
1067  return GNUNET_SYSERR;
1068  if (0 == size)
1069  {
1070  *result = NULL;
1071  return GNUNET_OK;
1072  }
1073  if (MAX_META_DATA < size)
1074  {
1075  GNUNET_asprintf (&emsg,
1076  _ (
1077  "Serialized metadata `%s' larger than allowed (%u > %u)\n"),
1078  what,
1079  size,
1080  MAX_META_DATA);
1081  GNUNET_BIO_read_set_error (h, emsg);
1082  GNUNET_free (emsg);
1083  return GNUNET_SYSERR;
1084  }
1085  buf = GNUNET_malloc (size);
1086  if (GNUNET_OK != GNUNET_BIO_read (h, what, buf, size))
1087  {
1088  GNUNET_free (buf);
1089  return GNUNET_SYSERR;
1090  }
1092  if (NULL == meta)
1093  {
1094  GNUNET_free (buf);
1096  _ ("Failed to deserialize metadata `%s'"), what);
1097  return GNUNET_SYSERR;
1098  }
1099  GNUNET_free (buf);
1100  *result = meta;
1101  return GNUNET_OK;
1102 }
1103 
1114  const char *what,
1115  const struct GNUNET_FS_MetaData *m)
1116 {
1117  ssize_t size;
1118  char *buf;
1119 
1120  if (m == NULL)
1121  return GNUNET_BIO_write_int32 (h, _ ("metadata length"), 0);
1122  buf = NULL;
1124  &buf,
1125  MAX_META_DATA,
1128  _ ("Serialized %ld bytes of metadata"),
1129  size);
1130 
1131  if (-1 == size)
1132  {
1133  GNUNET_free (buf);
1135  _ ("Failed to serialize metadata `%s'"),
1136  what);
1137  return GNUNET_SYSERR;
1138  }
1140  _ ("metadata length"),
1141  (uint32_t) size))
1142  || (GNUNET_OK != GNUNET_BIO_write (h, what, buf, size)))
1143  {
1144  GNUNET_free (buf);
1145  return GNUNET_SYSERR;
1146  }
1147  GNUNET_free (buf);
1148  return GNUNET_OK;
1149 }
1150 
1162 static int
1164  struct GNUNET_BIO_ReadHandle *h,
1165  const char *what,
1166  void *target,
1167  size_t target_size)
1168 {
1169  struct GNUNET_FS_MetaData **result = target;
1170  return GNUNET_FS_read_meta_data (h, what, result);
1171 }
1172 
1180 struct GNUNET_BIO_ReadSpec
1181 GNUNET_FS_read_spec_meta_data (const char *what,
1182  struct GNUNET_FS_MetaData **result)
1183 {
1184  struct GNUNET_BIO_ReadSpec rs = {
1186  .cls = NULL,
1187  .target = result,
1188  .size = 0,
1189  };
1190 
1191  return rs;
1192 }
1193 
1205 static int
1207  struct GNUNET_BIO_WriteHandle *h,
1208  const char *what,
1209  void *source,
1210  size_t source_size)
1211 {
1212  const struct GNUNET_FS_MetaData *m = source;
1213  return GNUNET_FS_write_meta_data (h, what, m);
1214 }
1215 
1216 
1217 struct GNUNET_BIO_WriteSpec
1219  const struct GNUNET_FS_MetaData *m)
1220 {
1221  struct GNUNET_BIO_WriteSpec ws = {
1223  .cls = NULL,
1224  .what = what,
1225  .source = (void *) m,
1226  .source_size = 0,
1227  };
1228 
1229  return ws;
1230 }
1231 
1232 
1233 /* 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.
commonly used definitions; globals in this file are exempt from the rule that the module name ("commo...
API for file sharing via GNUnet.
enum GNUNET_GenericReturnValue 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:292
enum GNUNET_GenericReturnValue GNUNET_BIO_write_int32(struct GNUNET_BIO_WriteHandle *h, const char *what, int32_t i)
Write an (u)int32_t.
Definition: bio.c:848
enum GNUNET_GenericReturnValue 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:753
void GNUNET_BIO_read_set_error(struct GNUNET_BIO_ReadHandle *h, const char *emsg)
Set read error to handle.
Definition: bio.c:188
enum GNUNET_GenericReturnValue GNUNET_BIO_read_int32(struct GNUNET_BIO_ReadHandle *h, const char *what, int32_t *i)
Read an (u)int32_t.
Definition: bio.c:428
#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:1113
enum GNUNET_GenericReturnValue 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:1055
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:1181
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:1218
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:423
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:396
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:863
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:495
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:642
void GNUNET_FS_meta_data_merge(struct GNUNET_FS_MetaData *md, const struct GNUNET_FS_MetaData *in)
Extend metadata.
Definition: meta_data.c:361
struct GNUNET_FS_MetaData * GNUNET_FS_meta_data_create()
Create a fresh struct FS_MetaData token.
Definition: meta_data.c:132
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:443
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:532
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:259
void GNUNET_FS_meta_data_destroy(struct GNUNET_FS_MetaData *md)
Free meta data.
Definition: meta_data.c:171
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:205
void GNUNET_FS_meta_data_clear(struct GNUNET_FS_MetaData *md)
Remove all items in the container.
Definition: meta_data.c:188
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:369
struct GNUNET_FS_MetaData * GNUNET_FS_meta_data_deserialize(const char *input, size_t size)
Deserialize meta-data.
Definition: meta_data.c:890
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:461
@ 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:144
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:1206
#define HEADER_VERSION_MASK
Bits in 'version' that give the version number.
Definition: meta_data.c:558
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:1163
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:348
#define MAX_META_DATA
Maximum size allowed for meta data written/read from disk.
Definition: meta_data.c:39
static void invalidate_sbuf(struct GNUNET_FS_MetaData *md)
The meta data has changed, invalidate its serialization buffer.
Definition: meta_data.c:160
#define HEADER_COMPRESSED
Flag in 'version' that indicates compressed meta-data.
Definition: meta_data.c:552
static unsigned int size
Size of the "table".
Definition: peer.c:68
#define _(String)
GNU gettext support macro.
Definition: platform.h:178
Handle for buffered reading.
Definition: bio.c:70
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:467
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:97
size_t sbuf_size
Number of bytes in 'sbuf'.
Definition: meta_data.c:117
struct MetaItem * items_head
Head of linked list of the meta data items.
Definition: meta_data.c:101
unsigned int item_count
Number of items in the linked list.
Definition: meta_data.c:122
struct MetaItem * items_tail
Tail of linked list of the meta data items.
Definition: meta_data.c:106
char * sbuf
Complete serialized and compressed buffer of the items.
Definition: meta_data.c:112
Time for absolute times used by GNUnet, in microseconds.
Entry of serialized meta data.
Definition: meta_data.c:599
uint32_t plugin_name_len
Number of bytes in the plugin name including 0-terminator.
Definition: meta_data.c:618
uint32_t mime_type_len
Number of bytes in the mime type including 0-terminator.
Definition: meta_data.c:623
uint32_t type
Meta data type.
Definition: meta_data.c:603
uint32_t data_size
Number of bytes of meta data.
Definition: meta_data.c:613
uint32_t format
Meta data format.
Definition: meta_data.c:608
Header for serialized meta data.
Definition: meta_data.c:565
uint32_t entries
How many MD entries are there?
Definition: meta_data.c:580
uint32_t size
Size of the decompressed meta data.
Definition: meta_data.c:585
uint32_t version
The version of the MD serialization.
Definition: meta_data.c:575
Meta data item.
Definition: meta_data.c:51
struct MetaItem * prev
This is a doubly linked list.
Definition: meta_data.c:60
struct MetaItem * next
This is a doubly linked list.
Definition: meta_data.c:55
enum EXTRACTOR_MetaType type
Type of the meta data.
Definition: meta_data.c:85
size_t data_size
Number of bytes in 'data'.
Definition: meta_data.c:80
char * mime_type
Mime-type of data.
Definition: meta_data.c:70
enum EXTRACTOR_MetaFormat format
Format of the meta data.
Definition: meta_data.c:90
char * data
The actual meta data.
Definition: meta_data.c:75
char * plugin_name
Name of the extracting plugin.
Definition: meta_data.c:65
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model