diff options
Diffstat (limited to 'src/fs/fs_directory.c')
-rw-r--r-- | src/fs/fs_directory.c | 600 |
1 files changed, 303 insertions, 297 deletions
diff --git a/src/fs/fs_directory.c b/src/fs/fs_directory.c index ae7727cf0..5e1e0af5e 100644 --- a/src/fs/fs_directory.c +++ b/src/fs/fs_directory.c | |||
@@ -51,18 +51,21 @@ | |||
51 | * we have no mime-type information (treat as #GNUNET_NO) | 51 | * we have no mime-type information (treat as #GNUNET_NO) |
52 | */ | 52 | */ |
53 | int | 53 | int |
54 | GNUNET_FS_meta_data_test_for_directory(const struct GNUNET_CONTAINER_MetaData *md) | 54 | GNUNET_FS_meta_data_test_for_directory (const struct |
55 | GNUNET_CONTAINER_MetaData *md) | ||
55 | { | 56 | { |
56 | char *mime; | 57 | char *mime; |
57 | int ret; | 58 | int ret; |
58 | 59 | ||
59 | if (NULL == md) | 60 | if (NULL == md) |
60 | return GNUNET_SYSERR; | 61 | return GNUNET_SYSERR; |
61 | mime = GNUNET_CONTAINER_meta_data_get_by_type(md, EXTRACTOR_METATYPE_MIMETYPE); | 62 | mime = GNUNET_CONTAINER_meta_data_get_by_type (md, |
63 | EXTRACTOR_METATYPE_MIMETYPE); | ||
62 | if (NULL == mime) | 64 | if (NULL == mime) |
63 | return GNUNET_SYSERR; | 65 | return GNUNET_SYSERR; |
64 | ret = (0 == strcasecmp(mime, GNUNET_FS_DIRECTORY_MIME)) ? GNUNET_YES : GNUNET_NO; | 66 | ret = (0 == strcasecmp (mime, GNUNET_FS_DIRECTORY_MIME)) ? GNUNET_YES : |
65 | GNUNET_free(mime); | 67 | GNUNET_NO; |
68 | GNUNET_free (mime); | ||
66 | return ret; | 69 | return ret; |
67 | } | 70 | } |
68 | 71 | ||
@@ -74,30 +77,31 @@ GNUNET_FS_meta_data_test_for_directory(const struct GNUNET_CONTAINER_MetaData *m | |||
74 | * @param md metadata to add mimetype to | 77 | * @param md metadata to add mimetype to |
75 | */ | 78 | */ |
76 | void | 79 | void |
77 | GNUNET_FS_meta_data_make_directory(struct GNUNET_CONTAINER_MetaData *md) | 80 | GNUNET_FS_meta_data_make_directory (struct GNUNET_CONTAINER_MetaData *md) |
78 | { | 81 | { |
79 | char *mime; | 82 | char *mime; |
80 | 83 | ||
81 | mime = | 84 | mime = |
82 | GNUNET_CONTAINER_meta_data_get_by_type(md, EXTRACTOR_METATYPE_MIMETYPE); | 85 | GNUNET_CONTAINER_meta_data_get_by_type (md, EXTRACTOR_METATYPE_MIMETYPE); |
83 | if (mime != NULL) | 86 | if (mime != NULL) |
84 | { | 87 | { |
85 | GNUNET_break(0 == strcmp(mime, GNUNET_FS_DIRECTORY_MIME)); | 88 | GNUNET_break (0 == strcmp (mime, GNUNET_FS_DIRECTORY_MIME)); |
86 | GNUNET_free(mime); | 89 | GNUNET_free (mime); |
87 | return; | 90 | return; |
88 | } | 91 | } |
89 | GNUNET_CONTAINER_meta_data_insert(md, "<gnunet>", | 92 | GNUNET_CONTAINER_meta_data_insert (md, "<gnunet>", |
90 | EXTRACTOR_METATYPE_MIMETYPE, | 93 | EXTRACTOR_METATYPE_MIMETYPE, |
91 | EXTRACTOR_METAFORMAT_UTF8, "text/plain", | 94 | EXTRACTOR_METAFORMAT_UTF8, "text/plain", |
92 | GNUNET_FS_DIRECTORY_MIME, | 95 | GNUNET_FS_DIRECTORY_MIME, |
93 | strlen(GNUNET_FS_DIRECTORY_MIME) + 1); | 96 | strlen (GNUNET_FS_DIRECTORY_MIME) + 1); |
94 | } | 97 | } |
95 | 98 | ||
96 | 99 | ||
97 | /** | 100 | /** |
98 | * Closure for 'find_full_data'. | 101 | * Closure for 'find_full_data'. |
99 | */ | 102 | */ |
100 | struct GetFullDataClosure { | 103 | struct GetFullDataClosure |
104 | { | ||
101 | /** | 105 | /** |
102 | * Extracted binary meta data. | 106 | * Extracted binary meta data. |
103 | */ | 107 | */ |
@@ -128,22 +132,22 @@ struct GetFullDataClosure { | |||
128 | * @return 0 to continue extracting, 1 to abort | 132 | * @return 0 to continue extracting, 1 to abort |
129 | */ | 133 | */ |
130 | static int | 134 | static int |
131 | find_full_data(void *cls, const char *plugin_name, | 135 | find_full_data (void *cls, const char *plugin_name, |
132 | enum EXTRACTOR_MetaType type, enum EXTRACTOR_MetaFormat format, | 136 | enum EXTRACTOR_MetaType type, enum EXTRACTOR_MetaFormat format, |
133 | const char *data_mime_type, const char *data, size_t data_len) | 137 | const char *data_mime_type, const char *data, size_t data_len) |
134 | { | 138 | { |
135 | struct GetFullDataClosure *gfdc = cls; | 139 | struct GetFullDataClosure *gfdc = cls; |
136 | 140 | ||
137 | if (type == EXTRACTOR_METATYPE_GNUNET_FULL_DATA) | 141 | if (type == EXTRACTOR_METATYPE_GNUNET_FULL_DATA) |
142 | { | ||
143 | gfdc->size = data_len; | ||
144 | if (data_len > 0) | ||
138 | { | 145 | { |
139 | gfdc->size = data_len; | 146 | gfdc->data = GNUNET_malloc (data_len); |
140 | if (data_len > 0) | 147 | GNUNET_memcpy (gfdc->data, data, data_len); |
141 | { | ||
142 | gfdc->data = GNUNET_malloc(data_len); | ||
143 | GNUNET_memcpy(gfdc->data, data, data_len); | ||
144 | } | ||
145 | return 1; | ||
146 | } | 148 | } |
149 | return 1; | ||
150 | } | ||
147 | return 0; | 151 | return 0; |
148 | } | 152 | } |
149 | 153 | ||
@@ -174,11 +178,11 @@ find_full_data(void *cls, const char *plugin_name, | |||
174 | * #GNUNET_SYSERR if @a data does not represent a directory | 178 | * #GNUNET_SYSERR if @a data does not represent a directory |
175 | */ | 179 | */ |
176 | int | 180 | int |
177 | GNUNET_FS_directory_list_contents(size_t size, | 181 | GNUNET_FS_directory_list_contents (size_t size, |
178 | const void *data, | 182 | const void *data, |
179 | uint64_t offset, | 183 | uint64_t offset, |
180 | GNUNET_FS_DirectoryEntryProcessor dep, | 184 | GNUNET_FS_DirectoryEntryProcessor dep, |
181 | void *dep_cls) | 185 | void *dep_cls) |
182 | { | 186 | { |
183 | struct GetFullDataClosure full_data; | 187 | struct GetFullDataClosure full_data; |
184 | const char *cdata = data; | 188 | const char *cdata = data; |
@@ -193,130 +197,131 @@ GNUNET_FS_directory_list_contents(size_t size, | |||
193 | 197 | ||
194 | if ((offset == 0) && | 198 | if ((offset == 0) && |
195 | ((size < 8 + sizeof(uint32_t)) || | 199 | ((size < 8 + sizeof(uint32_t)) || |
196 | (0 != memcmp(cdata, | 200 | (0 != memcmp (cdata, |
197 | GNUNET_FS_DIRECTORY_MAGIC, | 201 | GNUNET_FS_DIRECTORY_MAGIC, |
198 | 8)))) | 202 | 8)))) |
199 | return GNUNET_SYSERR; | 203 | return GNUNET_SYSERR; |
200 | pos = offset; | 204 | pos = offset; |
201 | if (offset == 0) | 205 | if (offset == 0) |
206 | { | ||
207 | GNUNET_memcpy (&mdSize, | ||
208 | &cdata[8], | ||
209 | sizeof(uint32_t)); | ||
210 | mdSize = ntohl (mdSize); | ||
211 | if (mdSize > size - 8 - sizeof(uint32_t)) | ||
202 | { | 212 | { |
203 | GNUNET_memcpy(&mdSize, | 213 | /* invalid size */ |
204 | &cdata[8], | 214 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, |
205 | sizeof(uint32_t)); | 215 | _ ("MAGIC mismatch. This is not a GNUnet directory.\n")); |
206 | mdSize = ntohl(mdSize); | 216 | return GNUNET_SYSERR; |
207 | if (mdSize > size - 8 - sizeof(uint32_t)) | 217 | } |
208 | { | 218 | md = GNUNET_CONTAINER_meta_data_deserialize (&cdata[8 + sizeof(uint32_t)], |
209 | /* invalid size */ | 219 | mdSize); |
210 | GNUNET_log(GNUNET_ERROR_TYPE_WARNING, | 220 | if (md == NULL) |
211 | _("MAGIC mismatch. This is not a GNUnet directory.\n")); | 221 | { |
212 | return GNUNET_SYSERR; | 222 | GNUNET_break (0); |
213 | } | 223 | return GNUNET_SYSERR; /* malformed ! */ |
214 | md = GNUNET_CONTAINER_meta_data_deserialize(&cdata[8 + sizeof(uint32_t)], | ||
215 | mdSize); | ||
216 | if (md == NULL) | ||
217 | { | ||
218 | GNUNET_break(0); | ||
219 | return GNUNET_SYSERR; /* malformed ! */ | ||
220 | } | ||
221 | dep(dep_cls, | ||
222 | NULL, | ||
223 | NULL, | ||
224 | md, | ||
225 | 0, | ||
226 | NULL); | ||
227 | GNUNET_CONTAINER_meta_data_destroy(md); | ||
228 | pos = 8 + sizeof(uint32_t) + mdSize; | ||
229 | } | 224 | } |
225 | dep (dep_cls, | ||
226 | NULL, | ||
227 | NULL, | ||
228 | md, | ||
229 | 0, | ||
230 | NULL); | ||
231 | GNUNET_CONTAINER_meta_data_destroy (md); | ||
232 | pos = 8 + sizeof(uint32_t) + mdSize; | ||
233 | } | ||
230 | while (pos < size) | 234 | while (pos < size) |
235 | { | ||
236 | /* find end of URI */ | ||
237 | if (cdata[pos] == '\0') | ||
231 | { | 238 | { |
232 | /* find end of URI */ | 239 | /* URI is never empty, must be end of block, |
233 | if (cdata[pos] == '\0') | 240 | * skip to next alignment */ |
234 | { | 241 | align = ((pos / DBLOCK_SIZE) + 1) * DBLOCK_SIZE; |
235 | /* URI is never empty, must be end of block, | 242 | if (align == pos) |
236 | * skip to next alignment */ | 243 | { |
237 | align = ((pos / DBLOCK_SIZE) + 1) * DBLOCK_SIZE; | 244 | /* if we were already aligned, still skip a block! */ |
238 | if (align == pos) | 245 | align += DBLOCK_SIZE; |
239 | { | 246 | } |
240 | /* if we were already aligned, still skip a block! */ | 247 | pos = align; |
241 | align += DBLOCK_SIZE; | 248 | if (pos >= size) |
242 | } | 249 | { |
243 | pos = align; | 250 | /* malformed - or partial download... */ |
244 | if (pos >= size) | 251 | break; |
245 | { | 252 | } |
246 | /* malformed - or partial download... */ | 253 | } |
247 | break; | 254 | epos = pos; |
248 | } | 255 | while ((epos < size) && (cdata[epos] != '\0')) |
249 | } | 256 | epos++; |
250 | epos = pos; | 257 | if (epos >= size) |
251 | while ((epos < size) && (cdata[epos] != '\0')) | 258 | return GNUNET_NO; /* malformed - or partial download */ |
252 | epos++; | 259 | |
253 | if (epos >= size) | 260 | uri = GNUNET_FS_uri_parse (&cdata[pos], &emsg); |
254 | return GNUNET_NO; /* malformed - or partial download */ | 261 | pos = epos + 1; |
255 | 262 | if (NULL == uri) | |
256 | uri = GNUNET_FS_uri_parse(&cdata[pos], &emsg); | 263 | { |
257 | pos = epos + 1; | 264 | GNUNET_free (emsg); |
258 | if (NULL == uri) | 265 | pos--; /* go back to '\0' to force going to next alignment */ |
259 | { | 266 | continue; |
260 | GNUNET_free(emsg); | 267 | } |
261 | pos--; /* go back to '\0' to force going to next alignment */ | 268 | if (GNUNET_FS_uri_test_ksk (uri)) |
262 | continue; | 269 | { |
263 | } | 270 | GNUNET_FS_uri_destroy (uri); |
264 | if (GNUNET_FS_uri_test_ksk(uri)) | 271 | GNUNET_break (0); |
265 | { | 272 | return GNUNET_NO; /* illegal in directory! */ |
266 | GNUNET_FS_uri_destroy(uri); | 273 | } |
267 | GNUNET_break(0); | ||
268 | return GNUNET_NO; /* illegal in directory! */ | ||
269 | } | ||
270 | 274 | ||
271 | GNUNET_memcpy(&mdSize, | 275 | GNUNET_memcpy (&mdSize, |
272 | &cdata[pos], | 276 | &cdata[pos], |
273 | sizeof(uint32_t)); | 277 | sizeof(uint32_t)); |
274 | mdSize = ntohl(mdSize); | 278 | mdSize = ntohl (mdSize); |
275 | pos += sizeof(uint32_t); | 279 | pos += sizeof(uint32_t); |
276 | if (pos + mdSize > size) | 280 | if (pos + mdSize > size) |
277 | { | 281 | { |
278 | GNUNET_FS_uri_destroy(uri); | 282 | GNUNET_FS_uri_destroy (uri); |
279 | return GNUNET_NO; /* malformed - or partial download */ | 283 | return GNUNET_NO; /* malformed - or partial download */ |
280 | } | 284 | } |
281 | 285 | ||
282 | md = GNUNET_CONTAINER_meta_data_deserialize(&cdata[pos], | 286 | md = GNUNET_CONTAINER_meta_data_deserialize (&cdata[pos], |
283 | mdSize); | 287 | mdSize); |
284 | if (NULL == md) | 288 | if (NULL == md) |
285 | { | 289 | { |
286 | GNUNET_FS_uri_destroy(uri); | 290 | GNUNET_FS_uri_destroy (uri); |
287 | GNUNET_break(0); | 291 | GNUNET_break (0); |
288 | return GNUNET_NO; /* malformed ! */ | 292 | return GNUNET_NO; /* malformed ! */ |
289 | } | 293 | } |
290 | pos += mdSize; | 294 | pos += mdSize; |
291 | filename = | 295 | filename = |
292 | GNUNET_CONTAINER_meta_data_get_by_type(md, | 296 | GNUNET_CONTAINER_meta_data_get_by_type (md, |
293 | EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME); | 297 | EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME); |
294 | full_data.size = 0; | 298 | full_data.size = 0; |
295 | full_data.data = NULL; | 299 | full_data.data = NULL; |
296 | GNUNET_CONTAINER_meta_data_iterate(md, | 300 | GNUNET_CONTAINER_meta_data_iterate (md, |
297 | &find_full_data, | 301 | &find_full_data, |
298 | &full_data); | 302 | &full_data); |
299 | if (NULL != dep) | 303 | if (NULL != dep) |
300 | { | 304 | { |
301 | dep(dep_cls, | 305 | dep (dep_cls, |
302 | filename, | 306 | filename, |
303 | uri, | 307 | uri, |
304 | md, | 308 | md, |
305 | full_data.size, | 309 | full_data.size, |
306 | full_data.data); | 310 | full_data.data); |
307 | } | ||
308 | GNUNET_free_non_null(full_data.data); | ||
309 | GNUNET_free_non_null(filename); | ||
310 | GNUNET_CONTAINER_meta_data_destroy(md); | ||
311 | GNUNET_FS_uri_destroy(uri); | ||
312 | } | 311 | } |
312 | GNUNET_free_non_null (full_data.data); | ||
313 | GNUNET_free_non_null (filename); | ||
314 | GNUNET_CONTAINER_meta_data_destroy (md); | ||
315 | GNUNET_FS_uri_destroy (uri); | ||
316 | } | ||
313 | return GNUNET_OK; | 317 | return GNUNET_OK; |
314 | } | 318 | } |
315 | 319 | ||
316 | /** | 320 | /** |
317 | * Entries in the directory (builder). | 321 | * Entries in the directory (builder). |
318 | */ | 322 | */ |
319 | struct BuilderEntry { | 323 | struct BuilderEntry |
324 | { | ||
320 | /** | 325 | /** |
321 | * This is a linked list. | 326 | * This is a linked list. |
322 | */ | 327 | */ |
@@ -331,7 +336,8 @@ struct BuilderEntry { | |||
331 | /** | 336 | /** |
332 | * Internal state of a directory builder. | 337 | * Internal state of a directory builder. |
333 | */ | 338 | */ |
334 | struct GNUNET_FS_DirectoryBuilder { | 339 | struct GNUNET_FS_DirectoryBuilder |
340 | { | ||
335 | /** | 341 | /** |
336 | * Meta-data for the directory itself. | 342 | * Meta-data for the directory itself. |
337 | */ | 343 | */ |
@@ -355,17 +361,17 @@ struct GNUNET_FS_DirectoryBuilder { | |||
355 | * @param mdir metadata for the directory | 361 | * @param mdir metadata for the directory |
356 | */ | 362 | */ |
357 | struct GNUNET_FS_DirectoryBuilder * | 363 | struct GNUNET_FS_DirectoryBuilder * |
358 | GNUNET_FS_directory_builder_create(const struct GNUNET_CONTAINER_MetaData | 364 | GNUNET_FS_directory_builder_create (const struct GNUNET_CONTAINER_MetaData |
359 | *mdir) | 365 | *mdir) |
360 | { | 366 | { |
361 | struct GNUNET_FS_DirectoryBuilder *ret; | 367 | struct GNUNET_FS_DirectoryBuilder *ret; |
362 | 368 | ||
363 | ret = GNUNET_new(struct GNUNET_FS_DirectoryBuilder); | 369 | ret = GNUNET_new (struct GNUNET_FS_DirectoryBuilder); |
364 | if (mdir != NULL) | 370 | if (mdir != NULL) |
365 | ret->meta = GNUNET_CONTAINER_meta_data_duplicate(mdir); | 371 | ret->meta = GNUNET_CONTAINER_meta_data_duplicate (mdir); |
366 | else | 372 | else |
367 | ret->meta = GNUNET_CONTAINER_meta_data_create(); | 373 | ret->meta = GNUNET_CONTAINER_meta_data_create (); |
368 | GNUNET_FS_meta_data_make_directory(ret->meta); | 374 | GNUNET_FS_meta_data_make_directory (ret->meta); |
369 | return ret; | 375 | return ret; |
370 | } | 376 | } |
371 | 377 | ||
@@ -381,10 +387,10 @@ GNUNET_FS_directory_builder_create(const struct GNUNET_CONTAINER_MetaData | |||
381 | * by the uri which must be of type LOC or CHK | 387 | * by the uri which must be of type LOC or CHK |
382 | */ | 388 | */ |
383 | void | 389 | void |
384 | GNUNET_FS_directory_builder_add(struct GNUNET_FS_DirectoryBuilder *bld, | 390 | GNUNET_FS_directory_builder_add (struct GNUNET_FS_DirectoryBuilder *bld, |
385 | const struct GNUNET_FS_Uri *uri, | 391 | const struct GNUNET_FS_Uri *uri, |
386 | const struct GNUNET_CONTAINER_MetaData *md, | 392 | const struct GNUNET_CONTAINER_MetaData *md, |
387 | const void *data) | 393 | const void *data) |
388 | { | 394 | { |
389 | struct GNUNET_FS_Uri *curi; | 395 | struct GNUNET_FS_Uri *curi; |
390 | struct BuilderEntry *e; | 396 | struct BuilderEntry *e; |
@@ -400,70 +406,70 @@ GNUNET_FS_directory_builder_add(struct GNUNET_FS_DirectoryBuilder *bld, | |||
400 | struct GNUNET_CONTAINER_MetaData *meta; | 406 | struct GNUNET_CONTAINER_MetaData *meta; |
401 | const struct GNUNET_CONTAINER_MetaData *meta_use; | 407 | const struct GNUNET_CONTAINER_MetaData *meta_use; |
402 | 408 | ||
403 | GNUNET_assert(!GNUNET_FS_uri_test_ksk(uri)); | 409 | GNUNET_assert (! GNUNET_FS_uri_test_ksk (uri)); |
404 | if (NULL != data) | 410 | if (NULL != data) |
411 | { | ||
412 | GNUNET_assert (! GNUNET_FS_uri_test_sks (uri)); | ||
413 | if (GNUNET_FS_uri_test_chk (uri)) | ||
405 | { | 414 | { |
406 | GNUNET_assert(!GNUNET_FS_uri_test_sks(uri)); | 415 | fsize = GNUNET_FS_uri_chk_get_file_size (uri); |
407 | if (GNUNET_FS_uri_test_chk(uri)) | ||
408 | { | ||
409 | fsize = GNUNET_FS_uri_chk_get_file_size(uri); | ||
410 | } | ||
411 | else | ||
412 | { | ||
413 | curi = GNUNET_FS_uri_loc_get_uri(uri); | ||
414 | GNUNET_assert(NULL != curi); | ||
415 | fsize = GNUNET_FS_uri_chk_get_file_size(curi); | ||
416 | GNUNET_FS_uri_destroy(curi); | ||
417 | } | ||
418 | } | 416 | } |
419 | else | 417 | else |
420 | { | 418 | { |
421 | fsize = 0; /* not given */ | 419 | curi = GNUNET_FS_uri_loc_get_uri (uri); |
420 | GNUNET_assert (NULL != curi); | ||
421 | fsize = GNUNET_FS_uri_chk_get_file_size (curi); | ||
422 | GNUNET_FS_uri_destroy (curi); | ||
422 | } | 423 | } |
424 | } | ||
425 | else | ||
426 | { | ||
427 | fsize = 0; /* not given */ | ||
428 | } | ||
423 | if (fsize > MAX_INLINE_SIZE) | 429 | if (fsize > MAX_INLINE_SIZE) |
424 | fsize = 0; /* too large */ | 430 | fsize = 0; /* too large */ |
425 | uris = GNUNET_FS_uri_to_string(uri); | 431 | uris = GNUNET_FS_uri_to_string (uri); |
426 | slen = strlen(uris) + 1; | 432 | slen = strlen (uris) + 1; |
427 | mds = GNUNET_CONTAINER_meta_data_get_serialized_size(md); | 433 | mds = GNUNET_CONTAINER_meta_data_get_serialized_size (md); |
428 | meta_use = md; | 434 | meta_use = md; |
429 | meta = NULL; | 435 | meta = NULL; |
430 | if (fsize > 0) | 436 | if (fsize > 0) |
437 | { | ||
438 | meta = GNUNET_CONTAINER_meta_data_duplicate (md); | ||
439 | GNUNET_CONTAINER_meta_data_insert (meta, "<gnunet>", | ||
440 | EXTRACTOR_METATYPE_GNUNET_FULL_DATA, | ||
441 | EXTRACTOR_METAFORMAT_BINARY, NULL, data, | ||
442 | fsize); | ||
443 | mdxs = GNUNET_CONTAINER_meta_data_get_serialized_size (meta); | ||
444 | if ((slen + sizeof(uint32_t) + mdxs - 1) / DBLOCK_SIZE == | ||
445 | (slen + sizeof(uint32_t) + mds - 1) / DBLOCK_SIZE) | ||
431 | { | 446 | { |
432 | meta = GNUNET_CONTAINER_meta_data_duplicate(md); | 447 | /* adding full data would not cause us to cross |
433 | GNUNET_CONTAINER_meta_data_insert(meta, "<gnunet>", | 448 | * additional blocks, so add it! */ |
434 | EXTRACTOR_METATYPE_GNUNET_FULL_DATA, | 449 | meta_use = meta; |
435 | EXTRACTOR_METAFORMAT_BINARY, NULL, data, | 450 | mds = mdxs; |
436 | fsize); | ||
437 | mdxs = GNUNET_CONTAINER_meta_data_get_serialized_size(meta); | ||
438 | if ((slen + sizeof(uint32_t) + mdxs - 1) / DBLOCK_SIZE == | ||
439 | (slen + sizeof(uint32_t) + mds - 1) / DBLOCK_SIZE) | ||
440 | { | ||
441 | /* adding full data would not cause us to cross | ||
442 | * additional blocks, so add it! */ | ||
443 | meta_use = meta; | ||
444 | mds = mdxs; | ||
445 | } | ||
446 | } | 451 | } |
452 | } | ||
447 | 453 | ||
448 | if (mds > GNUNET_MAX_MALLOC_CHECKED / 2) | 454 | if (mds > GNUNET_MAX_MALLOC_CHECKED / 2) |
449 | mds = GNUNET_MAX_MALLOC_CHECKED / 2; | 455 | mds = GNUNET_MAX_MALLOC_CHECKED / 2; |
450 | e = GNUNET_malloc(sizeof(struct BuilderEntry) + slen + mds + | 456 | e = GNUNET_malloc (sizeof(struct BuilderEntry) + slen + mds |
451 | sizeof(uint32_t)); | 457 | + sizeof(uint32_t)); |
452 | ser = (char *)&e[1]; | 458 | ser = (char *) &e[1]; |
453 | GNUNET_memcpy(ser, uris, slen); | 459 | GNUNET_memcpy (ser, uris, slen); |
454 | GNUNET_free(uris); | 460 | GNUNET_free (uris); |
455 | sptr = &ser[slen + sizeof(uint32_t)]; | 461 | sptr = &ser[slen + sizeof(uint32_t)]; |
456 | ret = | 462 | ret = |
457 | GNUNET_CONTAINER_meta_data_serialize(meta_use, &sptr, mds, | 463 | GNUNET_CONTAINER_meta_data_serialize (meta_use, &sptr, mds, |
458 | GNUNET_CONTAINER_META_DATA_SERIALIZE_PART); | 464 | GNUNET_CONTAINER_META_DATA_SERIALIZE_PART); |
459 | if (NULL != meta) | 465 | if (NULL != meta) |
460 | GNUNET_CONTAINER_meta_data_destroy(meta); | 466 | GNUNET_CONTAINER_meta_data_destroy (meta); |
461 | if (ret == -1) | 467 | if (ret == -1) |
462 | mds = 0; | 468 | mds = 0; |
463 | else | 469 | else |
464 | mds = ret; | 470 | mds = ret; |
465 | big = htonl(mds); | 471 | big = htonl (mds); |
466 | GNUNET_memcpy(&ser[slen], &big, sizeof(uint32_t)); | 472 | GNUNET_memcpy (&ser[slen], &big, sizeof(uint32_t)); |
467 | e->len = slen + sizeof(uint32_t) + mds; | 473 | e->len = slen + sizeof(uint32_t) + mds; |
468 | e->next = bld->head; | 474 | e->next = bld->head; |
469 | bld->head = e; | 475 | bld->head = e; |
@@ -477,7 +483,7 @@ GNUNET_FS_directory_builder_add(struct GNUNET_FS_DirectoryBuilder *bld, | |||
477 | * after alignment to the DBLOCK_SIZE. | 483 | * after alignment to the DBLOCK_SIZE. |
478 | */ | 484 | */ |
479 | static size_t | 485 | static size_t |
480 | do_align(size_t start_position, size_t end_position) | 486 | do_align (size_t start_position, size_t end_position) |
481 | { | 487 | { |
482 | size_t align; | 488 | size_t align; |
483 | 489 | ||
@@ -498,8 +504,8 @@ do_align(size_t start_position, size_t end_position) | |||
498 | * @param perm the permutation of the blocks (updated) | 504 | * @param perm the permutation of the blocks (updated) |
499 | */ | 505 | */ |
500 | static void | 506 | static void |
501 | block_align(size_t start, unsigned int count, const size_t * sizes, | 507 | block_align (size_t start, unsigned int count, const size_t *sizes, |
502 | unsigned int *perm) | 508 | unsigned int *perm) |
503 | { | 509 | { |
504 | unsigned int i; | 510 | unsigned int i; |
505 | unsigned int j; | 511 | unsigned int j; |
@@ -513,46 +519,46 @@ block_align(size_t start, unsigned int count, const size_t * sizes, | |||
513 | 519 | ||
514 | cpos = start; | 520 | cpos = start; |
515 | for (i = 0; i < count; i++) | 521 | for (i = 0; i < count; i++) |
522 | { | ||
523 | start = cpos; | ||
524 | badness = 0x7FFFFFFF; | ||
525 | best = -1; | ||
526 | for (j = i; j < count; j++) | ||
516 | { | 527 | { |
517 | start = cpos; | 528 | cval = perm[j]; |
518 | badness = 0x7FFFFFFF; | 529 | cend = cpos + sizes[cval]; |
519 | best = -1; | 530 | if (cpos % DBLOCK_SIZE == 0) |
520 | for (j = i; j < count; j++) | 531 | { |
532 | /* prefer placing the largest blocks first */ | ||
533 | cbad = -(cend % DBLOCK_SIZE); | ||
534 | } | ||
535 | else | ||
536 | { | ||
537 | if (cpos / DBLOCK_SIZE == cend / DBLOCK_SIZE) | ||
538 | { | ||
539 | /* Data fits into the same block! Prefer small left-overs! */ | ||
540 | cbad = DBLOCK_SIZE - cend % DBLOCK_SIZE; | ||
541 | } | ||
542 | else | ||
521 | { | 543 | { |
522 | cval = perm[j]; | 544 | /* Would have to waste space to re-align, add big factor, this |
523 | cend = cpos + sizes[cval]; | 545 | * case is a real loss (proportional to space wasted)! */ |
524 | if (cpos % DBLOCK_SIZE == 0) | 546 | cbad = DBLOCK_SIZE * (DBLOCK_SIZE - cpos % DBLOCK_SIZE); |
525 | { | ||
526 | /* prefer placing the largest blocks first */ | ||
527 | cbad = -(cend % DBLOCK_SIZE); | ||
528 | } | ||
529 | else | ||
530 | { | ||
531 | if (cpos / DBLOCK_SIZE == cend / DBLOCK_SIZE) | ||
532 | { | ||
533 | /* Data fits into the same block! Prefer small left-overs! */ | ||
534 | cbad = DBLOCK_SIZE - cend % DBLOCK_SIZE; | ||
535 | } | ||
536 | else | ||
537 | { | ||
538 | /* Would have to waste space to re-align, add big factor, this | ||
539 | * case is a real loss (proportional to space wasted)! */ | ||
540 | cbad = DBLOCK_SIZE * (DBLOCK_SIZE - cpos % DBLOCK_SIZE); | ||
541 | } | ||
542 | } | ||
543 | if (cbad < badness) | ||
544 | { | ||
545 | best = j; | ||
546 | badness = cbad; | ||
547 | } | ||
548 | } | 547 | } |
549 | GNUNET_assert(best != -1); | 548 | } |
550 | tmp = perm[i]; | 549 | if (cbad < badness) |
551 | perm[i] = perm[best]; | 550 | { |
552 | perm[best] = tmp; | 551 | best = j; |
553 | cpos += sizes[perm[i]]; | 552 | badness = cbad; |
554 | cpos = do_align(start, cpos); | 553 | } |
555 | } | 554 | } |
555 | GNUNET_assert (best != -1); | ||
556 | tmp = perm[i]; | ||
557 | perm[i] = perm[best]; | ||
558 | perm[best] = tmp; | ||
559 | cpos += sizes[perm[i]]; | ||
560 | cpos = do_align (start, cpos); | ||
561 | } | ||
556 | } | 562 | } |
557 | 563 | ||
558 | 564 | ||
@@ -567,9 +573,9 @@ block_align(size_t start, unsigned int count, const size_t * sizes, | |||
567 | * @return #GNUNET_OK on success | 573 | * @return #GNUNET_OK on success |
568 | */ | 574 | */ |
569 | int | 575 | int |
570 | GNUNET_FS_directory_builder_finish(struct GNUNET_FS_DirectoryBuilder *bld, | 576 | GNUNET_FS_directory_builder_finish (struct GNUNET_FS_DirectoryBuilder *bld, |
571 | size_t * rsize, | 577 | size_t *rsize, |
572 | void **rdata) | 578 | void **rdata) |
573 | { | 579 | { |
574 | char *data; | 580 | char *data; |
575 | char *sptr; | 581 | char *sptr; |
@@ -585,82 +591,82 @@ GNUNET_FS_directory_builder_finish(struct GNUNET_FS_DirectoryBuilder *bld, | |||
585 | ssize_t ret; | 591 | ssize_t ret; |
586 | uint32_t big; | 592 | uint32_t big; |
587 | 593 | ||
588 | size = strlen(GNUNET_DIRECTORY_MAGIC) + sizeof(uint32_t); | 594 | size = strlen (GNUNET_DIRECTORY_MAGIC) + sizeof(uint32_t); |
589 | size += GNUNET_CONTAINER_meta_data_get_serialized_size(bld->meta); | 595 | size += GNUNET_CONTAINER_meta_data_get_serialized_size (bld->meta); |
590 | sizes = NULL; | 596 | sizes = NULL; |
591 | perm = NULL; | 597 | perm = NULL; |
592 | bes = NULL; | 598 | bes = NULL; |
593 | if (0 < bld->count) | 599 | if (0 < bld->count) |
600 | { | ||
601 | sizes = GNUNET_new_array (bld->count, | ||
602 | size_t); | ||
603 | perm = GNUNET_new_array (bld->count, | ||
604 | unsigned int); | ||
605 | bes = GNUNET_new_array (bld->count, | ||
606 | struct BuilderEntry *); | ||
607 | pos = bld->head; | ||
608 | for (i = 0; i < bld->count; i++) | ||
594 | { | 609 | { |
595 | sizes = GNUNET_new_array(bld->count, | 610 | perm[i] = i; |
596 | size_t); | 611 | bes[i] = pos; |
597 | perm = GNUNET_new_array(bld->count, | 612 | sizes[i] = pos->len; |
598 | unsigned int); | 613 | pos = pos->next; |
599 | bes = GNUNET_new_array(bld->count, | ||
600 | struct BuilderEntry *); | ||
601 | pos = bld->head; | ||
602 | for (i = 0; i < bld->count; i++) | ||
603 | { | ||
604 | perm[i] = i; | ||
605 | bes[i] = pos; | ||
606 | sizes[i] = pos->len; | ||
607 | pos = pos->next; | ||
608 | } | ||
609 | block_align(size, bld->count, sizes, perm); | ||
610 | /* compute final size with alignment */ | ||
611 | for (i = 0; i < bld->count; i++) | ||
612 | { | ||
613 | psize = size; | ||
614 | size += sizes[perm[i]]; | ||
615 | size = do_align(psize, size); | ||
616 | } | ||
617 | } | 614 | } |
618 | *rsize = size; | 615 | block_align (size, bld->count, sizes, perm); |
619 | data = GNUNET_malloc_large(size); | 616 | /* compute final size with alignment */ |
620 | if (data == NULL) | 617 | for (i = 0; i < bld->count; i++) |
621 | { | 618 | { |
622 | GNUNET_log_strerror(GNUNET_ERROR_TYPE_ERROR, | 619 | psize = size; |
623 | "malloc"); | 620 | size += sizes[perm[i]]; |
624 | *rsize = 0; | 621 | size = do_align (psize, size); |
625 | *rdata = NULL; | ||
626 | GNUNET_free_non_null(sizes); | ||
627 | GNUNET_free_non_null(perm); | ||
628 | GNUNET_free_non_null(bes); | ||
629 | return GNUNET_SYSERR; | ||
630 | } | 622 | } |
623 | } | ||
624 | *rsize = size; | ||
625 | data = GNUNET_malloc_large (size); | ||
626 | if (data == NULL) | ||
627 | { | ||
628 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, | ||
629 | "malloc"); | ||
630 | *rsize = 0; | ||
631 | *rdata = NULL; | ||
632 | GNUNET_free_non_null (sizes); | ||
633 | GNUNET_free_non_null (perm); | ||
634 | GNUNET_free_non_null (bes); | ||
635 | return GNUNET_SYSERR; | ||
636 | } | ||
631 | *rdata = data; | 637 | *rdata = data; |
632 | GNUNET_memcpy(data, | 638 | GNUNET_memcpy (data, |
633 | GNUNET_DIRECTORY_MAGIC, | 639 | GNUNET_DIRECTORY_MAGIC, |
634 | strlen(GNUNET_DIRECTORY_MAGIC)); | 640 | strlen (GNUNET_DIRECTORY_MAGIC)); |
635 | off = strlen(GNUNET_DIRECTORY_MAGIC); | 641 | off = strlen (GNUNET_DIRECTORY_MAGIC); |
636 | 642 | ||
637 | sptr = &data[off + sizeof(uint32_t)]; | 643 | sptr = &data[off + sizeof(uint32_t)]; |
638 | ret = | 644 | ret = |
639 | GNUNET_CONTAINER_meta_data_serialize(bld->meta, | 645 | GNUNET_CONTAINER_meta_data_serialize (bld->meta, |
640 | &sptr, | 646 | &sptr, |
641 | size - off - sizeof(uint32_t), | 647 | size - off - sizeof(uint32_t), |
642 | GNUNET_CONTAINER_META_DATA_SERIALIZE_FULL); | 648 | GNUNET_CONTAINER_META_DATA_SERIALIZE_FULL); |
643 | GNUNET_assert(ret != -1); | 649 | GNUNET_assert (ret != -1); |
644 | big = htonl(ret); | 650 | big = htonl (ret); |
645 | GNUNET_memcpy(&data[off], | 651 | GNUNET_memcpy (&data[off], |
646 | &big, | 652 | &big, |
647 | sizeof(uint32_t)); | 653 | sizeof(uint32_t)); |
648 | off += sizeof(uint32_t) + ret; | 654 | off += sizeof(uint32_t) + ret; |
649 | for (j = 0; j < bld->count; j++) | 655 | for (j = 0; j < bld->count; j++) |
650 | { | 656 | { |
651 | i = perm[j]; | 657 | i = perm[j]; |
652 | psize = off; | 658 | psize = off; |
653 | off += sizes[i]; | 659 | off += sizes[i]; |
654 | off = do_align(psize, off); | 660 | off = do_align (psize, off); |
655 | GNUNET_memcpy(&data[off - sizes[i]], &(bes[i])[1], sizes[i]); | 661 | GNUNET_memcpy (&data[off - sizes[i]], &(bes[i])[1], sizes[i]); |
656 | GNUNET_free(bes[i]); | 662 | GNUNET_free (bes[i]); |
657 | } | 663 | } |
658 | GNUNET_free_non_null(sizes); | 664 | GNUNET_free_non_null (sizes); |
659 | GNUNET_free_non_null(perm); | 665 | GNUNET_free_non_null (perm); |
660 | GNUNET_free_non_null(bes); | 666 | GNUNET_free_non_null (bes); |
661 | GNUNET_assert(off == size); | 667 | GNUNET_assert (off == size); |
662 | GNUNET_CONTAINER_meta_data_destroy(bld->meta); | 668 | GNUNET_CONTAINER_meta_data_destroy (bld->meta); |
663 | GNUNET_free(bld); | 669 | GNUNET_free (bld); |
664 | return GNUNET_OK; | 670 | return GNUNET_OK; |
665 | } | 671 | } |
666 | 672 | ||