diff options
Diffstat (limited to 'src/util/bio.c')
-rw-r--r-- | src/util/bio.c | 1560 |
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 | */ | ||
56 | enum 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 | */ | ||
73 | struct 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 | */ | ||
118 | struct GNUNET_BIO_ReadHandle * | ||
119 | GNUNET_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 | */ | ||
143 | struct GNUNET_BIO_ReadHandle * | ||
144 | GNUNET_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 | */ | ||
165 | int | ||
166 | GNUNET_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 | */ | ||
199 | static int | ||
200 | read_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 | */ | ||
257 | static int | ||
258 | read_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 | */ | ||
286 | int | ||
287 | GNUNET_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 | */ | ||
325 | int | ||
326 | GNUNET_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 | */ | ||
388 | int | ||
389 | GNUNET_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 | */ | ||
442 | int | ||
443 | GNUNET_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 | */ | ||
459 | int | ||
460 | GNUNET_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 | */ | ||
477 | int | ||
478 | GNUNET_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 | */ | ||
499 | int | ||
500 | GNUNET_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 | */ | ||
516 | struct 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 | */ | ||
558 | struct GNUNET_BIO_WriteHandle * | ||
559 | GNUNET_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 | */ | ||
586 | struct GNUNET_BIO_WriteHandle * | ||
587 | GNUNET_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 | */ | ||
607 | int | ||
608 | GNUNET_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 | */ | ||
654 | int | ||
655 | GNUNET_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 | */ | ||
688 | int | ||
689 | GNUNET_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 | */ | ||
717 | static int | ||
718 | write_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 | */ | ||
773 | static int | ||
774 | write_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 | */ | ||
794 | int | ||
795 | GNUNET_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 | */ | ||
831 | int | ||
832 | GNUNET_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 | */ | ||
855 | int | ||
856 | GNUNET_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 | */ | ||
900 | int | ||
901 | GNUNET_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 | */ | ||
917 | int | ||
918 | GNUNET_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 | */ | ||
935 | int | ||
936 | GNUNET_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 | */ | ||
955 | int | ||
956 | GNUNET_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 | */ | ||
977 | static int | ||
978 | read_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 | */ | ||
996 | struct GNUNET_BIO_ReadSpec | ||
997 | GNUNET_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 | */ | ||
1023 | static int | ||
1024 | read_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 | */ | ||
1044 | struct GNUNET_BIO_ReadSpec | ||
1045 | GNUNET_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 | */ | ||
1071 | static int | ||
1072 | read_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 | */ | ||
1090 | struct GNUNET_BIO_ReadSpec | ||
1091 | GNUNET_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 | */ | ||
1115 | static int | ||
1116 | read_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 | */ | ||
1134 | struct GNUNET_BIO_ReadSpec | ||
1135 | GNUNET_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 | */ | ||
1159 | static int | ||
1160 | read_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 | */ | ||
1178 | struct GNUNET_BIO_ReadSpec | ||
1179 | GNUNET_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 | */ | ||
1199 | struct GNUNET_BIO_ReadSpec | ||
1200 | GNUNET_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 | */ | ||
1219 | struct GNUNET_BIO_ReadSpec | ||
1220 | GNUNET_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 | */ | ||
1241 | int | ||
1242 | GNUNET_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 | */ | ||
1268 | static int | ||
1269 | write_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 | */ | ||
1287 | struct GNUNET_BIO_WriteSpec | ||
1288 | GNUNET_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 | */ | ||
1315 | static int | ||
1316 | write_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 | */ | ||
1334 | struct GNUNET_BIO_WriteSpec | ||
1335 | GNUNET_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 | */ | ||
1361 | static int | ||
1362 | write_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 | */ | ||
1380 | struct GNUNET_BIO_WriteSpec | ||
1381 | GNUNET_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 | */ | ||
1406 | static int | ||
1407 | write_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 | */ | ||
1425 | struct GNUNET_BIO_WriteSpec | ||
1426 | GNUNET_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 | */ | ||
1451 | static int | ||
1452 | write_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 | */ | ||
1470 | struct GNUNET_BIO_WriteSpec | ||
1471 | GNUNET_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 | */ | ||
1493 | struct GNUNET_BIO_WriteSpec | ||
1494 | GNUNET_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 | */ | ||
1515 | struct GNUNET_BIO_WriteSpec | ||
1516 | GNUNET_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 | */ | ||
1538 | int | ||
1539 | GNUNET_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 */ | ||