diff options
author | Martin Schanzenbach <schanzen@gnunet.org> | 2022-12-04 23:26:25 +0900 |
---|---|---|
committer | Martin Schanzenbach <schanzen@gnunet.org> | 2022-12-04 23:26:25 +0900 |
commit | 395bc9345a005a55e29a7882fdcc82f35c06d2e5 (patch) | |
tree | b111592f9f57025a19ddafe11877f6038263ae7f /src/util | |
parent | 3f0d91045d29435feef723f09f9ff75c80296d3d (diff) | |
download | gnunet-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.am | 7 | ||||
-rw-r--r-- | src/util/bio.c | 198 | ||||
-rw-r--r-- | src/util/compress.c | 91 | ||||
-rw-r--r-- | src/util/container_meta_data.c | 1122 | ||||
-rw-r--r-- | src/util/crypto_crc.c | 6 | ||||
-rw-r--r-- | src/util/test_container_meta_data.c | 376 |
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 = \ | |||
423 | test_container_dll_LDADD = \ | 423 | test_container_dll_LDADD = \ |
424 | libgnunetutil.la | 424 | libgnunetutil.la |
425 | 425 | ||
426 | test_container_meta_data_SOURCES = \ | ||
427 | test_container_meta_data.c | ||
428 | test_container_meta_data_LDADD = \ | ||
429 | libgnunetutil.la | ||
430 | |||
431 | test_container_multihashmap_SOURCES = \ | 426 | test_container_multihashmap_SOURCES = \ |
432 | test_container_multihashmap.c | 427 | test_container_multihashmap.c |
433 | test_container_multihashmap_LDADD = \ | 428 | test_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 | */ | ||
390 | int | ||
391 | GNUNET_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 | */ | ||
857 | int | ||
858 | GNUNET_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 | */ | ||
1073 | static int | ||
1074 | read_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 | */ | ||
1092 | struct GNUNET_BIO_ReadSpec | ||
1093 | GNUNET_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 | */ | ||
1363 | static int | ||
1364 | write_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 | */ | ||
1382 | struct GNUNET_BIO_WriteSpec | ||
1383 | GNUNET_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 | |||
32 | int | ||
33 | GNUNET_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 | |||
69 | char * | ||
70 | GNUNET_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 | */ | ||
54 | int | ||
55 | GNUNET_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 | */ | ||
101 | char * | ||
102 | GNUNET_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 | */ | ||
125 | struct 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 | */ | ||
171 | struct 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 | */ | ||
206 | struct GNUNET_CONTAINER_MetaData * | ||
207 | GNUNET_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 | */ | ||
218 | static void | ||
219 | meta_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 | */ | ||
234 | static void | ||
235 | invalidate_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 | |||
245 | void | ||
246 | GNUNET_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 | |||
262 | void | ||
263 | GNUNET_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 | |||
279 | int | ||
280 | GNUNET_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. '<zlib>' 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 | */ | ||
333 | int | ||
334 | GNUNET_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. '<zlib>' 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 | */ | ||
422 | static int | ||
423 | merge_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 | |||
435 | void | ||
436 | GNUNET_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 | |||
443 | int | ||
444 | GNUNET_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 | |||
470 | void | ||
471 | GNUNET_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 | */ | ||
497 | int | ||
498 | GNUNET_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 | |||
517 | char * | ||
518 | GNUNET_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 | |||
535 | char * | ||
536 | GNUNET_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 | */ | ||
569 | size_t | ||
570 | GNUNET_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 | */ | ||
606 | struct GNUNET_CONTAINER_MetaData * | ||
607 | GNUNET_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 | */ | ||
639 | struct 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 | */ | ||
673 | struct 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 | */ | ||
716 | ssize_t | ||
717 | GNUNET_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 | |||
937 | ssize_t | ||
938 | GNUNET_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 | */ | ||
964 | struct GNUNET_CONTAINER_MetaData * | ||
965 | GNUNET_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 | */ |
86 | static GNUNET_uLong | 86 | static GNUNET_uLong |
87 | crc32 (GNUNET_uLong crc, const char *buf, size_t len) | 87 | gn_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 | |||
36 | static int | ||
37 | testMeta (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 | |||
148 | static int | ||
149 | testMetaMore (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 | |||
182 | static int | ||
183 | testMetaLink () | ||
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 | |||
218 | static int | ||
219 | check () | ||
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 | |||
352 | int | ||
353 | main (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 */ | ||