summaryrefslogtreecommitdiff
path: root/src/fs/fs_directory.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/fs/fs_directory.c')
-rw-r--r--src/fs/fs_directory.c600
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 */
53int 53int
54GNUNET_FS_meta_data_test_for_directory(const struct GNUNET_CONTAINER_MetaData *md) 54GNUNET_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 */
76void 79void
77GNUNET_FS_meta_data_make_directory(struct GNUNET_CONTAINER_MetaData *md) 80GNUNET_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 */
100struct GetFullDataClosure { 103struct 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 */
130static int 134static int
131find_full_data(void *cls, const char *plugin_name, 135find_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 */
176int 180int
177GNUNET_FS_directory_list_contents(size_t size, 181GNUNET_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 */
319struct BuilderEntry { 323struct 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 */
334struct GNUNET_FS_DirectoryBuilder { 339struct 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 */
357struct GNUNET_FS_DirectoryBuilder * 363struct GNUNET_FS_DirectoryBuilder *
358GNUNET_FS_directory_builder_create(const struct GNUNET_CONTAINER_MetaData 364GNUNET_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 */
383void 389void
384GNUNET_FS_directory_builder_add(struct GNUNET_FS_DirectoryBuilder *bld, 390GNUNET_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 */
479static size_t 485static size_t
480do_align(size_t start_position, size_t end_position) 486do_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 */
500static void 506static void
501block_align(size_t start, unsigned int count, const size_t * sizes, 507block_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 */
569int 575int
570GNUNET_FS_directory_builder_finish(struct GNUNET_FS_DirectoryBuilder *bld, 576GNUNET_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