aboutsummaryrefslogtreecommitdiff
path: root/src/util
diff options
context:
space:
mode:
authorMartin Schanzenbach <schanzen@gnunet.org>2022-12-04 23:26:25 +0900
committerMartin Schanzenbach <schanzen@gnunet.org>2022-12-04 23:26:25 +0900
commit395bc9345a005a55e29a7882fdcc82f35c06d2e5 (patch)
treeb111592f9f57025a19ddafe11877f6038263ae7f /src/util
parent3f0d91045d29435feef723f09f9ff75c80296d3d (diff)
downloadgnunet-395bc9345a005a55e29a7882fdcc82f35c06d2e5.tar.gz
gnunet-395bc9345a005a55e29a7882fdcc82f35c06d2e5.zip
Large refactor in order to restore some sanity with respect to private defines used in headers
Diffstat (limited to 'src/util')
-rw-r--r--src/util/Makefile.am7
-rw-r--r--src/util/bio.c198
-rw-r--r--src/util/compress.c91
-rw-r--r--src/util/container_meta_data.c1122
-rw-r--r--src/util/crypto_crc.c6
-rw-r--r--src/util/test_container_meta_data.c376
6 files changed, 96 insertions, 1704 deletions
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
index 90f111cad..284a7806d 100644
--- a/src/util/Makefile.am
+++ b/src/util/Makefile.am
@@ -48,12 +48,12 @@ libgnunetutil_la_SOURCES = \
48 common_allocation.c \ 48 common_allocation.c \
49 common_endian.c \ 49 common_endian.c \
50 common_logging.c \ 50 common_logging.c \
51 compress.c \
51 configuration.c \ 52 configuration.c \
52 configuration_helper.c \ 53 configuration_helper.c \
53 consttime_memcmp.c \ 54 consttime_memcmp.c \
54 container_bloomfilter.c \ 55 container_bloomfilter.c \
55 container_heap.c \ 56 container_heap.c \
56 container_meta_data.c \
57 container_multihashmap.c \ 57 container_multihashmap.c \
58 container_multishortmap.c \ 58 container_multishortmap.c \
59 container_multiuuidmap.c \ 59 container_multiuuidmap.c \
@@ -423,11 +423,6 @@ test_container_dll_SOURCES = \
423test_container_dll_LDADD = \ 423test_container_dll_LDADD = \
424 libgnunetutil.la 424 libgnunetutil.la
425 425
426test_container_meta_data_SOURCES = \
427 test_container_meta_data.c
428test_container_meta_data_LDADD = \
429 libgnunetutil.la
430
431test_container_multihashmap_SOURCES = \ 426test_container_multihashmap_SOURCES = \
432 test_container_multihashmap.c 427 test_container_multihashmap.c
433test_container_multihashmap_LDADD = \ 428test_container_multihashmap_LDADD = \
diff --git a/src/util/bio.c b/src/util/bio.c
index 1abe6e324..a19e4f3ba 100644
--- a/src/util/bio.c
+++ b/src/util/bio.c
@@ -41,12 +41,6 @@
41 */ 41 */
42#define BIO_BUFFER_SIZE 65536 42#define BIO_BUFFER_SIZE 65536
43 43
44/**
45 * Maximum size allowed for meta data written/read from disk.
46 * File-sharing limits to 64k, so this should be rather generous.
47 */
48#define MAX_META_DATA (1024 * 1024)
49
50 44
51/** 45/**
52 * Enum used internally to know how buffering is handled. 46 * Enum used internally to know how buffering is handled.
@@ -160,7 +154,7 @@ GNUNET_BIO_read_open_buffer (void *buffer, size_t size)
160 * 154 *
161 * @param h file handle 155 * @param h file handle
162 * @param emsg set to the (allocated) error message 156 * @param emsg set to the (allocated) error message
163 * if the handle has an error message, the return 157 * if the handle has an error message, the return
164 * value is #GNUNET_SYSERR 158 * value is #GNUNET_SYSERR
165 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise 159 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
166 */ 160 */
@@ -379,60 +373,6 @@ GNUNET_BIO_read_string (struct GNUNET_BIO_ReadHandle *h,
379} 373}
380 374
381 375
382/**
383 * Read a metadata container.
384 *
385 * @param h handle to an open file
386 * @param what describes what is being read (for error message creation)
387 * @param result the buffer to store a pointer to the (allocated) metadata
388 * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
389 */
390int
391GNUNET_BIO_read_meta_data (struct GNUNET_BIO_ReadHandle *h,
392 const char *what,
393 struct GNUNET_CONTAINER_MetaData **result)
394{
395 uint32_t size;
396 char *buf;
397 struct GNUNET_CONTAINER_MetaData *meta;
398
399 if (GNUNET_OK != GNUNET_BIO_read_int32 (h,
400 _ ("metadata length"),
401 (int32_t *) &size))
402 return GNUNET_SYSERR;
403 if (0 == size)
404 {
405 *result = NULL;
406 return GNUNET_OK;
407 }
408 if (MAX_META_DATA < size)
409 {
410 GNUNET_asprintf (
411 &h->emsg,
412 _ ("Serialized metadata `%s' larger than allowed (%u > %u)"),
413 what,
414 size,
415 MAX_META_DATA);
416 return GNUNET_SYSERR;
417 }
418 buf = GNUNET_malloc (size);
419 if (GNUNET_OK != GNUNET_BIO_read (h, what, buf, size))
420 {
421 GNUNET_free (buf);
422 return GNUNET_SYSERR;
423 }
424 meta = GNUNET_CONTAINER_meta_data_deserialize (buf, size);
425 if (NULL == meta)
426 {
427 GNUNET_free (buf);
428 GNUNET_asprintf (&h->emsg, _ ("Failed to deserialize metadata `%s'"), what);
429 return GNUNET_SYSERR;
430 }
431 GNUNET_free (buf);
432 *result = meta;
433 return GNUNET_OK;
434}
435
436 376
437/** 377/**
438 * Read a float. 378 * Read a float.
@@ -846,51 +786,6 @@ GNUNET_BIO_write_string (struct GNUNET_BIO_WriteHandle *h,
846} 786}
847 787
848 788
849/**
850 * Write a metadata container.
851 *
852 * @param h the IO handle to write to
853 * @param what what is being written (for error message creation)
854 * @param m metadata to write
855 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
856 */
857int
858GNUNET_BIO_write_meta_data (struct GNUNET_BIO_WriteHandle *h,
859 const char *what,
860 const struct GNUNET_CONTAINER_MetaData *m)
861{
862 ssize_t size;
863 char *buf;
864
865 if (m == NULL)
866 return GNUNET_BIO_write_int32 (h, _ ("metadata length"), 0);
867 buf = NULL;
868 size = GNUNET_CONTAINER_meta_data_serialize (
869 m,
870 &buf,
871 MAX_META_DATA,
872 GNUNET_CONTAINER_META_DATA_SERIALIZE_PART);
873 if (-1 == size)
874 {
875 GNUNET_free (buf);
876 GNUNET_free (h->emsg);
877 GNUNET_asprintf (&h->emsg,
878 _ ("Failed to serialize metadata `%s'"),
879 what);
880 return GNUNET_SYSERR;
881 }
882 if ((GNUNET_OK != GNUNET_BIO_write_int32 (h,
883 _ ("metadata length"),
884 (uint32_t) size))
885 || (GNUNET_OK != GNUNET_BIO_write (h, what, buf, size)))
886 {
887 GNUNET_free (buf);
888 return GNUNET_SYSERR;
889 }
890 GNUNET_free (buf);
891 return GNUNET_OK;
892}
893
894 789
895/** 790/**
896 * Write a float. 791 * Write a float.
@@ -1060,51 +955,6 @@ GNUNET_BIO_read_spec_string (const char *what,
1060 955
1061 956
1062/** 957/**
1063 * Function used internally to read a metadata container from within a read
1064 * spec.
1065 *
1066 * @param cls ignored, always NULL
1067 * @param h the IO handle to read from
1068 * @param what what is being read (for error message creation)
1069 * @param target where to store the data
1070 * @param target_size ignored
1071 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
1072 */
1073static int
1074read_spec_handler_meta_data (void *cls,
1075 struct GNUNET_BIO_ReadHandle *h,
1076 const char *what,
1077 void *target,
1078 size_t target_size)
1079{
1080 struct GNUNET_CONTAINER_MetaData **result = target;
1081 return GNUNET_BIO_read_meta_data (h, what, result);
1082}
1083
1084
1085/**
1086 * Create the specification to read a metadata container.
1087 *
1088 * @param what describes what is being read (for error message creation)
1089 * @param result the buffer to store a pointer to the (allocated) metadata
1090 * @return the read spec
1091 */
1092struct GNUNET_BIO_ReadSpec
1093GNUNET_BIO_read_spec_meta_data (const char *what,
1094 struct GNUNET_CONTAINER_MetaData **result)
1095{
1096 struct GNUNET_BIO_ReadSpec rs = {
1097 .rh = &read_spec_handler_meta_data,
1098 .cls = NULL,
1099 .target = result,
1100 .size = 0,
1101 };
1102
1103 return rs;
1104}
1105
1106
1107/**
1108 * Function used internally to read an (u)int32_t from within a read spec. 958 * Function used internally to read an (u)int32_t from within a read spec.
1109 * 959 *
1110 * @param cls ignored, always NULL 960 * @param cls ignored, always NULL
@@ -1350,52 +1200,6 @@ GNUNET_BIO_write_spec_string (const char *what,
1350 1200
1351 1201
1352/** 1202/**
1353 * Function used internally to write a metadata container from within a write
1354 * spec.
1355 *
1356 * @param cls ignored, always NULL
1357 * @param h the IO handle to write to
1358 * @param what what is being written (for error message creation)
1359 * @param source the data to write
1360 * @param source_size ignored
1361 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
1362 */
1363static int
1364write_spec_handler_meta_data (void *cls,
1365 struct GNUNET_BIO_WriteHandle *h,
1366 const char *what,
1367 void *source,
1368 size_t source_size)
1369{
1370 const struct GNUNET_CONTAINER_MetaData *m = source;
1371 return GNUNET_BIO_write_meta_data (h, what, m);
1372}
1373
1374
1375/**
1376 * Create the specification to write a metadata container.
1377 *
1378 * @param what what is being written (for error message creation)
1379 * @param m metadata to write
1380 * @return the write spec
1381 */
1382struct GNUNET_BIO_WriteSpec
1383GNUNET_BIO_write_spec_meta_data (const char *what,
1384 const struct GNUNET_CONTAINER_MetaData *m)
1385{
1386 struct GNUNET_BIO_WriteSpec ws = {
1387 .wh = &write_spec_handler_meta_data,
1388 .cls = NULL,
1389 .what = what,
1390 .source = (void *) m,
1391 .source_size = 0,
1392 };
1393
1394 return ws;
1395}
1396
1397
1398/**
1399 * Function used internally to write an (u)int32_t from within a write spec. 1203 * Function used internally to write an (u)int32_t from within a write spec.
1400 * 1204 *
1401 * @param cls ignored, always NULL 1205 * @param cls ignored, always NULL
diff --git a/src/util/compress.c b/src/util/compress.c
new file mode 100644
index 000000000..73fa25bd9
--- /dev/null
+++ b/src/util/compress.c
@@ -0,0 +1,91 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 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
21/**
22 * @file util/compress.c
23 * @brief Simple (de)compression logic
24 * @author Philipp Toelke
25 * @author Martin Schanzenbach
26 */
27
28#include "platform.h"
29#include "gnunet_util_lib.h"
30#include <zlib.h>
31
32int
33GNUNET_try_compression (const char *data,
34 size_t old_size,
35 char **result,
36 size_t *new_size)
37{
38 char *tmp;
39 uLongf dlen;
40
41 *result = NULL;
42 *new_size = 0;
43#ifdef compressBound
44 dlen = compressBound (old_size);
45#else
46 dlen = old_size + (old_size / 100) + 20;
47 /* documentation says 100.1% oldSize + 12 bytes, but we
48 * should be able to overshoot by more to be safe */
49#endif
50 tmp = GNUNET_malloc (dlen);
51 if (Z_OK ==
52 compress2 ((Bytef *) tmp,
53 &dlen,
54 (const Bytef *) data,
55 old_size, 9))
56 {
57 if (dlen < old_size)
58 {
59 *result = tmp;
60 *new_size = dlen;
61 return GNUNET_YES;
62 }
63 }
64 GNUNET_free (tmp);
65 return GNUNET_NO;
66}
67
68
69char *
70GNUNET_decompress (const char *input,
71 size_t input_size,
72 size_t output_size)
73{
74 char *output;
75 uLongf olen;
76
77 olen = output_size;
78 output = GNUNET_malloc (olen);
79 if (Z_OK ==
80 uncompress ((Bytef *) output,
81 &olen,
82 (const Bytef *) input,
83 input_size))
84 return output;
85 GNUNET_free (output);
86 return NULL;
87}
88
89
90
91/* end of compress.c */
diff --git a/src/util/container_meta_data.c b/src/util/container_meta_data.c
deleted file mode 100644
index b5b457291..000000000
--- a/src/util/container_meta_data.c
+++ /dev/null
@@ -1,1122 +0,0 @@
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
21/**
22 * @file util/container_meta_data.c
23 * @brief Storing of meta data
24 * @author Christian Grothoff
25 */
26
27
28#include "platform.h"
29#include "gnunet_util_lib.h"
30#if HAVE_EXTRACTOR_H
31#include <extractor.h>
32#endif
33#include <zlib.h>
34
35#define LOG(kind, ...) GNUNET_log_from (kind, "util-container-meta-data", \
36 __VA_ARGS__)
37
38
39/**
40 * Try to compress the given block of data using libz. Only returns
41 * the compressed block if compression worked and the new block is
42 * actually smaller. Decompress using #GNUNET_decompress().
43 *
44 * @param data block to compress; if compression
45 * resulted in a smaller block, the first
46 * bytes of data are updated to the compressed
47 * data
48 * @param old_size number of bytes in data
49 * @param[out] result set to the compressed data, if compression worked
50 * @param[out] new_size set to size of result, if compression worked
51 * @return #GNUNET_YES if compression reduce the size,
52 * #GNUNET_NO if compression did not help
53 */
54int
55GNUNET_try_compression (const char *data,
56 size_t old_size,
57 char **result,
58 size_t *new_size)
59{
60 char *tmp;
61 uLongf dlen;
62
63 *result = NULL;
64 *new_size = 0;
65#ifdef compressBound
66 dlen = compressBound (old_size);
67#else
68 dlen = old_size + (old_size / 100) + 20;
69 /* documentation says 100.1% oldSize + 12 bytes, but we
70 * should be able to overshoot by more to be safe */
71#endif
72 tmp = GNUNET_malloc (dlen);
73 if (Z_OK ==
74 compress2 ((Bytef *) tmp,
75 &dlen,
76 (const Bytef *) data,
77 old_size, 9))
78 {
79 if (dlen < old_size)
80 {
81 *result = tmp;
82 *new_size = dlen;
83 return GNUNET_YES;
84 }
85 }
86 GNUNET_free (tmp);
87 return GNUNET_NO;
88}
89
90
91/**
92 * Decompress input, return the decompressed data as output. Dual to
93 * #GNUNET_try_compression(). Caller must set @a output_size to the
94 * number of bytes that were originally compressed.
95 *
96 * @param input compressed data
97 * @param input_size number of bytes in input
98 * @param output_size expected size of the output
99 * @return NULL on error, buffer of @a output_size decompressed bytes otherwise
100 */
101char *
102GNUNET_decompress (const char *input,
103 size_t input_size,
104 size_t output_size)
105{
106 char *output;
107 uLongf olen;
108
109 olen = output_size;
110 output = GNUNET_malloc (olen);
111 if (Z_OK ==
112 uncompress ((Bytef *) output,
113 &olen,
114 (const Bytef *) input,
115 input_size))
116 return output;
117 GNUNET_free (output);
118 return NULL;
119}
120
121
122/**
123 * Meta data item.
124 */
125struct MetaItem
126{
127 /**
128 * This is a doubly linked list.
129 */
130 struct MetaItem *next;
131
132 /**
133 * This is a doubly linked list.
134 */
135 struct MetaItem *prev;
136
137 /**
138 * Name of the extracting plugin.
139 */
140 char *plugin_name;
141
142 /**
143 * Mime-type of data.
144 */
145 char *mime_type;
146
147 /**
148 * The actual meta data.
149 */
150 char *data;
151
152 /**
153 * Number of bytes in 'data'.
154 */
155 size_t data_size;
156
157 /**
158 * Type of the meta data.
159 */
160 enum EXTRACTOR_MetaType type;
161
162 /**
163 * Format of the meta data.
164 */
165 enum EXTRACTOR_MetaFormat format;
166};
167
168/**
169 * Meta data to associate with a file, directory or namespace.
170 */
171struct GNUNET_CONTAINER_MetaData
172{
173 /**
174 * Head of linked list of the meta data items.
175 */
176 struct MetaItem *items_head;
177
178 /**
179 * Tail of linked list of the meta data items.
180 */
181 struct MetaItem *items_tail;
182
183 /**
184 * Complete serialized and compressed buffer of the items.
185 * NULL if we have not computed that buffer yet.
186 */
187 char *sbuf;
188
189 /**
190 * Number of bytes in 'sbuf'. 0 if the buffer is stale.
191 */
192 size_t sbuf_size;
193
194 /**
195 * Number of items in the linked list.
196 */
197 unsigned int item_count;
198};
199
200
201/**
202 * Create a fresh struct CONTAINER_MetaData token.
203 *
204 * @return empty meta-data container
205 */
206struct GNUNET_CONTAINER_MetaData *
207GNUNET_CONTAINER_meta_data_create ()
208{
209 return GNUNET_new (struct GNUNET_CONTAINER_MetaData);
210}
211
212
213/**
214 * Free meta data item.
215 *
216 * @param mi item to free
217 */
218static void
219meta_item_free (struct MetaItem *mi)
220{
221 GNUNET_free (mi->plugin_name);
222 GNUNET_free (mi->mime_type);
223 GNUNET_free (mi->data);
224 GNUNET_free (mi);
225}
226
227
228/**
229 * The meta data has changed, invalidate its serialization
230 * buffer.
231 *
232 * @param md meta data that changed
233 */
234static void
235invalidate_sbuf (struct GNUNET_CONTAINER_MetaData *md)
236{
237 if (NULL == md->sbuf)
238 return;
239 GNUNET_free (md->sbuf);
240 md->sbuf = NULL;
241 md->sbuf_size = 0;
242}
243
244
245void
246GNUNET_CONTAINER_meta_data_destroy (struct GNUNET_CONTAINER_MetaData *md)
247{
248 struct MetaItem *pos;
249
250 if (NULL == md)
251 return;
252 while (NULL != (pos = md->items_head))
253 {
254 GNUNET_CONTAINER_DLL_remove (md->items_head, md->items_tail, pos);
255 meta_item_free (pos);
256 }
257 GNUNET_free (md->sbuf);
258 GNUNET_free (md);
259}
260
261
262void
263GNUNET_CONTAINER_meta_data_clear (struct GNUNET_CONTAINER_MetaData *md)
264{
265 struct MetaItem *mi;
266
267 if (NULL == md)
268 return;
269 while (NULL != (mi = md->items_head))
270 {
271 GNUNET_CONTAINER_DLL_remove (md->items_head, md->items_tail, mi);
272 meta_item_free (mi);
273 }
274 GNUNET_free (md->sbuf);
275 memset (md, 0, sizeof(struct GNUNET_CONTAINER_MetaData));
276}
277
278
279int
280GNUNET_CONTAINER_meta_data_test_equal (const struct GNUNET_CONTAINER_MetaData
281 *md1,
282 const struct GNUNET_CONTAINER_MetaData
283 *md2)
284{
285 struct MetaItem *i;
286 struct MetaItem *j;
287 int found;
288
289 if (md1 == md2)
290 return GNUNET_YES;
291 if (md1->item_count != md2->item_count)
292 return GNUNET_NO;
293 for (i = md1->items_head; NULL != i; i = i->next)
294 {
295 found = GNUNET_NO;
296 for (j = md2->items_head; NULL != j; j = j->next)
297 {
298 if ((i->type == j->type) && (i->format == j->format) &&
299 (i->data_size == j->data_size) &&
300 (0 == memcmp (i->data, j->data, i->data_size)))
301 {
302 found = GNUNET_YES;
303 break;
304 }
305 if (j->data_size < i->data_size)
306 break; /* elements are sorted by (decreasing) size... */
307 }
308 if (GNUNET_NO == found)
309 return GNUNET_NO;
310 }
311 return GNUNET_YES;
312}
313
314
315/**
316 * Extend metadata. Note that the list of meta data items is
317 * sorted by size (largest first).
318 *
319 * @param md metadata to extend
320 * @param plugin_name name of the plugin that produced this value;
321 * special values can be used (e.g. '&lt;zlib&gt;' for zlib being
322 * used in the main libextractor library and yielding
323 * meta data).
324 * @param type libextractor-type describing the meta data
325 * @param format basic format information about data
326 * @param data_mime_type mime-type of data (not of the original file);
327 * can be NULL (if mime-type is not known)
328 * @param data actual meta-data found
329 * @param data_size number of bytes in @a data
330 * @return #GNUNET_OK on success, #GNUNET_SYSERR if this entry already exists
331 * data_mime_type and plugin_name are not considered for "exists" checks
332 */
333int
334GNUNET_CONTAINER_meta_data_insert (struct GNUNET_CONTAINER_MetaData *md,
335 const char *plugin_name,
336 enum EXTRACTOR_MetaType type,
337 enum EXTRACTOR_MetaFormat format,
338 const char *data_mime_type, const char *data,
339 size_t data_size)
340{
341 struct MetaItem *pos;
342 struct MetaItem *mi;
343 char *p;
344
345 if ((EXTRACTOR_METAFORMAT_UTF8 == format) ||
346 (EXTRACTOR_METAFORMAT_C_STRING == format))
347 GNUNET_break ('\0' == data[data_size - 1]);
348
349 for (pos = md->items_head; NULL != pos; pos = pos->next)
350 {
351 if (pos->data_size < data_size)
352 break; /* elements are sorted by size in the list */
353 if ((pos->type == type) && (pos->data_size == data_size) &&
354 (0 == memcmp (pos->data, data, data_size)))
355 {
356 if ((NULL == pos->mime_type) && (NULL != data_mime_type))
357 {
358 pos->mime_type = GNUNET_strdup (data_mime_type);
359 invalidate_sbuf (md);
360 }
361 if ((EXTRACTOR_METAFORMAT_C_STRING == pos->format) &&
362 (EXTRACTOR_METAFORMAT_UTF8 == format))
363 {
364 pos->format = EXTRACTOR_METAFORMAT_UTF8;
365 invalidate_sbuf (md);
366 }
367 return GNUNET_SYSERR;
368 }
369 }
370 md->item_count++;
371 mi = GNUNET_new (struct MetaItem);
372 mi->type = type;
373 mi->format = format;
374 mi->data_size = data_size;
375 if (NULL == pos)
376 GNUNET_CONTAINER_DLL_insert_tail (md->items_head,
377 md->items_tail,
378 mi);
379 else
380 GNUNET_CONTAINER_DLL_insert_after (md->items_head,
381 md->items_tail,
382 pos->prev,
383 mi);
384 mi->mime_type =
385 (NULL == data_mime_type) ? NULL : GNUNET_strdup (data_mime_type);
386 mi->plugin_name = (NULL == plugin_name) ? NULL : GNUNET_strdup (plugin_name);
387 mi->data = GNUNET_malloc (data_size);
388 GNUNET_memcpy (mi->data, data, data_size);
389 /* change all dir separators to POSIX style ('/') */
390 if ((EXTRACTOR_METATYPE_FILENAME == type) ||
391 (EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME == type))
392 {
393 p = mi->data;
394 while (('\0' != *p) && (p < mi->data + data_size))
395 {
396 if ('\\' == *p)
397 *p = '/';
398 p++;
399 }
400 }
401 invalidate_sbuf (md);
402 return GNUNET_OK;
403}
404
405
406/**
407 * Merge given meta data.
408 *
409 * @param cls the `struct GNUNET_CONTAINER_MetaData` to merge into
410 * @param plugin_name name of the plugin that produced this value;
411 * special values can be used (e.g. '&lt;zlib&gt;' for zlib being
412 * used in the main libextractor library and yielding
413 * meta data).
414 * @param type libextractor-type describing the meta data
415 * @param format basic format information about data
416 * @param data_mime_type mime-type of data (not of the original file);
417 * can be NULL (if mime-type is not known)
418 * @param data actual meta-data found
419 * @param data_size number of bytes in @a data
420 * @return 0 (to continue)
421 */
422static int
423merge_helper (void *cls, const char *plugin_name, enum EXTRACTOR_MetaType type,
424 enum EXTRACTOR_MetaFormat format, const char *data_mime_type,
425 const char *data, size_t data_size)
426{
427 struct GNUNET_CONTAINER_MetaData *md = cls;
428
429 (void) GNUNET_CONTAINER_meta_data_insert (md, plugin_name, type, format,
430 data_mime_type, data, data_size);
431 return 0;
432}
433
434
435void
436GNUNET_CONTAINER_meta_data_merge (struct GNUNET_CONTAINER_MetaData *md,
437 const struct GNUNET_CONTAINER_MetaData *in)
438{
439 GNUNET_CONTAINER_meta_data_iterate (in, &merge_helper, md);
440}
441
442
443int
444GNUNET_CONTAINER_meta_data_delete (struct GNUNET_CONTAINER_MetaData *md,
445 enum EXTRACTOR_MetaType type,
446 const char *data, size_t data_size)
447{
448 struct MetaItem *pos;
449
450 for (pos = md->items_head; NULL != pos; pos = pos->next)
451 {
452 if (pos->data_size < data_size)
453 break; /* items are sorted by (decreasing) size */
454 if ((pos->type == type) &&
455 ((NULL == data) ||
456 ((pos->data_size == data_size) &&
457 (0 == memcmp (pos->data, data, data_size)))))
458 {
459 GNUNET_CONTAINER_DLL_remove (md->items_head, md->items_tail, pos);
460 meta_item_free (pos);
461 md->item_count--;
462 invalidate_sbuf (md);
463 return GNUNET_OK;
464 }
465 }
466 return GNUNET_SYSERR;
467}
468
469
470void
471GNUNET_CONTAINER_meta_data_add_publication_date (struct
472 GNUNET_CONTAINER_MetaData *md)
473{
474 const char *dat;
475 struct GNUNET_TIME_Absolute t;
476
477 t = GNUNET_TIME_absolute_get ();
478 GNUNET_CONTAINER_meta_data_delete (md,
479 EXTRACTOR_METATYPE_PUBLICATION_DATE,
480 NULL, 0);
481 dat = GNUNET_STRINGS_absolute_time_to_string (t);
482 GNUNET_CONTAINER_meta_data_insert (md, "<gnunet>",
483 EXTRACTOR_METATYPE_PUBLICATION_DATE,
484 EXTRACTOR_METAFORMAT_UTF8, "text/plain",
485 dat, strlen (dat) + 1);
486}
487
488
489/**
490 * Iterate over MD entries.
491 *
492 * @param md metadata to inspect
493 * @param iter function to call on each entry
494 * @param iter_cls closure for iterator
495 * @return number of entries
496 */
497int
498GNUNET_CONTAINER_meta_data_iterate (const struct GNUNET_CONTAINER_MetaData *md,
499 EXTRACTOR_MetaDataProcessor iter,
500 void *iter_cls)
501{
502 struct MetaItem *pos;
503
504 if (NULL == md)
505 return 0;
506 if (NULL == iter)
507 return md->item_count;
508 for (pos = md->items_head; NULL != pos; pos = pos->next)
509 if (0 !=
510 iter (iter_cls, pos->plugin_name, pos->type, pos->format,
511 pos->mime_type, pos->data, pos->data_size))
512 return md->item_count;
513 return md->item_count;
514}
515
516
517char *
518GNUNET_CONTAINER_meta_data_get_by_type (const struct
519 GNUNET_CONTAINER_MetaData *md,
520 enum EXTRACTOR_MetaType type)
521{
522 struct MetaItem *pos;
523
524 if (NULL == md)
525 return NULL;
526 for (pos = md->items_head; NULL != pos; pos = pos->next)
527 if ((type == pos->type) &&
528 ((pos->format == EXTRACTOR_METAFORMAT_UTF8) ||
529 (pos->format == EXTRACTOR_METAFORMAT_C_STRING)))
530 return GNUNET_strdup (pos->data);
531 return NULL;
532}
533
534
535char *
536GNUNET_CONTAINER_meta_data_get_first_by_types (const struct
537 GNUNET_CONTAINER_MetaData *md,
538 ...)
539{
540 char *ret;
541 va_list args;
542 int type;
543
544 if (NULL == md)
545 return NULL;
546 ret = NULL;
547 va_start (args, md);
548 while (1)
549 {
550 type = va_arg (args, int);
551 if (-1 == type)
552 break;
553 if (NULL != (ret = GNUNET_CONTAINER_meta_data_get_by_type (md, type)))
554 break;
555 }
556 va_end (args);
557 return ret;
558}
559
560
561/**
562 * Get a thumbnail from the meta-data (if present).
563 *
564 * @param md metadata to get the thumbnail from
565 * @param thumb will be set to the thumbnail data. Must be
566 * freed by the caller!
567 * @return number of bytes in thumbnail, 0 if not available
568 */
569size_t
570GNUNET_CONTAINER_meta_data_get_thumbnail (const struct GNUNET_CONTAINER_MetaData
571 *md, unsigned char **thumb)
572{
573 struct MetaItem *pos;
574 struct MetaItem *match;
575
576 if (NULL == md)
577 return 0;
578 match = NULL;
579 for (pos = md->items_head; NULL != pos; pos = pos->next)
580 {
581 if ((NULL != pos->mime_type) &&
582 (0 == strncasecmp ("image/", pos->mime_type, strlen ("image/"))) &&
583 (EXTRACTOR_METAFORMAT_BINARY == pos->format))
584 {
585 if (NULL == match)
586 match = pos;
587 else if ((match->type != EXTRACTOR_METATYPE_THUMBNAIL) &&
588 (pos->type == EXTRACTOR_METATYPE_THUMBNAIL))
589 match = pos;
590 }
591 }
592 if ((NULL == match) || (0 == match->data_size))
593 return 0;
594 *thumb = GNUNET_malloc (match->data_size);
595 GNUNET_memcpy (*thumb, match->data, match->data_size);
596 return match->data_size;
597}
598
599
600/**
601 * Duplicate a `struct GNUNET_CONTAINER_MetaData`.
602 *
603 * @param md what to duplicate
604 * @return duplicate meta-data container
605 */
606struct GNUNET_CONTAINER_MetaData *
607GNUNET_CONTAINER_meta_data_duplicate (const struct GNUNET_CONTAINER_MetaData
608 *md)
609{
610 struct GNUNET_CONTAINER_MetaData *ret;
611 struct MetaItem *pos;
612
613 if (NULL == md)
614 return NULL;
615 ret = GNUNET_CONTAINER_meta_data_create ();
616 for (pos = md->items_tail; NULL != pos; pos = pos->prev)
617 GNUNET_CONTAINER_meta_data_insert (ret, pos->plugin_name, pos->type,
618 pos->format, pos->mime_type, pos->data,
619 pos->data_size);
620 return ret;
621}
622
623
624/**
625 * Flag in 'version' that indicates compressed meta-data.
626 */
627#define HEADER_COMPRESSED 0x80000000
628
629
630/**
631 * Bits in 'version' that give the version number.
632 */
633#define HEADER_VERSION_MASK 0x7FFFFFFF
634
635
636/**
637 * Header for serialized meta data.
638 */
639struct MetaDataHeader
640{
641 /**
642 * The version of the MD serialization. The highest bit is used to
643 * indicate compression.
644 *
645 * Version 0 is traditional (pre-0.9) meta data (unsupported)
646 * Version is 1 for a NULL pointer
647 * Version 2 is for 0.9.x (and possibly higher)
648 * Other version numbers are not yet defined.
649 */
650 uint32_t version;
651
652 /**
653 * How many MD entries are there?
654 */
655 uint32_t entries;
656
657 /**
658 * Size of the decompressed meta data.
659 */
660 uint32_t size;
661
662 /**
663 * This is followed by 'entries' values of type 'struct MetaDataEntry'
664 * and then by 'entry' plugin names, mime-types and data blocks
665 * as specified in those meta data entries.
666 */
667};
668
669
670/**
671 * Entry of serialized meta data.
672 */
673struct MetaDataEntry
674{
675 /**
676 * Meta data type. Corresponds to an 'enum EXTRACTOR_MetaType'
677 */
678 uint32_t type;
679
680 /**
681 * Meta data format. Corresponds to an 'enum EXTRACTOR_MetaFormat'
682 */
683 uint32_t format;
684
685 /**
686 * Number of bytes of meta data.
687 */
688 uint32_t data_size;
689
690 /**
691 * Number of bytes in the plugin name including 0-terminator. 0 for NULL.
692 */
693 uint32_t plugin_name_len;
694
695 /**
696 * Number of bytes in the mime type including 0-terminator. 0 for NULL.
697 */
698 uint32_t mime_type_len;
699};
700
701
702/**
703 * Serialize meta-data to target.
704 *
705 * @param md metadata to serialize
706 * @param target where to write the serialized metadata;
707 * *target can be NULL, in which case memory is allocated
708 * @param max maximum number of bytes available in target
709 * @param opt is it ok to just write SOME of the
710 * meta-data to match the size constraint,
711 * possibly discarding some data?
712 * @return number of bytes written on success,
713 * #GNUNET_SYSERR on error (typically: not enough
714 * space)
715 */
716ssize_t
717GNUNET_CONTAINER_meta_data_serialize (const struct GNUNET_CONTAINER_MetaData
718 *md, char **target, size_t max,
719 enum
720 GNUNET_CONTAINER_MetaDataSerializationOptions
721 opt)
722{
723 struct GNUNET_CONTAINER_MetaData *vmd;
724 struct MetaItem *pos;
725 struct MetaDataHeader ihdr;
726 struct MetaDataHeader *hdr;
727 struct MetaDataEntry *ent;
728 char *dst;
729 unsigned int i;
730 uint64_t msize;
731 size_t off;
732 char *mdata;
733 char *cdata;
734 size_t mlen;
735 size_t plen;
736 size_t size;
737 size_t left;
738 size_t clen;
739 size_t rlen;
740 int comp;
741
742 if (max < sizeof(struct MetaDataHeader))
743 return GNUNET_SYSERR; /* far too small */
744 if (NULL == md)
745 return 0;
746
747 if (NULL != md->sbuf)
748 {
749 /* try to use serialization cache */
750 if (md->sbuf_size <= max)
751 {
752 if (NULL == *target)
753 *target = GNUNET_malloc (md->sbuf_size);
754 GNUNET_memcpy (*target, md->sbuf, md->sbuf_size);
755 return md->sbuf_size;
756 }
757 if (0 == (opt & GNUNET_CONTAINER_META_DATA_SERIALIZE_PART))
758 return GNUNET_SYSERR; /* can say that this will fail */
759 /* need to compute a partial serialization, sbuf useless ... */
760 }
761 dst = NULL;
762 msize = 0;
763 for (pos = md->items_tail; NULL != pos; pos = pos->prev)
764 {
765 msize += sizeof(struct MetaDataEntry);
766 msize += pos->data_size;
767 if (NULL != pos->plugin_name)
768 msize += strlen (pos->plugin_name) + 1;
769 if (NULL != pos->mime_type)
770 msize += strlen (pos->mime_type) + 1;
771 }
772 size = (size_t) msize;
773 if (size != msize)
774 {
775 GNUNET_break (0); /* integer overflow */
776 return GNUNET_SYSERR;
777 }
778 if (size >= GNUNET_MAX_MALLOC_CHECKED)
779 {
780 /* too large to be processed */
781 return GNUNET_SYSERR;
782 }
783 ent = GNUNET_malloc (size);
784 mdata = (char *) &ent[md->item_count];
785 off = size - (md->item_count * sizeof(struct MetaDataEntry));
786 i = 0;
787 for (pos = md->items_head; NULL != pos; pos = pos->next)
788 {
789 ent[i].type = htonl ((uint32_t) pos->type);
790 ent[i].format = htonl ((uint32_t) pos->format);
791 ent[i].data_size = htonl ((uint32_t) pos->data_size);
792 if (NULL == pos->plugin_name)
793 plen = 0;
794 else
795 plen = strlen (pos->plugin_name) + 1;
796 ent[i].plugin_name_len = htonl ((uint32_t) plen);
797 if (NULL == pos->mime_type)
798 mlen = 0;
799 else
800 mlen = strlen (pos->mime_type) + 1;
801 ent[i].mime_type_len = htonl ((uint32_t) mlen);
802 off -= pos->data_size;
803 if ((EXTRACTOR_METAFORMAT_UTF8 == pos->format) ||
804 (EXTRACTOR_METAFORMAT_C_STRING == pos->format))
805 GNUNET_break ('\0' == pos->data[pos->data_size - 1]);
806 GNUNET_memcpy (&mdata[off], pos->data, pos->data_size);
807 off -= plen;
808 if (NULL != pos->plugin_name)
809 GNUNET_memcpy (&mdata[off], pos->plugin_name, plen);
810 off -= mlen;
811 if (NULL != pos->mime_type)
812 GNUNET_memcpy (&mdata[off], pos->mime_type, mlen);
813 i++;
814 }
815 GNUNET_assert (0 == off);
816
817 clen = 0;
818 cdata = NULL;
819 left = size;
820 i = 0;
821 for (pos = md->items_head; NULL != pos; pos = pos->next)
822 {
823 comp = GNUNET_NO;
824 if (0 == (opt & GNUNET_CONTAINER_META_DATA_SERIALIZE_NO_COMPRESS))
825 comp = GNUNET_try_compression ((const char *) &ent[i],
826 left,
827 &cdata,
828 &clen);
829
830 if ((NULL == md->sbuf) && (0 == i))
831 {
832 /* fill 'sbuf'; this "modifies" md, but since this is only
833 * an internal cache we will cast away the 'const' instead
834 * of making the API look strange. */
835 vmd = (struct GNUNET_CONTAINER_MetaData *) md;
836 hdr = GNUNET_malloc (left + sizeof(struct MetaDataHeader));
837 hdr->size = htonl (left);
838 hdr->entries = htonl (md->item_count);
839 if (GNUNET_YES == comp)
840 {
841 GNUNET_assert (clen < left);
842 hdr->version = htonl (2 | HEADER_COMPRESSED);
843 GNUNET_memcpy (&hdr[1], cdata, clen);
844 vmd->sbuf_size = clen + sizeof(struct MetaDataHeader);
845 }
846 else
847 {
848 hdr->version = htonl (2);
849 GNUNET_memcpy (&hdr[1], &ent[0], left);
850 vmd->sbuf_size = left + sizeof(struct MetaDataHeader);
851 }
852 vmd->sbuf = (char *) hdr;
853 }
854
855 if (((left + sizeof(struct MetaDataHeader)) <= max) ||
856 ((GNUNET_YES == comp) && (clen <= max)))
857 {
858 /* success, this now fits! */
859 if (GNUNET_YES == comp)
860 {
861 if (NULL == dst)
862 dst = GNUNET_malloc (clen + sizeof(struct MetaDataHeader));
863 hdr = (struct MetaDataHeader *) dst;
864 hdr->version = htonl (2 | HEADER_COMPRESSED);
865 hdr->size = htonl (left);
866 hdr->entries = htonl (md->item_count - i);
867 GNUNET_memcpy (&dst[sizeof(struct MetaDataHeader)], cdata, clen);
868 GNUNET_free (cdata);
869 cdata = NULL;
870 GNUNET_free (ent);
871 rlen = clen + sizeof(struct MetaDataHeader);
872 }
873 else
874 {
875 if (NULL == dst)
876 dst = GNUNET_malloc (left + sizeof(struct MetaDataHeader));
877 hdr = (struct MetaDataHeader *) dst;
878 hdr->version = htonl (2);
879 hdr->entries = htonl (md->item_count - i);
880 hdr->size = htonl (left);
881 GNUNET_memcpy (&dst[sizeof(struct MetaDataHeader)], &ent[i], left);
882 GNUNET_free (ent);
883 rlen = left + sizeof(struct MetaDataHeader);
884 }
885 if (NULL != *target)
886 {
887 if (GNUNET_YES == comp)
888 GNUNET_memcpy (*target, dst, clen + sizeof(struct MetaDataHeader));
889 else
890 GNUNET_memcpy (*target, dst, left + sizeof(struct MetaDataHeader));
891 GNUNET_free (dst);
892 }
893 else
894 {
895 *target = dst;
896 }
897 return rlen;
898 }
899
900 if (0 == (opt & GNUNET_CONTAINER_META_DATA_SERIALIZE_PART))
901 {
902 /* does not fit! */
903 GNUNET_free (ent);
904 if (NULL != cdata)
905 GNUNET_free (cdata);
906 cdata = NULL;
907 return GNUNET_SYSERR;
908 }
909
910 /* next iteration: ignore the corresponding meta data at the
911 * end and try again without it */
912 left -= sizeof(struct MetaDataEntry);
913 left -= pos->data_size;
914 if (NULL != pos->plugin_name)
915 left -= strlen (pos->plugin_name) + 1;
916 if (NULL != pos->mime_type)
917 left -= strlen (pos->mime_type) + 1;
918
919 if (NULL != cdata)
920 GNUNET_free (cdata);
921 cdata = NULL;
922 i++;
923 }
924 GNUNET_free (ent);
925
926 /* nothing fit, only write header! */
927 ihdr.version = htonl (2);
928 ihdr.entries = htonl (0);
929 ihdr.size = htonl (0);
930 if (NULL == *target)
931 *target = (char *) GNUNET_new (struct MetaDataHeader);
932 GNUNET_memcpy (*target, &ihdr, sizeof(struct MetaDataHeader));
933 return sizeof(struct MetaDataHeader);
934}
935
936
937ssize_t
938GNUNET_CONTAINER_meta_data_get_serialized_size (const struct
939 GNUNET_CONTAINER_MetaData *md)
940{
941 ssize_t ret;
942 char *ptr;
943
944 if (NULL != md->sbuf)
945 return md->sbuf_size;
946 ptr = NULL;
947 ret =
948 GNUNET_CONTAINER_meta_data_serialize (md, &ptr, GNUNET_MAX_MALLOC_CHECKED,
949 GNUNET_CONTAINER_META_DATA_SERIALIZE_FULL);
950 if (-1 != ret)
951 GNUNET_free (ptr);
952 return ret;
953}
954
955
956/**
957 * Deserialize meta-data. Initializes md.
958 *
959 * @param input buffer with the serialized metadata
960 * @param size number of bytes available in input
961 * @return MD on success, NULL on error (i.e.
962 * bad format)
963 */
964struct GNUNET_CONTAINER_MetaData *
965GNUNET_CONTAINER_meta_data_deserialize (const char *input, size_t size)
966{
967 struct GNUNET_CONTAINER_MetaData *md;
968 struct MetaDataHeader hdr;
969 struct MetaDataEntry ent;
970 uint32_t ic;
971 uint32_t i;
972 char *data;
973 const char *cdata;
974 uint32_t version;
975 uint32_t dataSize;
976 int compressed;
977 size_t left;
978 uint32_t mlen;
979 uint32_t plen;
980 uint32_t dlen;
981 const char *mdata;
982 const char *meta_data;
983 const char *plugin_name;
984 const char *mime_type;
985 enum EXTRACTOR_MetaFormat format;
986
987 if (size < sizeof(struct MetaDataHeader))
988 return NULL;
989 GNUNET_memcpy (&hdr, input, sizeof(struct MetaDataHeader));
990 version = ntohl (hdr.version) & HEADER_VERSION_MASK;
991 compressed = (ntohl (hdr.version) & HEADER_COMPRESSED) != 0;
992
993 if (1 == version)
994 return NULL; /* null pointer */
995 if (2 != version)
996 {
997 GNUNET_break_op (0); /* unsupported version */
998 return NULL;
999 }
1000
1001 ic = ntohl (hdr.entries);
1002 dataSize = ntohl (hdr.size);
1003 if (((sizeof(struct MetaDataEntry) * ic) > dataSize) ||
1004 ((0 != ic) &&
1005 (dataSize / ic < sizeof(struct MetaDataEntry))))
1006 {
1007 GNUNET_break_op (0);
1008 return NULL;
1009 }
1010
1011 if (compressed)
1012 {
1013 if (dataSize >= GNUNET_MAX_MALLOC_CHECKED)
1014 {
1015 /* make sure we don't blow our memory limit because of a mal-formed
1016 * message... */
1017 GNUNET_break_op (0);
1018 return NULL;
1019 }
1020 data =
1021 GNUNET_decompress ((const char *) &input[sizeof(struct MetaDataHeader)],
1022 size - sizeof(struct MetaDataHeader),
1023 dataSize);
1024 if (NULL == data)
1025 {
1026 GNUNET_break_op (0);
1027 return NULL;
1028 }
1029 cdata = data;
1030 }
1031 else
1032 {
1033 data = NULL;
1034 cdata = (const char *) &input[sizeof(struct MetaDataHeader)];
1035 if (dataSize != size - sizeof(struct MetaDataHeader))
1036 {
1037 GNUNET_break_op (0);
1038 return NULL;
1039 }
1040 }
1041
1042 md = GNUNET_CONTAINER_meta_data_create ();
1043 left = dataSize - ic * sizeof(struct MetaDataEntry);
1044 mdata = &cdata[ic * sizeof(struct MetaDataEntry)];
1045 for (i = 0; i < ic; i++)
1046 {
1047 GNUNET_memcpy (&ent, &cdata[i * sizeof(struct MetaDataEntry)],
1048 sizeof(struct MetaDataEntry));
1049 format = (enum EXTRACTOR_MetaFormat) ntohl (ent.format);
1050 if ((EXTRACTOR_METAFORMAT_UTF8 != format) &&
1051 (EXTRACTOR_METAFORMAT_C_STRING != format) &&
1052 (EXTRACTOR_METAFORMAT_BINARY != format))
1053 {
1054 GNUNET_break_op (0);
1055 break;
1056 }
1057 dlen = ntohl (ent.data_size);
1058 plen = ntohl (ent.plugin_name_len);
1059 mlen = ntohl (ent.mime_type_len);
1060 if (dlen > left)
1061 {
1062 GNUNET_break_op (0);
1063 break;
1064 }
1065 left -= dlen;
1066 meta_data = &mdata[left];
1067 if ((EXTRACTOR_METAFORMAT_UTF8 == format) ||
1068 (EXTRACTOR_METAFORMAT_C_STRING == format))
1069 {
1070 if (0 == dlen)
1071 {
1072 GNUNET_break_op (0);
1073 break;
1074 }
1075 if ('\0' != meta_data[dlen - 1])
1076 {
1077 GNUNET_break_op (0);
1078 break;
1079 }
1080 }
1081 if (plen > left)
1082 {
1083 GNUNET_break_op (0);
1084 break;
1085 }
1086 left -= plen;
1087 if ((plen > 0) && ('\0' != mdata[left + plen - 1]))
1088 {
1089 GNUNET_break_op (0);
1090 break;
1091 }
1092 if (0 == plen)
1093 plugin_name = NULL;
1094 else
1095 plugin_name = &mdata[left];
1096
1097 if (mlen > left)
1098 {
1099 GNUNET_break_op (0);
1100 break;
1101 }
1102 left -= mlen;
1103 if ((mlen > 0) && ('\0' != mdata[left + mlen - 1]))
1104 {
1105 GNUNET_break_op (0);
1106 break;
1107 }
1108 if (0 == mlen)
1109 mime_type = NULL;
1110 else
1111 mime_type = &mdata[left];
1112 GNUNET_CONTAINER_meta_data_insert (md, plugin_name,
1113 (enum EXTRACTOR_MetaType)
1114 ntohl (ent.type), format, mime_type,
1115 meta_data, dlen);
1116 }
1117 GNUNET_free (data);
1118 return md;
1119}
1120
1121
1122/* end of container_meta_data.c */
diff --git a/src/util/crypto_crc.c b/src/util/crypto_crc.c
index d33a19db2..9328f2b84 100644
--- a/src/util/crypto_crc.c
+++ b/src/util/crypto_crc.c
@@ -84,7 +84,7 @@ crc_init ()
84 * property of detecting all burst errors of length 32 bits or less. 84 * property of detecting all burst errors of length 32 bits or less.
85 */ 85 */
86static GNUNET_uLong 86static GNUNET_uLong
87crc32 (GNUNET_uLong crc, const char *buf, size_t len) 87gn_crc32 (GNUNET_uLong crc, const char *buf, size_t len)
88{ 88{
89 crc_init (); 89 crc_init ();
90 GNUNET_assert (crc_table[255] != 0); 90 GNUNET_assert (crc_table[255] != 0);
@@ -100,8 +100,8 @@ GNUNET_CRYPTO_crc32_n (const void *buf, size_t len)
100{ 100{
101 GNUNET_uLong crc; 101 GNUNET_uLong crc;
102 102
103 crc = crc32 (0L, Z_NULL, 0); 103 crc = gn_crc32 (0L, Z_NULL, 0);
104 crc = crc32 (crc, (char *) buf, len); 104 crc = gn_crc32 (crc, (char *) buf, len);
105 return crc; 105 return crc;
106} 106}
107 107
diff --git a/src/util/test_container_meta_data.c b/src/util/test_container_meta_data.c
deleted file mode 100644
index 54b0dd100..000000000
--- a/src/util/test_container_meta_data.c
+++ /dev/null
@@ -1,376 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2003, 2004, 2006, 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
21/**
22 * @file util/test_container_meta_data.c
23 * @brief Test for container_meta_data.c
24 * @author Christian Grothoff
25 */
26
27
28#include "platform.h"
29#include "gnunet_util_lib.h"
30
31#define ABORT(m) { fprintf (stderr, "Error at %s:%d\n", __FILE__, __LINE__); \
32 if (m != NULL) GNUNET_CONTAINER_meta_data_destroy (m); \
33 return 1; }
34
35
36static int
37testMeta (int i)
38{
39 struct GNUNET_CONTAINER_MetaData *m;
40 char val[256];
41 char *sval;
42 int j;
43 unsigned int size;
44
45 m = GNUNET_CONTAINER_meta_data_create ();
46 if (GNUNET_OK !=
47 GNUNET_CONTAINER_meta_data_insert (m, "<test>", EXTRACTOR_METATYPE_TITLE,
48 EXTRACTOR_METAFORMAT_UTF8,
49 "text/plain", "TestTitle",
50 strlen ("TestTitle") + 1))
51 ABORT (m);
52 if (GNUNET_OK !=
53 GNUNET_CONTAINER_meta_data_insert (m, "<test>",
54 EXTRACTOR_METATYPE_AUTHOR_NAME,
55 EXTRACTOR_METAFORMAT_UTF8,
56 "text/plain", "TestTitle",
57 strlen ("TestTitle") + 1))
58 ABORT (m);
59 if (GNUNET_OK == GNUNET_CONTAINER_meta_data_insert (m, "<test>",
60 EXTRACTOR_METATYPE_TITLE,
61 EXTRACTOR_METAFORMAT_UTF8,
62 "text/plain",
63 "TestTitle", strlen (
64 "TestTitle") + 1)) /* dup! */
65 ABORT (m);
66 if (GNUNET_OK == GNUNET_CONTAINER_meta_data_insert (m, "<test>",
67 EXTRACTOR_METATYPE_AUTHOR_NAME,
68 EXTRACTOR_METAFORMAT_UTF8,
69 "text/plain",
70 "TestTitle", strlen (
71 "TestTitle") + 1)) /* dup! */
72 ABORT (m);
73 if (2 != GNUNET_CONTAINER_meta_data_iterate (m, NULL, NULL))
74 ABORT (m);
75 if (GNUNET_OK !=
76 GNUNET_CONTAINER_meta_data_delete (m, EXTRACTOR_METATYPE_AUTHOR_NAME,
77 "TestTitle", strlen ("TestTitle") + 1))
78 ABORT (m);
79 if (GNUNET_OK == GNUNET_CONTAINER_meta_data_delete (m,
80 EXTRACTOR_METATYPE_AUTHOR_NAME,
81 "TestTitle", strlen (
82 "TestTitle") + 1)) /* already gone */
83 ABORT (m);
84 if (1 != GNUNET_CONTAINER_meta_data_iterate (m, NULL, NULL))
85 ABORT (m);
86 if (GNUNET_OK !=
87 GNUNET_CONTAINER_meta_data_delete (m, EXTRACTOR_METATYPE_TITLE,
88 "TestTitle", strlen ("TestTitle") + 1))
89 ABORT (m);
90 if (GNUNET_OK == GNUNET_CONTAINER_meta_data_delete (m,
91 EXTRACTOR_METATYPE_TITLE,
92 "TestTitle", strlen (
93 "TestTitle") + 1)) /* already gone */
94 ABORT (m);
95 if (0 != GNUNET_CONTAINER_meta_data_iterate (m, NULL, NULL))
96 ABORT (m);
97 for (j = 0; j < i; j++)
98 {
99 GNUNET_snprintf (val, sizeof(val), "%s.%d",
100 "A teststring that should compress well.", j);
101 if (GNUNET_OK !=
102 GNUNET_CONTAINER_meta_data_insert (m, "<test>",
103 EXTRACTOR_METATYPE_UNKNOWN,
104 EXTRACTOR_METAFORMAT_UTF8,
105 "text/plain", val, strlen (val) + 1))
106 ABORT (m);
107 }
108 if (i != GNUNET_CONTAINER_meta_data_iterate (m, NULL, NULL))
109 ABORT (m);
110
111 size = GNUNET_CONTAINER_meta_data_get_serialized_size (m);
112 sval = NULL;
113 if (size !=
114 GNUNET_CONTAINER_meta_data_serialize (m, &sval, size,
115 GNUNET_CONTAINER_META_DATA_SERIALIZE_FULL))
116 {
117 GNUNET_free (sval);
118 ABORT (m);
119 }
120 GNUNET_CONTAINER_meta_data_destroy (m);
121 m = GNUNET_CONTAINER_meta_data_deserialize (sval, size);
122 GNUNET_free (sval);
123 if (m == NULL)
124 ABORT (m);
125 for (j = 0; j < i; j++)
126 {
127 GNUNET_snprintf (val,
128 sizeof(val),
129 "%s.%d",
130 "A teststring that should compress well.",
131 j);
132 if (GNUNET_OK !=
133 GNUNET_CONTAINER_meta_data_delete (m,
134 EXTRACTOR_METATYPE_UNKNOWN,
135 val,
136 strlen (val) + 1))
137 {
138 ABORT (m);
139 }
140 }
141 if (0 != GNUNET_CONTAINER_meta_data_iterate (m, NULL, NULL))
142 ABORT (m);
143 GNUNET_CONTAINER_meta_data_destroy (m);
144 return 0;
145}
146
147
148static int
149testMetaMore (int i)
150{
151 struct GNUNET_CONTAINER_MetaData *meta;
152 int q;
153 char txt[128];
154 char *data;
155 unsigned long long size;
156
157 meta = GNUNET_CONTAINER_meta_data_create ();
158 for (q = 0; q <= i; q++)
159 {
160 GNUNET_snprintf (txt, 128, "%u -- %u\n", i, q);
161 GNUNET_CONTAINER_meta_data_insert (meta, "<test>",
162 q
163 % 42 /* EXTRACTOR_metatype_get_max () */,
164 EXTRACTOR_METAFORMAT_UTF8, "text/plain",
165 txt, strlen (txt) + 1);
166 }
167 size = GNUNET_CONTAINER_meta_data_get_serialized_size (meta);
168 data = GNUNET_malloc (size * 4);
169 if (size !=
170 GNUNET_CONTAINER_meta_data_serialize (meta, &data, size * 4,
171 GNUNET_CONTAINER_META_DATA_SERIALIZE_FULL))
172 {
173 GNUNET_free (data);
174 ABORT (meta);
175 }
176 GNUNET_CONTAINER_meta_data_destroy (meta);
177 GNUNET_free (data);
178 return 0;
179}
180
181
182static int
183testMetaLink ()
184{
185 struct GNUNET_CONTAINER_MetaData *m;
186 char *val;
187 unsigned int size;
188
189 m = GNUNET_CONTAINER_meta_data_create ();
190 if (GNUNET_OK !=
191 GNUNET_CONTAINER_meta_data_insert (m, "<test>",
192 EXTRACTOR_METATYPE_UNKNOWN,
193 EXTRACTOR_METAFORMAT_UTF8,
194 "text/plain", "link",
195 strlen ("link") + 1))
196 ABORT (m);
197 if (GNUNET_OK !=
198 GNUNET_CONTAINER_meta_data_insert (m, "<test>",
199 EXTRACTOR_METATYPE_FILENAME,
200 EXTRACTOR_METAFORMAT_UTF8,
201 "text/plain", "lib-link.m4",
202 strlen ("lib-link.m4") + 1))
203 ABORT (m);
204 val = NULL;
205 size =
206 GNUNET_CONTAINER_meta_data_serialize (m, &val, (size_t) -1,
207 GNUNET_CONTAINER_META_DATA_SERIALIZE_FULL);
208 GNUNET_CONTAINER_meta_data_destroy (m);
209 m = GNUNET_CONTAINER_meta_data_deserialize (val, size);
210 GNUNET_free (val);
211 if (m == NULL)
212 ABORT (m);
213 GNUNET_CONTAINER_meta_data_destroy (m);
214 return 0;
215}
216
217
218static int
219check ()
220{
221 struct GNUNET_CONTAINER_MetaData *meta;
222 struct GNUNET_CONTAINER_MetaData *meta2;
223 int q;
224 int i = 100;
225 char txt[128];
226 char *str;
227 unsigned char *thumb;
228
229 meta = GNUNET_CONTAINER_meta_data_create ();
230 meta2 = GNUNET_CONTAINER_meta_data_create ();
231 for (q = 0; q <= i; q++)
232 {
233 GNUNET_snprintf (txt, 128, "%u -- %u\n", i, q);
234 GNUNET_CONTAINER_meta_data_insert (meta, "<test>",
235 EXTRACTOR_METATYPE_UNKNOWN,
236 EXTRACTOR_METAFORMAT_UTF8, "text/plain",
237 "TestTitle", strlen ("TestTitle") + 1);
238 GNUNET_CONTAINER_meta_data_insert (meta2, "<test>",
239 EXTRACTOR_METATYPE_UNKNOWN,
240 EXTRACTOR_METAFORMAT_UTF8, "text/plain",
241 "TestTitle", strlen ("TestTitle") + 1);
242 }
243
244 // check meta_data_test_equal
245 if (GNUNET_YES != GNUNET_CONTAINER_meta_data_test_equal (meta, meta2))
246 {
247 GNUNET_CONTAINER_meta_data_destroy (meta2);
248 ABORT (meta);
249 }
250
251 // check meta_data_clear
252 GNUNET_CONTAINER_meta_data_clear (meta2);
253 if (0 != GNUNET_CONTAINER_meta_data_iterate (meta2, NULL, NULL))
254 {
255 GNUNET_CONTAINER_meta_data_destroy (meta2);
256 ABORT (meta);
257 }
258 // check equal branch in meta_data_test_equal
259 if (GNUNET_YES != GNUNET_CONTAINER_meta_data_test_equal (meta, meta))
260 {
261 GNUNET_CONTAINER_meta_data_destroy (meta2);
262 ABORT (meta);
263 }
264 // check "count" branch in meta_data_test_equal
265 if (GNUNET_NO != GNUNET_CONTAINER_meta_data_test_equal (meta, meta2))
266 {
267 GNUNET_CONTAINER_meta_data_destroy (meta2);
268 ABORT (meta);
269 }
270
271 // check meta_data_add_publication_date
272 GNUNET_CONTAINER_meta_data_add_publication_date (meta2);
273
274 // check meta_data_merge
275 GNUNET_CONTAINER_meta_data_clear (meta2);
276 GNUNET_CONTAINER_meta_data_merge (meta2, meta);
277 if (100 == GNUNET_CONTAINER_meta_data_iterate (meta2, NULL, NULL))
278 {
279 GNUNET_CONTAINER_meta_data_destroy (meta2);
280 ABORT (meta);
281 }
282
283 // check meta_data_get_by_type
284 GNUNET_CONTAINER_meta_data_clear (meta2);
285 if (NULL !=
286 (str =
287 GNUNET_CONTAINER_meta_data_get_by_type (meta2,
288 EXTRACTOR_METATYPE_UNKNOWN)))
289 {
290 GNUNET_CONTAINER_meta_data_destroy (meta2);
291 GNUNET_free (str);
292 ABORT (meta);
293 }
294
295 str =
296 GNUNET_CONTAINER_meta_data_get_by_type (meta, EXTRACTOR_METATYPE_UNKNOWN);
297 GNUNET_assert (NULL != str);
298 if (str[0] != 'T')
299 {
300 GNUNET_CONTAINER_meta_data_destroy (meta2);
301 GNUNET_free (str);
302 ABORT (meta);
303 }
304 GNUNET_free (str);
305
306 // check branch
307 if (NULL !=
308 (str =
309 GNUNET_CONTAINER_meta_data_get_by_type (meta,
310 EXTRACTOR_METATYPE_PUBLICATION_DATE)))
311 {
312 GNUNET_free (str);
313 GNUNET_CONTAINER_meta_data_destroy (meta2);
314 ABORT (meta);
315 }
316
317 // check meta_data_get_first_by_types
318 str =
319 GNUNET_CONTAINER_meta_data_get_first_by_types (meta,
320 EXTRACTOR_METATYPE_UNKNOWN,
321 -1);
322 GNUNET_assert (NULL != str);
323 if (str[0] != 'T')
324 {
325 GNUNET_CONTAINER_meta_data_destroy (meta2);
326 GNUNET_free (str);
327 ABORT (meta);
328 }
329 GNUNET_free (str);
330
331 // check meta_data_get_thumbnail
332 if (GNUNET_CONTAINER_meta_data_get_thumbnail (meta, &thumb) != 0)
333 {
334 GNUNET_free (thumb);
335 GNUNET_CONTAINER_meta_data_destroy (meta2);
336 ABORT (meta);
337 }
338 GNUNET_CONTAINER_meta_data_destroy (meta2);
339 // check meta_data_duplicate
340 meta2 = GNUNET_CONTAINER_meta_data_duplicate (meta);
341 if (200 == GNUNET_CONTAINER_meta_data_iterate (meta2, NULL, NULL))
342 {
343 GNUNET_CONTAINER_meta_data_destroy (meta2);
344 ABORT (meta);
345 }
346 GNUNET_CONTAINER_meta_data_destroy (meta2);
347 GNUNET_CONTAINER_meta_data_destroy (meta);
348 return 0;
349}
350
351
352int
353main (int argc, char *argv[])
354{
355 int failureCount = 0;
356 int i;
357
358 GNUNET_log_setup ("test-container-meta-data", "WARNING", NULL);
359 for (i = 0; i < 255; i++)
360 failureCount += testMeta (i);
361 for (i = 1; i < 255; i++)
362 failureCount += testMetaMore (i);
363 failureCount += testMetaLink ();
364
365 int ret = check ();
366
367 if (ret == 1)
368 return 1;
369
370 if (failureCount != 0)
371 return 1;
372 return 0;
373}
374
375
376/* end of test_container_meta_data.c */