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