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