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