aboutsummaryrefslogtreecommitdiff
path: root/src/util/bio.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/bio.c')
-rw-r--r--src/util/bio.c1560
1 files changed, 0 insertions, 1560 deletions
diff --git a/src/util/bio.c b/src/util/bio.c
deleted file mode 100644
index d221d0a21..000000000
--- a/src/util/bio.c
+++ /dev/null
@@ -1,1560 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2006, 2009, 2013 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 * @file util/bio.c
22 * @brief functions for buffering IO
23 * @author Christian Grothoff
24 */
25#include "platform.h"
26#include "gnunet_util_lib.h"
27
28#define LOG(kind, ...) GNUNET_log_from (kind, "util-bio", __VA_ARGS__)
29
30#ifndef PATH_MAX
31/**
32 * Assumed maximum path length (for source file names).
33 */
34#define PATH_MAX 4096
35#endif
36
37
38/**
39 * Size for I/O buffers.
40 */
41#define BIO_BUFFER_SIZE 65536
42
43/**
44 * Maximum size allowed for meta data written/read from disk.
45 * File-sharing limits to 64k, so this should be rather generous.
46 */
47#define MAX_META_DATA (1024 * 1024)
48
49
50/**
51 * Enum used internally to know how buffering is handled.
52 *
53 * The idea is that by using an enum, BIO can be extended to support other
54 * kinds of "backend" for buffering (or just formatted I/O.)
55 */
56enum IOType
57{
58 /**
59 * The handle uses a file to read/write data.
60 */
61 IO_FILE = 0,
62
63 /**
64 * The data is stored entirely in memory.
65 */
66 IO_BUFFER,
67};
68
69
70/**
71 * Handle for buffered reading.
72 */
73struct GNUNET_BIO_ReadHandle
74{
75 /**
76 * The "backend" type.
77 */
78 enum IOType type;
79
80 /**
81 * Handle to a file on disk, if @e type is #IO_FILE.
82 */
83 struct GNUNET_DISK_FileHandle *fd;
84
85 /**
86 * Error message, NULL if there were no errors.
87 */
88 char *emsg;
89
90 /**
91 * I/O buffer. Do @b not free!
92 */
93 char *buffer;
94
95 /**
96 * Number of bytes available in @e buffer.
97 */
98 size_t have;
99
100 /**
101 * Total size of @e buffer.
102 */
103 size_t size;
104
105 /**
106 * Current read offset in @e buffer.
107 */
108 off_t pos;
109};
110
111
112/**
113 * Open a file for reading.
114 *
115 * @param fn file name to be opened
116 * @return IO handle on success, NULL on error
117 */
118struct GNUNET_BIO_ReadHandle *
119GNUNET_BIO_read_open_file (const char *fn)
120{
121 struct GNUNET_DISK_FileHandle *fd;
122 struct GNUNET_BIO_ReadHandle *h;
123
124 fd = GNUNET_DISK_file_open (fn, GNUNET_DISK_OPEN_READ, GNUNET_DISK_PERM_NONE);
125 if (NULL == fd)
126 return NULL;
127 h = GNUNET_malloc (sizeof(struct GNUNET_BIO_ReadHandle) + BIO_BUFFER_SIZE);
128 h->type = IO_FILE;
129 h->buffer = (char *) &h[1];
130 h->size = BIO_BUFFER_SIZE;
131 h->fd = fd;
132 return h;
133}
134
135
136/**
137 * Create a handle from an existing allocated buffer.
138 *
139 * @param buffer the buffer to use as source
140 * @param size the total size in bytes of the buffer
141 * @return IO handle on success, NULL on error
142 */
143struct GNUNET_BIO_ReadHandle *
144GNUNET_BIO_read_open_buffer (void *buffer, size_t size)
145{
146 struct GNUNET_BIO_ReadHandle *h;
147
148 h = GNUNET_new (struct GNUNET_BIO_ReadHandle);
149 h->type = IO_BUFFER;
150 h->buffer = buffer;
151 h->size = size;
152 return h;
153}
154
155
156/**
157 * Close an open handle. Reports if any errors reading
158 * from the file were encountered.
159 *
160 * @param h file handle
161 * @param emsg set to the (allocated) error message
162 * if the handle has an error message, the return value is #GNUNET_SYSERR
163 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
164 */
165int
166GNUNET_BIO_read_close (struct GNUNET_BIO_ReadHandle *h, char **emsg)
167{
168 int err;
169
170 err = (NULL == h->emsg) ? GNUNET_OK : GNUNET_SYSERR;
171 if (NULL != emsg)
172 *emsg = h->emsg;
173 else
174 GNUNET_free (h->emsg);
175 switch (h->type)
176 {
177 case IO_FILE:
178 GNUNET_DISK_file_close (h->fd);
179 break;
180 case IO_BUFFER:
181 break;
182 default:
183 break;
184 }
185 GNUNET_free (h);
186 return err;
187}
188
189
190/**
191 * Function used internally to read the contents of a file into a buffer.
192 *
193 * @param h the IO handle to read from
194 * @param what describes what is being read (for error message creation)
195 * @param result the buffer to write the data to
196 * @param len the number of bytes to read
197 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
198 */
199static int
200read_from_file (struct GNUNET_BIO_ReadHandle *h,
201 const char *what,
202 char *result,
203 size_t len)
204{
205 size_t pos = 0;
206 size_t min;
207 ssize_t ret;
208
209 do
210 {
211 min = h->have - h->pos;
212 if (0 < min)
213 {
214 if (len - pos < min)
215 min = len - pos;
216 GNUNET_memcpy (&result[pos], &h->buffer[h->pos], min);
217 h->pos += min;
218 pos += min;
219 }
220 if (len == pos)
221 return GNUNET_OK;
222 GNUNET_assert (((off_t) h->have) == h->pos);
223 ret = GNUNET_DISK_file_read (h->fd, h->buffer, h->size);
224 if (-1 == ret)
225 {
226 GNUNET_asprintf (&h->emsg,
227 _ ("Error reading `%s' from file: %s"),
228 what,
229 strerror (errno));
230 return GNUNET_SYSERR;
231 }
232 if (0 == ret)
233 {
234 GNUNET_asprintf (&h->emsg,
235 _ ("Error reading `%s' from file: %s"),
236 what,
237 _ ("End of file"));
238 return GNUNET_SYSERR;
239 }
240 h->pos = 0;
241 h->have = ret;
242 }
243 while (pos < len);
244 return GNUNET_OK;
245}
246
247
248/**
249 * Function used internally to read the content of a buffer into a buffer.
250 *
251 * @param h the IO handle to read from
252 * @param what describes what is being read (for error message creation)
253 * @param result the buffer to write the result to
254 * @param len the number of bytes to read
255 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
256 */
257static int
258read_from_buffer (struct GNUNET_BIO_ReadHandle *h,
259 const char *what,
260 char *result,
261 size_t len)
262{
263 if ((h->size < len) || (h->size - h->pos < len))
264 {
265 GNUNET_asprintf (&h->emsg,
266 _ ("Error while reading `%s' from buffer: %s"),
267 what,
268 _ ("Not enough data left"));
269 return GNUNET_SYSERR;
270 }
271 GNUNET_memcpy (result, h->buffer + h->pos, len);
272 h->pos += len;
273 return GNUNET_OK;
274}
275
276
277/**
278 * Read some contents into a buffer.
279 *
280 * @param h the IO handle to read from
281 * @param what describes what is being read (for error message creation)
282 * @param result the buffer to write the result to
283 * @param len the number of bytes to read
284 * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
285 */
286int
287GNUNET_BIO_read (struct GNUNET_BIO_ReadHandle *h,
288 const char *what,
289 void *result,
290 size_t len)
291{
292 char *dst = result;
293
294 if (NULL != h->emsg)
295 return GNUNET_SYSERR;
296
297 if (0 == len)
298 return GNUNET_OK;
299
300 switch (h->type)
301 {
302 case IO_FILE:
303 return read_from_file (h, what, dst, len);
304 case IO_BUFFER:
305 return read_from_buffer (h, what, dst, len);
306 default:
307 GNUNET_asprintf (&h->emsg,
308 _ ("Invalid handle type while reading `%s'"),
309 what);
310 return GNUNET_SYSERR;
311 }
312}
313
314
315/**
316 * Read 0-terminated string.
317 *
318 * @param h the IO handle to read from
319 * @param what describes what is being read (for error message creation)
320 * @param result where to store the pointer to the (allocated) string
321 * (note that *result could be set to NULL as well)
322 * @param max_length maximum allowed length for the string
323 * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
324 */
325int
326GNUNET_BIO_read_string (struct GNUNET_BIO_ReadHandle *h,
327 const char *what,
328 char **result,
329 size_t max_length)
330{
331 char *buf;
332 uint32_t big;
333
334 if (GNUNET_OK != GNUNET_BIO_read_int32 (h,
335 _ ("string length"),
336 (int32_t *) &big))
337 {
338 char *tmp = h->emsg;
339 if (NULL != tmp)
340 GNUNET_asprintf (&h->emsg,
341 _ ("%s (while reading `%s')"),
342 tmp,
343 what);
344 else
345 GNUNET_asprintf (&h->emsg,
346 _ ("Error reading length of string `%s'"),
347 what);
348 GNUNET_free (tmp);
349 return GNUNET_SYSERR;
350 }
351 if (0 == big)
352 {
353 *result = NULL;
354 return GNUNET_OK;
355 }
356 if (big > max_length)
357 {
358 GNUNET_asprintf (&h->emsg,
359 _ ("String `%s' longer than allowed (%u > %lu)"),
360 what,
361 big,
362 (unsigned long) max_length);
363 return GNUNET_SYSERR;
364 }
365 buf = GNUNET_malloc (big);
366 *result = buf;
367 buf[--big] = '\0';
368 if (0 == big)
369 return GNUNET_OK;
370 if (GNUNET_OK != GNUNET_BIO_read (h, what, buf, big))
371 {
372 GNUNET_free (buf);
373 *result = NULL;
374 return GNUNET_SYSERR;
375 }
376 return GNUNET_OK;
377}
378
379
380/**
381 * Read a metadata container.
382 *
383 * @param h handle to an open file
384 * @param what describes what is being read (for error message creation)
385 * @param result the buffer to store a pointer to the (allocated) metadata
386 * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
387 */
388int
389GNUNET_BIO_read_meta_data (struct GNUNET_BIO_ReadHandle *h,
390 const char *what,
391 struct GNUNET_CONTAINER_MetaData **result)
392{
393 uint32_t size;
394 char *buf;
395 struct GNUNET_CONTAINER_MetaData *meta;
396
397 if (GNUNET_OK != GNUNET_BIO_read_int32 (h,
398 _ ("metadata length"),
399 (int32_t *) &size))
400 return GNUNET_SYSERR;
401 if (0 == size)
402 {
403 *result = NULL;
404 return GNUNET_OK;
405 }
406 if (MAX_META_DATA < size)
407 {
408 GNUNET_asprintf (
409 &h->emsg,
410 _ ("Serialized metadata `%s' larger than allowed (%u > %u)"),
411 what,
412 size,
413 MAX_META_DATA);
414 return GNUNET_SYSERR;
415 }
416 buf = GNUNET_malloc (size);
417 if (GNUNET_OK != GNUNET_BIO_read (h, what, buf, size))
418 {
419 GNUNET_free (buf);
420 return GNUNET_SYSERR;
421 }
422 meta = GNUNET_CONTAINER_meta_data_deserialize (buf, size);
423 if (NULL == meta)
424 {
425 GNUNET_free (buf);
426 GNUNET_asprintf (&h->emsg, _ ("Failed to deserialize metadata `%s'"), what);
427 return GNUNET_SYSERR;
428 }
429 GNUNET_free (buf);
430 *result = meta;
431 return GNUNET_OK;
432}
433
434
435/**
436 * Read a float.
437 *
438 * @param h the IO handle to read from
439 * @param what describes what is being read (for error message creation)
440 * @param f address of float to read
441 */
442int
443GNUNET_BIO_read_float (struct GNUNET_BIO_ReadHandle *h,
444 const char *what,
445 float *f)
446{
447 int32_t *i = (int32_t *) f;
448 return GNUNET_BIO_read_int32 (h, what, i);
449}
450
451
452/**
453 * Read a double.
454 *
455 * @param h the IO handle to read from
456 * @param what describes what is being read (for error message creation)
457 * @param f address of double to read
458 */
459int
460GNUNET_BIO_read_double (struct GNUNET_BIO_ReadHandle *h,
461 const char *what,
462 double *f)
463{
464 int64_t *i = (int64_t *) f;
465 return GNUNET_BIO_read_int64 (h, what, i);
466}
467
468
469/**
470 * Read an (u)int32_t.
471 *
472 * @param h the IO handle to read from
473 * @param what describes what is being read (for error message creation)
474 * @param i where to store the data
475 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
476 */
477int
478GNUNET_BIO_read_int32 (struct GNUNET_BIO_ReadHandle *h,
479 const char *what,
480 int32_t *i)
481{
482 int32_t big;
483
484 if (GNUNET_OK != GNUNET_BIO_read (h, what, &big, sizeof(int32_t)))
485 return GNUNET_SYSERR;
486 *i = ntohl (big);
487 return GNUNET_OK;
488}
489
490
491/**
492 * Read an (u)int64_t.
493 *
494 * @param h the IO handle to read from
495 * @param what describes what is being read (for error message creation)
496 * @param i where to store the data
497 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
498 */
499int
500GNUNET_BIO_read_int64 (struct GNUNET_BIO_ReadHandle *h,
501 const char *what,
502 int64_t *i)
503{
504 int64_t big;
505
506 if (GNUNET_OK != GNUNET_BIO_read (h, what, &big, sizeof(int64_t)))
507 return GNUNET_SYSERR;
508 *i = GNUNET_ntohll (big);
509 return GNUNET_OK;
510}
511
512
513/**
514 * Handle for buffered writing.
515 */
516struct GNUNET_BIO_WriteHandle
517{
518 /**
519 * The "backend" type.
520 */
521 enum IOType type;
522
523 /**
524 * Handle to a file on disk, if @e type is #IO_FILE.
525 */
526 struct GNUNET_DISK_FileHandle *fd;
527
528 /**
529 * Error message, NULL if there were no errors.
530 */
531 char *emsg;
532
533 /**
534 * I/O buffer.
535 * This field is a void * because it is used to hold pointers to allocated
536 * structures or arrays and will be casted to the appropriate type.
537 */
538 void *buffer;
539
540 /**
541 * Number of bytes available in @e buffer.
542 */
543 size_t have;
544
545 /**
546 * Total size of @e buffer.
547 */
548 size_t size;
549};
550
551
552/**
553 * Open a file for writing.
554 *
555 * @param fn name of the file to be opened
556 * @return IO handle on success, NULL on error
557 */
558struct GNUNET_BIO_WriteHandle *
559GNUNET_BIO_write_open_file (const char *fn)
560{
561 struct GNUNET_DISK_FileHandle *fd;
562 struct GNUNET_BIO_WriteHandle *h;
563
564 fd =
565 GNUNET_DISK_file_open (fn,
566 GNUNET_DISK_OPEN_WRITE
567 | GNUNET_DISK_OPEN_TRUNCATE
568 | GNUNET_DISK_OPEN_CREATE,
569 GNUNET_DISK_PERM_USER_READ
570 | GNUNET_DISK_PERM_USER_WRITE);
571 if (NULL == fd)
572 return NULL;
573 h = GNUNET_malloc (sizeof(struct GNUNET_BIO_WriteHandle) + BIO_BUFFER_SIZE);
574 h->buffer = &h[1];
575 h->size = BIO_BUFFER_SIZE;
576 h->fd = fd;
577 return h;
578}
579
580
581/**
582 * Create a handle backed by an in-memory buffer.
583 *
584 * @return IO handle on success, NULL on error
585 */
586struct GNUNET_BIO_WriteHandle *
587GNUNET_BIO_write_open_buffer (void)
588{
589 struct GNUNET_BIO_WriteHandle *h;
590
591 h = GNUNET_new (struct GNUNET_BIO_WriteHandle);
592 h->type = IO_BUFFER;
593 h->buffer = (void *) GNUNET_malloc (sizeof (struct GNUNET_Buffer));
594 return h;
595}
596
597
598/**
599 * Close an IO handle.
600 * If the handle was using a file, the file will be closed.
601 *
602 * @param h file handle
603 * @param emsg set to the (allocated) error message
604 * if the handle has an error message, the return value is #GNUNET_SYSERR
605 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
606 */
607int
608GNUNET_BIO_write_close (struct GNUNET_BIO_WriteHandle *h, char **emsg)
609{
610 int err;
611
612 err = (NULL == h->emsg) ? GNUNET_OK : GNUNET_SYSERR;
613 if (NULL != emsg)
614 *emsg = h->emsg;
615 else
616 GNUNET_free (h->emsg);
617 switch (h->type)
618 {
619 case IO_FILE:
620 if (NULL == h->fd)
621 return GNUNET_SYSERR;
622 if (GNUNET_OK != GNUNET_BIO_flush (h))
623 {
624 if (NULL != emsg)
625 *emsg = h->emsg;
626 else
627 GNUNET_free (h->emsg);
628 err = GNUNET_SYSERR;
629 }
630 else
631 {
632 GNUNET_DISK_file_close (h->fd);
633 }
634 break;
635 case IO_BUFFER:
636 GNUNET_buffer_clear ((struct GNUNET_Buffer *) h->buffer);
637 GNUNET_free (h->buffer);
638 break;
639 }
640 GNUNET_free (h);
641 return err;
642}
643
644
645/**
646 * Force a file-based buffered writer to flush its buffer.
647 * If the handle does not use a file, this function returns #GNUNET_OK
648 * without doing anything.
649 *
650 * @param h the IO handle
651 * @return #GNUNET_OK upon success. Upon failure #GNUNET_SYSERR is returned
652 * and the file is closed
653 */
654int
655GNUNET_BIO_flush (struct GNUNET_BIO_WriteHandle *h)
656{
657 ssize_t ret;
658
659 if (IO_FILE != h->type)
660 return GNUNET_OK;
661
662 ret = GNUNET_DISK_file_write (h->fd, h->buffer, h->have);
663 if (ret != (ssize_t) h->have)
664 {
665 GNUNET_DISK_file_close (h->fd);
666 h->fd = NULL;
667 GNUNET_free (h->emsg);
668 GNUNET_asprintf (&h->emsg, _ ("Unable to flush buffer to file"));
669 return GNUNET_SYSERR;
670 }
671 h->have = 0;
672 return GNUNET_OK;
673}
674
675
676/**
677 * Get the IO handle's contents.
678 * If the handle doesn't use an in-memory buffer, this function returns
679 * #GNUNET_SYSERR.
680 *
681 * @param h the IO handle
682 * @param emsg set to the (allocated) error message
683 * if the handle has an error message the return value is #GNUNET_SYSERR
684 * @param contents where to store the pointer to the handle's contents
685 * @param size where to store the size of @e contents
686 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
687 */
688int
689GNUNET_BIO_get_buffer_contents (struct GNUNET_BIO_WriteHandle *h,
690 char **emsg,
691 void **contents,
692 size_t *size)
693{
694 if (IO_BUFFER != h->type)
695 return GNUNET_SYSERR;
696 if ((NULL == contents) || (NULL == size))
697 return GNUNET_SYSERR;
698 int ret = (NULL != h->emsg) ? GNUNET_SYSERR : GNUNET_OK;
699 if (NULL != emsg)
700 *emsg = h->emsg;
701 else
702 GNUNET_free (h->emsg);
703 *contents = GNUNET_buffer_reap ((struct GNUNET_Buffer *) h->buffer, size);
704 return ret;
705}
706
707
708/**
709 * Function used internally to write the contents of a buffer into a file.
710 *
711 * @param h the IO handle to write to
712 * @param what describes what is being written (for error message creation)
713 * @param source the buffer to write
714 * @param len the number of bytes to write
715 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
716 */
717static int
718write_to_file (struct GNUNET_BIO_WriteHandle *h,
719 const char *what,
720 const char *source,
721 size_t len)
722{
723 size_t min;
724 size_t pos = 0;
725 char *buffer = (char *) h->buffer;
726
727 if (NULL == h->fd)
728 {
729 GNUNET_asprintf (&h->emsg,
730 _ ("Error while writing `%s' to file: %s"),
731 what,
732 _ ("No associated file"));
733 return GNUNET_SYSERR;
734 }
735
736 do
737 {
738 min = h->size - h->have;
739 if (len - pos < min)
740 min = len - pos;
741 GNUNET_memcpy (&buffer[h->have], &source[pos], min);
742 pos += min;
743 h->have += min;
744 if (len == pos)
745 return GNUNET_OK;
746 GNUNET_assert (h->have == h->size);
747 if (GNUNET_OK != GNUNET_BIO_flush (h))
748 {
749 char *tmp = h->emsg;
750 GNUNET_asprintf (&h->emsg,
751 _ ("Error while writing `%s' to file: %s"),
752 what,
753 tmp);
754 GNUNET_free (tmp);
755 return GNUNET_SYSERR;
756 }
757 }
758 while (pos < len);
759 GNUNET_break (0);
760 return GNUNET_OK;
761}
762
763
764/**
765 * Function used internally to write the contents of a buffer to another buffer.
766 *
767 * @param h the IO handle to write to
768 * @param what describes what is being written (for error message creation)
769 * @param source the buffer to write
770 * @param len the number of bytes to write
771 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
772 */
773static int
774write_to_buffer (struct GNUNET_BIO_WriteHandle *h,
775 const char *what,
776 const char *source,
777 size_t len)
778{
779 GNUNET_buffer_write ((struct GNUNET_Buffer *) h->buffer, source, len);
780 h->have += len;
781 return GNUNET_OK;
782}
783
784
785/**
786 * Write a buffer to a handle.
787 *
788 * @param h the IO handle to write to
789 * @param what what is being written (for error message creation)
790 * @param buffer the data to write
791 * @param n number of bytes to write
792 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
793 */
794int
795GNUNET_BIO_write (struct GNUNET_BIO_WriteHandle *h,
796 const char *what,
797 const void *buffer,
798 size_t n)
799{
800 const char *src = buffer;
801
802 if (NULL != h->emsg)
803 return GNUNET_SYSERR;
804
805 if (0 == n)
806 return GNUNET_OK;
807
808 switch (h->type)
809 {
810 case IO_FILE:
811 return write_to_file (h, what, src, n);
812 case IO_BUFFER:
813 return write_to_buffer (h, what, src, n);
814 default:
815 GNUNET_asprintf (&h->emsg,
816 _ ("Invalid handle type while writing `%s'"),
817 what);
818 return GNUNET_SYSERR;
819 }
820}
821
822
823/**
824 * Write a 0-terminated string.
825 *
826 * @param h the IO handle to write to
827 * @param what what is being written (for error message creation)
828 * @param s string to write (can be NULL)
829 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
830 */
831int
832GNUNET_BIO_write_string (struct GNUNET_BIO_WriteHandle *h,
833 const char *what,
834 const char *s)
835{
836 uint32_t slen;
837
838 slen = (uint32_t) ((s == NULL) ? 0 : strlen (s) + 1);
839 if (GNUNET_OK != GNUNET_BIO_write_int32 (h, _ ("string length"), slen))
840 return GNUNET_SYSERR;
841 if (0 != slen)
842 return GNUNET_BIO_write (h, what, s, slen - 1);
843 return GNUNET_OK;
844}
845
846
847/**
848 * Write a metadata container.
849 *
850 * @param h the IO handle to write to
851 * @param what what is being written (for error message creation)
852 * @param m metadata to write
853 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
854 */
855int
856GNUNET_BIO_write_meta_data (struct GNUNET_BIO_WriteHandle *h,
857 const char *what,
858 const struct GNUNET_CONTAINER_MetaData *m)
859{
860 ssize_t size;
861 char *buf;
862
863 if (m == NULL)
864 return GNUNET_BIO_write_int32 (h, _ ("metadata length"), 0);
865 buf = NULL;
866 size = GNUNET_CONTAINER_meta_data_serialize (
867 m,
868 &buf,
869 MAX_META_DATA,
870 GNUNET_CONTAINER_META_DATA_SERIALIZE_PART);
871 if (-1 == size)
872 {
873 GNUNET_free (buf);
874 GNUNET_free (h->emsg);
875 GNUNET_asprintf (&h->emsg,
876 _ ("Failed to serialize metadata `%s'"),
877 what);
878 return GNUNET_SYSERR;
879 }
880 if ((GNUNET_OK != GNUNET_BIO_write_int32 (h,
881 _ ("metadata length"),
882 (uint32_t) size))
883 || (GNUNET_OK != GNUNET_BIO_write (h, what, buf, size)))
884 {
885 GNUNET_free (buf);
886 return GNUNET_SYSERR;
887 }
888 GNUNET_free (buf);
889 return GNUNET_OK;
890}
891
892
893/**
894 * Write a float.
895 *
896 * @param h the IO handle to write to
897 * @param what what is being written (for error message creation)
898 * @param f float to write
899 */
900int
901GNUNET_BIO_write_float (struct GNUNET_BIO_WriteHandle *h,
902 const char *what,
903 float f)
904{
905 int32_t i = f;
906 return GNUNET_BIO_write_int32 (h, what, i);
907}
908
909
910/**
911 * Write a double.
912 *
913 * @param h the IO handle to write to
914 * @param what what is being written (for error message creation)
915 * @param f double to write
916 */
917int
918GNUNET_BIO_write_double (struct GNUNET_BIO_WriteHandle *h,
919 const char *what,
920 double f)
921{
922 int64_t i = f;
923 return GNUNET_BIO_write_int64 (h, what, i);
924}
925
926
927/**
928 * Write an (u)int32_t.
929 *
930 * @param h the IO handle to write to
931 * @param what what is being written (for error message creation)
932 * @param i 32-bit integer to write
933 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
934 */
935int
936GNUNET_BIO_write_int32 (struct GNUNET_BIO_WriteHandle *h,
937 const char *what,
938 int32_t i)
939{
940 int32_t big;
941
942 big = htonl (i);
943 return GNUNET_BIO_write (h, what, &big, sizeof(int32_t));
944}
945
946
947/**
948 * Write an (u)int64_t.
949 *
950 * @param h the IO handle to write to
951 * @param what what is being written (for error message creation)
952 * @param i 64-bit integer to write
953 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
954 */
955int
956GNUNET_BIO_write_int64 (struct GNUNET_BIO_WriteHandle *h,
957 const char *what,
958 int64_t i)
959{
960 int64_t big;
961
962 big = GNUNET_htonll (i);
963 return GNUNET_BIO_write (h, what, &big, sizeof(int64_t));
964}
965
966
967/**
968 * Function used internally to read some bytes from within a read spec.
969 *
970 * @param cls ignored, always NULL
971 * @param h the IO handle to read from
972 * @param what what is being read (for error message creation)
973 * @param target where to store the data
974 * @param target_size how many bytes to read
975 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
976 */
977static int
978read_spec_handler_object (void *cls,
979 struct GNUNET_BIO_ReadHandle *h,
980 const char *what,
981 void *target,
982 size_t target_size)
983{
984 return GNUNET_BIO_read (h, what, target, target_size);
985}
986
987
988/**
989 * Create the specification to read a certain amount of bytes.
990 *
991 * @param what describes what is being read (for error message creation)
992 * @param result the buffer to write the result to
993 * @param len the number of bytes to read
994 * @return the read spec
995 */
996struct GNUNET_BIO_ReadSpec
997GNUNET_BIO_read_spec_object (const char *what,
998 void *result,
999 size_t len)
1000{
1001 struct GNUNET_BIO_ReadSpec rs = {
1002 .rh = &read_spec_handler_object,
1003 .cls = NULL,
1004 .what = what,
1005 .target = result,
1006 .size = len,
1007 };
1008
1009 return rs;
1010}
1011
1012
1013/**
1014 * Function used internally to read a string from within a read spec.
1015 *
1016 * @param cls ignored, always NULL
1017 * @param h the IO handle to read from
1018 * @param what what is being read (for error message creation)
1019 * @param target where to store the data
1020 * @param target_size how many bytes to read
1021 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
1022 */
1023static int
1024read_spec_handler_string (void *cls,
1025 struct GNUNET_BIO_ReadHandle *h,
1026 const char *what,
1027 void *target,
1028 size_t target_size)
1029{
1030 char **result = target;
1031 return GNUNET_BIO_read_string (h, what, result, target_size);
1032}
1033
1034
1035/**
1036 * Create the specification to read a 0-terminated string.
1037 *
1038 * @param what describes what is being read (for error message creation)
1039 * @param result where to store the pointer to the (allocated) string
1040 * (note that *result could be set to NULL as well)
1041 * @param max_length maximum allowed length for the string
1042 * @return the read spec
1043 */
1044struct GNUNET_BIO_ReadSpec
1045GNUNET_BIO_read_spec_string (const char *what,
1046 char **result,
1047 size_t max_length)
1048{
1049 struct GNUNET_BIO_ReadSpec rs = {
1050 .rh = &read_spec_handler_string,
1051 .cls = NULL,
1052 .target = result,
1053 .size = max_length,
1054 };
1055
1056 return rs;
1057}
1058
1059
1060/**
1061 * Function used internally to read a metadata container from within a read
1062 * spec.
1063 *
1064 * @param cls ignored, always NULL
1065 * @param h the IO handle to read from
1066 * @param what what is being read (for error message creation)
1067 * @param target where to store the data
1068 * @param target_size ignored
1069 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
1070 */
1071static int
1072read_spec_handler_meta_data (void *cls,
1073 struct GNUNET_BIO_ReadHandle *h,
1074 const char *what,
1075 void *target,
1076 size_t target_size)
1077{
1078 struct GNUNET_CONTAINER_MetaData **result = target;
1079 return GNUNET_BIO_read_meta_data (h, what, result);
1080}
1081
1082
1083/**
1084 * Create the specification to read a metadata container.
1085 *
1086 * @param what describes what is being read (for error message creation)
1087 * @param result the buffer to store a pointer to the (allocated) metadata
1088 * @return the read spec
1089 */
1090struct GNUNET_BIO_ReadSpec
1091GNUNET_BIO_read_spec_meta_data (const char *what,
1092 struct GNUNET_CONTAINER_MetaData **result)
1093{
1094 struct GNUNET_BIO_ReadSpec rs = {
1095 .rh = &read_spec_handler_meta_data,
1096 .cls = NULL,
1097 .target = result,
1098 .size = 0,
1099 };
1100
1101 return rs;
1102}
1103
1104
1105/**
1106 * Function used internally to read an (u)int32_t from within a read spec.
1107 *
1108 * @param cls ignored, always NULL
1109 * @param h the IO handle to read from
1110 * @param what what is being read (for error message creation)
1111 * @param target where to store the data
1112 * @param target_size ignored
1113 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
1114 */
1115static int
1116read_spec_handler_int32 (void *cls,
1117 struct GNUNET_BIO_ReadHandle *h,
1118 const char *what,
1119 void *target,
1120 size_t target_size)
1121{
1122 int32_t *result = target;
1123 return GNUNET_BIO_read_int32 (h, what, result);
1124}
1125
1126
1127/**
1128 * Create the specification to read an (u)int32_t.
1129 *
1130 * @param what describes what is being read (for error message creation)
1131 * @param i where to store the data
1132 * @return the read spec
1133 */
1134struct GNUNET_BIO_ReadSpec
1135GNUNET_BIO_read_spec_int32 (const char *what,
1136 int32_t *i)
1137{
1138 struct GNUNET_BIO_ReadSpec rs = {
1139 .rh = &read_spec_handler_int32,
1140 .cls = NULL,
1141 .target = i,
1142 .size = 0,
1143 };
1144
1145 return rs;
1146}
1147
1148
1149/**
1150 * Function used internally to read an (u)int64_t from within a read spec.
1151 *
1152 * @param cls ignored, always NULL
1153 * @param h the IO handle to read from
1154 * @param what what is being read (for error message creation)
1155 * @param target where to store the data
1156 * @param target_size ignored
1157 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
1158 */
1159static int
1160read_spec_handler_int64 (void *cls,
1161 struct GNUNET_BIO_ReadHandle *h,
1162 const char *what,
1163 void *target,
1164 size_t target_size)
1165{
1166 int64_t *result = target;
1167 return GNUNET_BIO_read_int64 (h, what, result);
1168}
1169
1170
1171/**
1172 * Create the specification to read an (u)int64_t.
1173 *
1174 * @param what describes what is being read (for error message creation)
1175 * @param i where to store the data
1176 * @return the read spec
1177 */
1178struct GNUNET_BIO_ReadSpec
1179GNUNET_BIO_read_spec_int64 (const char *what,
1180 int64_t *i)
1181{
1182 struct GNUNET_BIO_ReadSpec rs = {
1183 .rh = &read_spec_handler_int64,
1184 .cls = NULL,
1185 .target = i,
1186 .size = 0,
1187 };
1188
1189 return rs;
1190}
1191
1192
1193/**
1194 * Create the specification to read a float.
1195 *
1196 * @param what describes what is being read (for error message creation)
1197 * @param f address of float to read
1198 */
1199struct GNUNET_BIO_ReadSpec
1200GNUNET_BIO_read_spec_float (const char *what, float *f)
1201{
1202 struct GNUNET_BIO_ReadSpec rs = {
1203 .rh = &read_spec_handler_int32,
1204 .cls = NULL,
1205 .target = (int32_t *) f,
1206 .size = 0,
1207 };
1208
1209 return rs;
1210}
1211
1212
1213/**
1214 * Create the specification to read a double.
1215 *
1216 * @param what describes what is being read (for error message creation)
1217 * @param f address of double to read
1218 */
1219struct GNUNET_BIO_ReadSpec
1220GNUNET_BIO_read_spec_double (const char *what, double *f)
1221{
1222 struct GNUNET_BIO_ReadSpec rs = {
1223 .rh = &read_spec_handler_int64,
1224 .cls = NULL,
1225 .target = (int64_t *) f,
1226 .size = 0,
1227 };
1228
1229 return rs;
1230}
1231
1232
1233/**
1234 * Execute the read specifications in order.
1235 *
1236 * @param h the IO handle to read from
1237 * @param rs array of read specs
1238 * the last element must be #GNUNET_BIO_read_spec_end
1239 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
1240 */
1241int
1242GNUNET_BIO_read_spec_commit (struct GNUNET_BIO_ReadHandle *h,
1243 struct GNUNET_BIO_ReadSpec *rs)
1244{
1245 int ret = GNUNET_OK;
1246
1247 for (size_t i = 0; NULL!=rs[i].rh; ++i)
1248 {
1249 ret = rs[i].rh (rs[i].cls, h, rs[i].what, rs[i].target, rs[i].size);
1250 if (GNUNET_OK != ret)
1251 return ret;
1252 }
1253
1254 return ret;
1255}
1256
1257
1258/**
1259 * Function used internally to write some bytes from within a write spec.
1260 *
1261 * @param cls ignored, always NULL
1262 * @param h the IO handle to write to
1263 * @param what what is being written (for error message creation)
1264 * @param source the data to write
1265 * @param source_size how many bytes to write
1266 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
1267 */
1268static int
1269write_spec_handler_object (void *cls,
1270 struct GNUNET_BIO_WriteHandle *h,
1271 const char *what,
1272 void *source,
1273 size_t source_size)
1274{
1275 return GNUNET_BIO_write (h, what, source, source_size);
1276}
1277
1278
1279/**
1280 * Create the specification to read some bytes.
1281 *
1282 * @param what describes what is being written (for error message creation)
1283 * @param source the data to write
1284 * @param size how many bytes should be written
1285 * @return the write spec
1286 */
1287struct GNUNET_BIO_WriteSpec
1288GNUNET_BIO_write_spec_object (const char *what,
1289 void *source,
1290 size_t size)
1291{
1292 struct GNUNET_BIO_WriteSpec ws = {
1293 .wh = &write_spec_handler_object,
1294 .cls = NULL,
1295 .what = what,
1296 .source = source,
1297 .source_size = size,
1298 };
1299
1300 return ws;
1301}
1302
1303
1304/**
1305 * Function used internally to write a 0-terminated string from within a write
1306 * spec.
1307 *
1308 * @param cls ignored, always NULL
1309 * @param h the IO handle to write to
1310 * @param what what is being written (for error message creation)
1311 * @param source the data to write
1312 * @param source_size ignored
1313 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
1314 */
1315static int
1316write_spec_handler_string (void *cls,
1317 struct GNUNET_BIO_WriteHandle *h,
1318 const char *what,
1319 void *source,
1320 size_t source_size)
1321{
1322 const char *s = source;
1323 return GNUNET_BIO_write_string (h, what, s);
1324}
1325
1326
1327/**
1328 * Create the specification to write a 0-terminated string.
1329 *
1330 * @param what describes what is being read (for error message creation)
1331 * @param s string to write (can be NULL)
1332 * @return the read spec
1333 */
1334struct GNUNET_BIO_WriteSpec
1335GNUNET_BIO_write_spec_string (const char *what,
1336 const char *s)
1337{
1338 struct GNUNET_BIO_WriteSpec ws = {
1339 .wh = &write_spec_handler_string,
1340 .cls = NULL,
1341 .what = what,
1342 .source = (void *) s,
1343 .source_size = 0,
1344 };
1345
1346 return ws;
1347}
1348
1349
1350/**
1351 * Function used internally to write a metadata container from within a write
1352 * spec.
1353 *
1354 * @param cls ignored, always NULL
1355 * @param h the IO handle to write to
1356 * @param what what is being written (for error message creation)
1357 * @param source the data to write
1358 * @param source_size ignored
1359 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
1360 */
1361static int
1362write_spec_handler_meta_data (void *cls,
1363 struct GNUNET_BIO_WriteHandle *h,
1364 const char *what,
1365 void *source,
1366 size_t source_size)
1367{
1368 const struct GNUNET_CONTAINER_MetaData *m = source;
1369 return GNUNET_BIO_write_meta_data (h, what, m);
1370}
1371
1372
1373/**
1374 * Create the specification to write a metadata container.
1375 *
1376 * @param what what is being written (for error message creation)
1377 * @param m metadata to write
1378 * @return the write spec
1379 */
1380struct GNUNET_BIO_WriteSpec
1381GNUNET_BIO_write_spec_meta_data (const char *what,
1382 const struct GNUNET_CONTAINER_MetaData *m)
1383{
1384 struct GNUNET_BIO_WriteSpec ws = {
1385 .wh = &write_spec_handler_meta_data,
1386 .cls = NULL,
1387 .what = what,
1388 .source = (void *) m,
1389 .source_size = 0,
1390 };
1391
1392 return ws;
1393}
1394
1395
1396/**
1397 * Function used internally to write an (u)int32_t from within a write spec.
1398 *
1399 * @param cls ignored, always NULL
1400 * @param h the IO handle to write to
1401 * @param what what is being written (for error message creation)
1402 * @param source the data to write
1403 * @param source_size ignored
1404 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
1405 */
1406static int
1407write_spec_handler_int32 (void *cls,
1408 struct GNUNET_BIO_WriteHandle *h,
1409 const char *what,
1410 void *source,
1411 size_t source_size)
1412{
1413 int32_t i = *(int32_t *) source;
1414 return GNUNET_BIO_write_int32 (h, what, i);
1415}
1416
1417
1418/**
1419 * Create the specification to write an (u)int32_t.
1420 *
1421 * @param what describes what is being written (for error message creation)
1422 * @param i pointer to a 32-bit integer
1423 * @return the write spec
1424 */
1425struct GNUNET_BIO_WriteSpec
1426GNUNET_BIO_write_spec_int32 (const char *what,
1427 int32_t *i)
1428{
1429 struct GNUNET_BIO_WriteSpec ws = {
1430 .wh = &write_spec_handler_int32,
1431 .cls = NULL,
1432 .what = what,
1433 .source = i,
1434 .source_size = 0,
1435 };
1436
1437 return ws;
1438}
1439
1440
1441/**
1442 * Function used internally to write an (u)int64_t from within a write spec.
1443 *
1444 * @param cls ignored, always NULL
1445 * @param h the IO handle to write to
1446 * @param what what is being written (for error message creation)
1447 * @param source the data to write
1448 * @param source_size ignored
1449 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
1450 */
1451static int
1452write_spec_handler_int64 (void *cls,
1453 struct GNUNET_BIO_WriteHandle *h,
1454 const char *what,
1455 void *source,
1456 size_t source_size)
1457{
1458 int64_t i = *(int64_t *) source;
1459 return GNUNET_BIO_write_int64 (h, what, i);
1460}
1461
1462
1463/**
1464 * Create the specification to write an (u)int64_t.
1465 *
1466 * @param what describes what is being written (for error message creation)
1467 * @param i pointer to a 64-bit integer
1468 * @return the write spec
1469 */
1470struct GNUNET_BIO_WriteSpec
1471GNUNET_BIO_write_spec_int64 (const char *what,
1472 int64_t *i)
1473{
1474 struct GNUNET_BIO_WriteSpec ws = {
1475 .wh = &write_spec_handler_int64,
1476 .cls = NULL,
1477 .what = what,
1478 .source = i,
1479 .source_size = 0,
1480 };
1481
1482 return ws;
1483}
1484
1485
1486/**
1487 * Create the specification to write a float.
1488 *
1489 * @param what describes what is being written (for error message creation)
1490 * @param f pointer to a float
1491 * @return the write spec
1492 */
1493struct GNUNET_BIO_WriteSpec
1494GNUNET_BIO_write_spec_float (const char *what, float *f)
1495{
1496 struct GNUNET_BIO_WriteSpec ws = {
1497 .wh = &write_spec_handler_int32,
1498 .cls = NULL,
1499 .what = what,
1500 .source = (int32_t *) f,
1501 .source_size = 0,
1502 };
1503
1504 return ws;
1505}
1506
1507
1508/**
1509 * Create the specification to write an double.
1510 *
1511 * @param what describes what is being written (for error message creation)
1512 * @param f pointer to a double
1513 * @return the write spec
1514 */
1515struct GNUNET_BIO_WriteSpec
1516GNUNET_BIO_write_spec_double (const char *what, double *f)
1517{
1518 struct GNUNET_BIO_WriteSpec ws = {
1519 .wh = &write_spec_handler_int64,
1520 .cls = NULL,
1521 .what = what,
1522 .source = (int64_t *) f,
1523 .source_size = 0,
1524 };
1525
1526 return ws;
1527}
1528
1529
1530/**
1531 * Execute the write specifications in order.
1532 *
1533 * @param h the IO handle to write to
1534 * @param ws array of write specs
1535 * the last element must be #GNUNET_BIO_write_spec_end
1536 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
1537 */
1538int
1539GNUNET_BIO_write_spec_commit (struct GNUNET_BIO_WriteHandle *h,
1540 struct GNUNET_BIO_WriteSpec *ws)
1541{
1542 int ret = GNUNET_OK;
1543
1544 for (size_t i = 0; NULL!=ws[i].wh; ++i)
1545 {
1546 ret = ws[i].wh (ws[i].cls, h, ws[i].what, ws[i].source, ws[i].source_size);
1547 if (GNUNET_OK != ret)
1548 return ret;
1549 }
1550
1551 /* If it's a file-based handle, the flush makes sure that the data in the
1552 buffer is actually written to the disk. */
1553 if (IO_FILE == h->type)
1554 ret = GNUNET_BIO_flush (h);
1555
1556 return ret;
1557}
1558
1559
1560/* end of bio.c */