aboutsummaryrefslogtreecommitdiff
path: root/src/util
diff options
context:
space:
mode:
Diffstat (limited to 'src/util')
-rw-r--r--src/util/bio.c1219
-rw-r--r--src/util/buffer.c23
-rw-r--r--src/util/test_bio.c601
3 files changed, 1428 insertions, 415 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 */
56enum IOType
57{
58 /**
59 * The handle uses a file to read/write data.
60 */
61 IO_FILE = 0,
62
63 /**
64 * The data is stored entirely in memory.
65 */
66 IO_BUFFER,
67};
68
69
70/**
51 * Handle for buffered reading. 71 * Handle for buffered reading.
52 */ 72 */
53struct GNUNET_BIO_ReadHandle 73struct 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 */
93struct GNUNET_BIO_ReadHandle * 118struct GNUNET_BIO_ReadHandle *
94GNUNET_BIO_read_open (const char *fn) 119GNUNET_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 */
143struct GNUNET_BIO_ReadHandle *
144GNUNET_BIO_read_open_buffer (void *buffer, size_t size)
145{
146 struct GNUNET_BIO_ReadHandle *h;
147
148 h = GNUNET_new (struct GNUNET_BIO_ReadHandle);
149 h->type = IO_BUFFER;
150 h->buffer = buffer;
151 h->size = size;
152 return h;
153}
154
155
156/**
157 * Close an open handle. Reports if any errors reading
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 */
118int 165int
@@ -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 */
143int 199static int
144GNUNET_BIO_read (struct GNUNET_BIO_ReadHandle *h, 200read_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 */
257static int
258read_from_buffer (struct GNUNET_BIO_ReadHandle *h,
259 const char *what,
260 char *result,
261 size_t len)
262{
263 if (h->size < len || h->size - h->pos < len)
264 {
265 GNUNET_asprintf (&h->emsg,
266 _ ("Error while reading `%s' from buffer: %s"),
267 what,
268 _ ("Not enough data left"));
269 return GNUNET_SYSERR;
270 }
271 GNUNET_memcpy (result, h->buffer + h->pos, len);
272 h->pos += len;
273 return GNUNET_OK;
274}
275
276
277/**
278 * Read some contents into a buffer.
279 *
280 * @param h the IO handle to read from
281 * @param what describes what is being read (for error message creation)
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 */
208int 286int
209GNUNET_BIO_read_fn (struct GNUNET_BIO_ReadHandle *h, 287GNUNET_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 */
441int
442GNUNET_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 */
458int
459GNUNET_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 */
337int 476int
338GNUNET_BIO_read_int32__ (struct GNUNET_BIO_ReadHandle *h, 477GNUNET_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 */
361int 498int
362GNUNET_BIO_read_int64__ (struct GNUNET_BIO_ReadHandle *h, 499GNUNET_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,
379struct GNUNET_BIO_WriteHandle 515struct 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 */
409struct GNUNET_BIO_WriteHandle * 557struct GNUNET_BIO_WriteHandle *
410GNUNET_BIO_write_open (const char *fn) 558GNUNET_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 */
585struct GNUNET_BIO_WriteHandle *
586GNUNET_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 */
437int 606int
438GNUNET_BIO_write_close (struct GNUNET_BIO_WriteHandle *h) 607GNUNET_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 */
457int 653int
458GNUNET_BIO_flush (struct GNUNET_BIO_WriteHandle *h) 654GNUNET_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 */
482int 687int
483GNUNET_BIO_write (struct GNUNET_BIO_WriteHandle *h, 688GNUNET_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 */
716static int
717write_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 */
772static int
773write_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 */
793int
794GNUNET_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 */
522int 830int
523GNUNET_BIO_write_string (struct GNUNET_BIO_WriteHandle *h, const char *s) 831GNUNET_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 */
543int 854int
544GNUNET_BIO_write_meta_data (struct GNUNET_BIO_WriteHandle *h, 855GNUNET_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 */
899int
900GNUNET_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 */
916int
917GNUNET_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 */
581int 934int
582GNUNET_BIO_write_int32 (struct GNUNET_BIO_WriteHandle *h, int32_t i) 935GNUNET_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 */
598int 954int
599GNUNET_BIO_write_int64 (struct GNUNET_BIO_WriteHandle *h, int64_t i) 955GNUNET_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 */
976static int
977read_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 */
995struct GNUNET_BIO_ReadSpec
996GNUNET_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 */
1022static int
1023read_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 */
1043struct GNUNET_BIO_ReadSpec
1044GNUNET_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 */
1070static int
1071read_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 */
1089struct GNUNET_BIO_ReadSpec
1090GNUNET_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 */
1114static int
1115read_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 */
1133struct GNUNET_BIO_ReadSpec
1134GNUNET_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 */
1158static int
1159read_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 */
1177struct GNUNET_BIO_ReadSpec
1178GNUNET_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 */
1198struct GNUNET_BIO_ReadSpec
1199GNUNET_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 */
1218struct GNUNET_BIO_ReadSpec
1219GNUNET_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 */
1240int
1241GNUNET_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 */
1267static int
1268write_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 */
1286struct GNUNET_BIO_WriteSpec
1287GNUNET_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 */
1314static int
1315write_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 */
1333struct GNUNET_BIO_WriteSpec
1334GNUNET_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 */
1360static int
1361write_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 */
1379struct GNUNET_BIO_WriteSpec
1380GNUNET_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 */
1405static int
1406write_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 */
1424struct GNUNET_BIO_WriteSpec
1425GNUNET_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 */
1450static int
1451write_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 */
1469struct GNUNET_BIO_WriteSpec
1470GNUNET_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 */
1492struct GNUNET_BIO_WriteSpec
1493GNUNET_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 */
1514struct GNUNET_BIO_WriteSpec
1515GNUNET_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 */
1537int
1538GNUNET_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
diff --git a/src/util/buffer.c b/src/util/buffer.c
index dabf630c7..c865f6307 100644
--- a/src/util/buffer.c
+++ b/src/util/buffer.c
@@ -130,7 +130,26 @@ GNUNET_buffer_reap_str (struct GNUNET_Buffer *buf)
130 buf->mem[buf->position++] = '\0'; 130 buf->mem[buf->position++] = '\0';
131 } 131 }
132 res = buf->mem; 132 res = buf->mem;
133 *buf = (struct GNUNET_Buffer) { 0 }; 133 memset (buf, 0, sizeof (struct GNUNET_Buffer));
134 return res;
135}
136
137
138/**
139 * Clear the buffer and return its contents.
140 * The caller is responsible to eventually #GNUNET_free
141 * the returned data.
142 *
143 * @param buf the buffer to reap the contents from
144 * @param size where to store the size of the returned data
145 * @returns the data contained in the string
146 */
147void *
148GNUNET_buffer_reap (struct GNUNET_Buffer *buf, size_t *size)
149{
150 *size = buf->position;
151 void *res = buf->mem;
152 memset (buf, 0, sizeof (struct GNUNET_Buffer));
134 return res; 153 return res;
135} 154}
136 155
@@ -144,7 +163,7 @@ void
144GNUNET_buffer_clear (struct GNUNET_Buffer *buf) 163GNUNET_buffer_clear (struct GNUNET_Buffer *buf)
145{ 164{
146 GNUNET_free_non_null (buf->mem); 165 GNUNET_free_non_null (buf->mem);
147 *buf = (struct GNUNET_Buffer) { 0 }; 166 memset (buf, 0, sizeof (struct GNUNET_Buffer));
148} 167}
149 168
150 169
diff --git a/src/util/test_bio.c b/src/util/test_bio.c
index 53b45c23a..0c8453121 100644
--- a/src/util/test_bio.c
+++ b/src/util/test_bio.c
@@ -30,363 +30,406 @@
30#define TESTSTRING "testString" 30#define TESTSTRING "testString"
31#define TESTNUMBER64 ((int64_t) 100000L) 31#define TESTNUMBER64 ((int64_t) 100000L)
32 32
33
33static int 34static int
34test_normal_rw () 35test_normal_rw (void)
35{ 36{
36 char *msg; 37 struct GNUNET_BIO_WriteHandle *wh;
37 int64_t testNum; 38 struct GNUNET_BIO_ReadHandle *rh;
38 char *readResultString; 39 void *buffer;
39 char *fileName = GNUNET_DISK_mktemp ("gnunet_bio"); 40 size_t buffer_size = 0;
40 struct GNUNET_BIO_WriteHandle *fileW; 41 char *filename = GNUNET_DISK_mktemp ("gnunet-bio");
41 struct GNUNET_BIO_ReadHandle *fileR; 42 struct GNUNET_CONTAINER_MetaData *mdW;
42 struct GNUNET_CONTAINER_MetaData *metaDataW; 43 struct GNUNET_CONTAINER_MetaData *mdR = NULL;
43 struct GNUNET_CONTAINER_MetaData *metaDataR; 44 char *rString = NULL;
44 45 int64_t wNum = TESTNUMBER64;
45 metaDataW = GNUNET_CONTAINER_meta_data_create (); 46 int64_t rNum = 0;
46 metaDataR = NULL; 47
47 GNUNET_CONTAINER_meta_data_add_publication_date (metaDataW); 48 mdW = GNUNET_CONTAINER_meta_data_create ();
48 49 GNUNET_CONTAINER_meta_data_add_publication_date (mdW);
49 fileW = GNUNET_BIO_write_open (fileName); 50
50 GNUNET_assert (NULL != fileW); 51 struct GNUNET_BIO_WriteSpec ws[] = {
51 GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_string (fileW, TESTSTRING)); 52 GNUNET_BIO_write_spec_string ("test-normal-rw-string", TESTSTRING),
52 GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_meta_data (fileW, metaDataW)); 53 GNUNET_BIO_write_spec_meta_data ("test-normal-rw-metadata", mdW),
53 GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_int64 (fileW, TESTNUMBER64)); 54 GNUNET_BIO_write_spec_int64 ("test-normal-rw-int64", &wNum),
54 GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_close (fileW)); 55 GNUNET_BIO_write_spec_end(),
55 56 };
56 fileR = GNUNET_BIO_read_open (fileName); 57
57 GNUNET_assert (NULL != fileR); 58 struct GNUNET_BIO_ReadSpec rs[] = {
58 readResultString = NULL; 59 GNUNET_BIO_read_spec_string ("test-normal-rw-string", &rString, 200),
59 GNUNET_assert (GNUNET_OK == 60 GNUNET_BIO_read_spec_meta_data ("test-normal-rw-metadata", &mdR),
60 GNUNET_BIO_read_string (fileR, "Read string error", 61 GNUNET_BIO_read_spec_int64 ("test-normal-rw-int64", &rNum),
61 &readResultString, 200)); 62 GNUNET_BIO_read_spec_end(),
62 GNUNET_assert (NULL != readResultString); 63 };
63 GNUNET_assert (0 == strcmp (TESTSTRING, readResultString)); 64
64 GNUNET_free (readResultString); 65 /* I/O on file */
66 wh = GNUNET_BIO_write_open_file (filename);
67 GNUNET_assert (NULL != wh);
68 GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_spec_commit (wh, ws));
69 GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_close (wh, NULL));
70
71 rh = GNUNET_BIO_read_open_file (filename);
72 GNUNET_assert (NULL != rh);
73 GNUNET_assert (GNUNET_OK == GNUNET_BIO_read_spec_commit (rh, rs));
74 GNUNET_assert (GNUNET_OK == GNUNET_BIO_read_close (rh, NULL));
75 GNUNET_assert (0 == strcmp (TESTSTRING, rString));
76 GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_meta_data_test_equal (mdR, mdW));
77 GNUNET_assert (wNum == rNum);
78
79 GNUNET_CONTAINER_meta_data_destroy (mdR);
80 GNUNET_assert (GNUNET_OK == GNUNET_DISK_directory_remove (filename));
81 GNUNET_free(filename);
82
83 /* I/O on buffer */
84 wh = GNUNET_BIO_write_open_buffer ();
85 GNUNET_assert (NULL != wh);
86 GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_spec_commit (wh, ws));
65 GNUNET_assert (GNUNET_OK == 87 GNUNET_assert (GNUNET_OK ==
66 GNUNET_BIO_read_meta_data (fileR, "Read meta error", 88 GNUNET_BIO_get_buffer_contents (wh,
67 &metaDataR)); 89 NULL,
68 GNUNET_assert (GNUNET_YES == 90 &buffer,
69 GNUNET_CONTAINER_meta_data_test_equal (metaDataR, metaDataW)); 91 &buffer_size));
70 GNUNET_assert (GNUNET_OK == GNUNET_BIO_read_int64 (fileR, &testNum)); 92 GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_close (wh, NULL));
71 GNUNET_BIO_read_close (fileR, &msg); 93
72 GNUNET_CONTAINER_meta_data_destroy (metaDataW); 94 rh = GNUNET_BIO_read_open_buffer (buffer, buffer_size);
73 GNUNET_CONTAINER_meta_data_destroy (metaDataR); 95 GNUNET_assert (NULL != rh);
74 GNUNET_assert (GNUNET_OK == GNUNET_DISK_directory_remove (fileName)); 96 GNUNET_assert (GNUNET_OK == GNUNET_BIO_read_spec_commit (rh, rs));
75 GNUNET_free (fileName); 97 GNUNET_assert (GNUNET_OK == GNUNET_BIO_read_close (rh, NULL));
98 GNUNET_assert (0 == strcmp (TESTSTRING, rString));
99 GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_meta_data_test_equal (mdR, mdW));
100 GNUNET_assert (wNum == rNum);
101
102 GNUNET_free (buffer);
103
104 GNUNET_CONTAINER_meta_data_destroy (mdW);
105 GNUNET_CONTAINER_meta_data_destroy (mdR);
76 return 0; 106 return 0;
77} 107}
78 108
79 109
80static int 110static int
81test_nullstring_rw () 111test_nullstring_rw (void)
82{ 112{
83 char *msg; 113 struct GNUNET_BIO_WriteHandle *wh;
84 char *readResultString = (char *) "not null"; 114 struct GNUNET_BIO_ReadHandle *rh;
85 struct GNUNET_BIO_WriteHandle *fileW; 115 char *filename = GNUNET_DISK_mktemp ("gnunet_bio");
86 struct GNUNET_BIO_ReadHandle *fileR; 116 char *rString = "not null";
87 char *fileName = GNUNET_DISK_mktemp ("gnunet_bio"); 117
88 118 wh = GNUNET_BIO_write_open_file (filename);
89 fileW = GNUNET_BIO_write_open (fileName); 119 GNUNET_assert (NULL != wh);
90 GNUNET_assert (NULL != fileW); 120 GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_string (wh,
91 GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_string (fileW, NULL)); 121 "test-nullstring-rw",
92 GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_close (fileW)); 122 NULL));
93 123 GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_close (wh, NULL));
94 fileR = GNUNET_BIO_read_open (fileName); 124
95 GNUNET_assert (NULL != fileR); 125 rh = GNUNET_BIO_read_open_file (filename);
96 GNUNET_assert (GNUNET_OK == 126 GNUNET_assert (NULL != rh);
97 GNUNET_BIO_read_string (fileR, "Read string error", 127 GNUNET_assert (GNUNET_OK == GNUNET_BIO_read_string (rh,
98 &readResultString, 200)); 128 "test-nullstring-rw",
99 GNUNET_assert (NULL == readResultString); 129 &rString, 200));
100 GNUNET_BIO_read_close (fileR, &msg); 130 GNUNET_assert (GNUNET_OK == GNUNET_BIO_read_close (rh, NULL));
101 GNUNET_assert (GNUNET_OK == GNUNET_DISK_directory_remove (fileName)); 131
102 GNUNET_free (fileName); 132 GNUNET_assert (NULL == rString);
103 133
134 GNUNET_assert (GNUNET_OK == GNUNET_DISK_directory_remove (filename));
135 GNUNET_free (filename);
104 return 0; 136 return 0;
105} 137}
106 138
107 139
108static int 140static int
109test_emptystring_rw () 141test_emptystring_rw (void)
110{ 142{
111 char *msg; 143 struct GNUNET_BIO_WriteHandle *wh;
112 char *readResultString; 144 struct GNUNET_BIO_ReadHandle *rh;
113 struct GNUNET_BIO_WriteHandle *fileW; 145 char *filename = GNUNET_DISK_mktemp ("gnunet_bio");
114 struct GNUNET_BIO_ReadHandle *fileR; 146 char *rString = NULL;
115 char *fileName = GNUNET_DISK_mktemp ("gnunet_bio"); 147
116 148 wh = GNUNET_BIO_write_open_file (filename);
117 fileW = GNUNET_BIO_write_open (fileName); 149 GNUNET_assert (NULL != wh);
118 GNUNET_assert (NULL != fileW); 150 GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_string (wh,
119 GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_string (fileW, "")); 151 "test-emptystring-rw",
120 GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_close (fileW)); 152 ""));
121 153 GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_close (wh, NULL));
122 fileR = GNUNET_BIO_read_open (fileName); 154
123 GNUNET_assert (NULL != fileR); 155 rh = GNUNET_BIO_read_open_file (filename);
124 readResultString = NULL; 156 GNUNET_assert (NULL != rh);
125 GNUNET_assert (GNUNET_OK == 157 GNUNET_assert (GNUNET_OK == GNUNET_BIO_read_string (rh,
126 GNUNET_BIO_read_string (fileR, "Read string error", 158 "test-emptystring-rw",
127 &readResultString, 200)); 159 &rString, 200));
128 GNUNET_free (readResultString); 160 GNUNET_assert (GNUNET_OK == GNUNET_BIO_read_close (rh, NULL));
129 GNUNET_BIO_read_close (fileR, &msg); 161
130 GNUNET_assert (GNUNET_OK == GNUNET_DISK_directory_remove (fileName)); 162 GNUNET_free (rString);
131 GNUNET_free (fileName); 163
164 GNUNET_assert (GNUNET_OK == GNUNET_DISK_directory_remove (filename));
165 GNUNET_free (filename);
132 return 0; 166 return 0;
133} 167}
134 168
135 169
136static int 170static int
137test_bigstring_rw () 171test_bigstring_rw (void)
138{ 172{
139 char *msg; 173 struct GNUNET_BIO_WriteHandle *wh;
140 char *readResultString; 174 struct GNUNET_BIO_ReadHandle *rh;
141 struct GNUNET_BIO_WriteHandle *fileW; 175 char *filename = GNUNET_DISK_mktemp ("gnunet_bio");
142 struct GNUNET_BIO_ReadHandle *fileR; 176 char *rString = NULL;
143 char *fileName = GNUNET_DISK_mktemp ("gnunet_bio"); 177
144 178 wh = GNUNET_BIO_write_open_file (filename);
145 fileW = GNUNET_BIO_write_open (fileName); 179 GNUNET_assert (NULL != wh);
146 GNUNET_assert (NULL != fileW); 180 GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_string (wh,
147 GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_string (fileW, TESTSTRING)); 181 "test-bigstring-rw",
148 GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_close (fileW)); 182 TESTSTRING));
149 183 GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_close (wh, NULL));
150 fileR = GNUNET_BIO_read_open (fileName); 184
151 GNUNET_assert (NULL != fileR); 185 rh = GNUNET_BIO_read_open_file (filename);
152 readResultString = NULL; 186 GNUNET_assert (NULL != rh);
153 GNUNET_assert (GNUNET_SYSERR == 187 GNUNET_assert (GNUNET_SYSERR == GNUNET_BIO_read_string (rh,
154 GNUNET_BIO_read_string (fileR, "Read string error", 188 "test-bigstring-rw",
155 &readResultString, 1)); 189 &rString, 1));
156 GNUNET_assert (NULL == readResultString); 190 GNUNET_assert (GNUNET_SYSERR == GNUNET_BIO_read_close (rh, NULL));
157 msg = NULL; 191
158 GNUNET_BIO_read_close (fileR, &msg); 192 GNUNET_assert (NULL == rString);
159 GNUNET_free (msg); 193
160 GNUNET_assert (GNUNET_OK == GNUNET_DISK_directory_remove (fileName)); 194 GNUNET_assert (GNUNET_OK == GNUNET_DISK_directory_remove (filename));
161 GNUNET_free (fileName); 195 GNUNET_free (filename);
162 return 0; 196 return 0;
163} 197}
164 198
165 199
166static int 200static int
167test_bigmeta_rw () 201test_bigmeta_rw (void)
168{ 202{
169 char *msg;
170 static char meta[1024 * 1024 * 10]; 203 static char meta[1024 * 1024 * 10];
171 struct GNUNET_BIO_WriteHandle *fileW; 204 struct GNUNET_BIO_WriteHandle *wh;
172 struct GNUNET_BIO_ReadHandle *fileR; 205 struct GNUNET_BIO_ReadHandle *rh;
173 char *fileName = GNUNET_DISK_mktemp ("gnunet_bio"); 206 char *filename = GNUNET_DISK_mktemp ("gnunet_bio");
174 struct GNUNET_CONTAINER_MetaData *metaDataR; 207 struct GNUNET_CONTAINER_MetaData *mdR = NULL;
175 208
176 memset (meta, 'b', sizeof(meta)); 209 memset (meta, 'b', sizeof (meta));
177 meta[sizeof(meta) - 1] = '\0'; 210 meta[sizeof (meta) - 1] = '\0';
178 fileW = GNUNET_BIO_write_open (fileName); 211
179 GNUNET_assert (NULL != fileW); 212 wh = GNUNET_BIO_write_open_file (filename);
180 GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_int32 (fileW, sizeof(meta))); 213 GNUNET_assert (NULL != wh);
181 GNUNET_assert (GNUNET_OK == GNUNET_BIO_write (fileW, meta, sizeof(meta))); 214 GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_int32 (wh,
182 GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_close (fileW)); 215 "test-bigmeta-rw-int32",
183 216 sizeof (meta)));
184 fileR = GNUNET_BIO_read_open (fileName); 217 GNUNET_assert (GNUNET_OK == GNUNET_BIO_write (wh,
185 GNUNET_assert (NULL != fileR); 218 "test-bigmeta-rw-bytes",
186 metaDataR = NULL; 219 meta,
220 sizeof (meta)));
221 GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_close (wh, NULL));
222
223 rh = GNUNET_BIO_read_open_file (filename);
224 GNUNET_assert (NULL != rh);
187 GNUNET_assert (GNUNET_SYSERR == 225 GNUNET_assert (GNUNET_SYSERR ==
188 GNUNET_BIO_read_meta_data (fileR, "Read meta error", 226 GNUNET_BIO_read_meta_data (rh,
189 &metaDataR)); 227 "test-bigmeta-rw-metadata",
190 msg = NULL; 228 &mdR));
191 GNUNET_BIO_read_close (fileR, &msg); 229 GNUNET_assert (GNUNET_SYSERR == GNUNET_BIO_read_close (rh, NULL));
192 GNUNET_free (msg); 230
193 GNUNET_assert (GNUNET_OK == GNUNET_DISK_directory_remove (fileName)); 231 GNUNET_assert (NULL == mdR);
194 GNUNET_assert (NULL == metaDataR); 232
195 GNUNET_free (fileName); 233 GNUNET_assert (GNUNET_OK == GNUNET_DISK_directory_remove (filename));
234 GNUNET_free (filename);
196 return 0; 235 return 0;
197} 236}
198 237
199 238
200static int 239static int
201test_directory_r () 240test_directory_r (void)
202{ 241{
203#ifdef __linux__ 242#ifdef LINUX
204 char *msg; 243 struct GNUNET_BIO_ReadHandle *rh;
205 char readResult[200]; 244 char rString[200];
206 struct GNUNET_BIO_ReadHandle *fileR; 245
207 246 rh = GNUNET_BIO_read_open_file ("/dev");
208 fileR = GNUNET_BIO_read_open ("/dev"); 247 GNUNET_assert (NULL != rh);
209 GNUNET_assert (NULL != fileR); 248 GNUNET_assert (GNUNET_SYSERR == GNUNET_BIO_read (rh,
210 GNUNET_assert (GNUNET_SYSERR == 249 "test-directory-r",
211 GNUNET_BIO_read (fileR, "Read error", readResult, 250 rString,
212 sizeof(readResult))); 251 sizeof (rString)));
213 msg = NULL; 252 GNUNET_assert (GNUNET_SYSERR == GNUNET_BIO_read_close (rh, NULL));
214 GNUNET_BIO_read_close (fileR, &msg);
215 GNUNET_free (msg);
216#endif 253#endif
217 return 0; 254 return 0;
218} 255}
219 256
220 257
221static int 258static int
222test_nullfile_rw () 259test_nullfile_rw (void)
223{ 260{
224 static char fileNameNO[102401]; 261 static char filename[102401];
225 struct GNUNET_BIO_WriteHandle *fileWNO; 262 struct GNUNET_BIO_WriteHandle *wh;
226 struct GNUNET_BIO_ReadHandle *fileRNO; 263 struct GNUNET_BIO_ReadHandle *rh;
227 264
228 memset (fileNameNO, 'a', sizeof(fileNameNO)); 265 memset (filename, 'a', sizeof (filename));
229 fileNameNO[sizeof(fileNameNO) - 1] = '\0'; 266 filename[sizeof (filename) - 1] = '\0';
230 267
231 GNUNET_log_skip (1, GNUNET_NO); 268 GNUNET_log_skip (2, GNUNET_NO);
232 fileWNO = GNUNET_BIO_write_open (fileNameNO); 269 wh = GNUNET_BIO_write_open_file (filename);
233 GNUNET_log_skip (0, GNUNET_YES); 270 GNUNET_log_skip (0, GNUNET_YES);
234 GNUNET_assert (NULL == fileWNO); 271 GNUNET_assert (NULL == wh);
235 272
236 GNUNET_log_skip (1, GNUNET_NO); 273 GNUNET_log_skip (2, GNUNET_NO);
237 fileRNO = GNUNET_BIO_read_open (fileNameNO); 274 rh = GNUNET_BIO_read_open_file (filename);
238 GNUNET_log_skip (0, GNUNET_YES); 275 GNUNET_log_skip (0, GNUNET_YES);
239 GNUNET_assert (NULL == fileRNO); 276 GNUNET_assert (NULL == rh);
277
240 return 0; 278 return 0;
241} 279}
242 280
243 281
244static int 282static int
245test_fullfile_rw () 283test_fullfile_rw (void)
246{ 284{
247#ifdef __linux__ 285#ifdef LINUX
248 /* /dev/full only seems to exist on Linux */ 286 /* /dev/full doesn't exist on every platform */
249 char *msg; 287 struct GNUNET_BIO_WriteHandle *wh;
250 int64_t testNum; 288 struct GNUNET_BIO_ReadHandle *rh;
251 char *readResultString; 289 char *rString = NULL;
252 char readResult[200]; 290 char rResult[200];
253 struct GNUNET_BIO_WriteHandle *fileW; 291 struct GNUNET_CONTAINER_MetaData *mdW;
254 struct GNUNET_BIO_ReadHandle *fileR; 292 struct GNUNET_CONTAINER_MetaData *mdR = NULL;
255 struct GNUNET_CONTAINER_MetaData *metaDataW; 293
256 struct GNUNET_CONTAINER_MetaData *metaDataR; 294 mdW = GNUNET_CONTAINER_meta_data_create ();
257 295 GNUNET_CONTAINER_meta_data_add_publication_date (mdW);
258 metaDataW = GNUNET_CONTAINER_meta_data_create (); 296
259 GNUNET_CONTAINER_meta_data_add_publication_date (metaDataW); 297 struct GNUNET_BIO_WriteSpec ws[] = {
260 298 GNUNET_BIO_write_spec_object ("test-fullfile-rw-bytes",
261 fileW = GNUNET_BIO_write_open ("/dev/full"); 299 TESTSTRING,
262 GNUNET_assert (NULL != fileW); 300 strlen (TESTSTRING)),
263 (void) GNUNET_BIO_write (fileW, TESTSTRING, strlen (TESTSTRING)); 301 GNUNET_BIO_write_spec_string ("test-fullfile-rw-string",
264 (void) GNUNET_BIO_write_string (fileW, TESTSTRING); 302 TESTSTRING),
265 (void) GNUNET_BIO_write_meta_data (fileW, metaDataW); 303 GNUNET_BIO_write_spec_meta_data ("test-fullfile-rw-metadata",
266 GNUNET_assert (GNUNET_SYSERR == GNUNET_BIO_write_close (fileW)); 304 mdW),
267 GNUNET_CONTAINER_meta_data_destroy (metaDataW); 305 GNUNET_BIO_write_spec_end (),
268 306 };
269 fileW = GNUNET_BIO_write_open ("/dev/full"); 307
270 GNUNET_assert (NULL != fileW); 308 struct GNUNET_BIO_ReadSpec rs[] = {
271 GNUNET_assert (GNUNET_SYSERR == GNUNET_BIO_write_close (fileW)); 309 GNUNET_BIO_read_spec_object ("test-fullfile-rw-bytes",
272 310 rResult,
273 fileR = GNUNET_BIO_read_open ("/dev/null"); 311 sizeof (rResult)),
274 GNUNET_assert (NULL != fileR); 312 GNUNET_BIO_read_spec_string ("test-fullfile-rw-string",
275 GNUNET_assert (GNUNET_SYSERR == 313 &rString,
276 GNUNET_BIO_read (fileR, "Read error", readResult, 314 200),
277 sizeof(readResult))); 315 GNUNET_BIO_read_spec_meta_data ("test-fullfile-rw-metadata",
278 readResultString = NULL; 316 &mdR),
279 GNUNET_assert (GNUNET_SYSERR == 317 GNUNET_BIO_read_spec_end(),
280 GNUNET_BIO_read_string (fileR, "Read string error", 318 };
281 &readResultString, 200)); 319
282 GNUNET_assert (NULL == readResultString); 320 wh = GNUNET_BIO_write_open_file ("/dev/full");
283 GNUNET_assert (GNUNET_SYSERR == GNUNET_BIO_read_int64 (fileR, &testNum)); 321 GNUNET_assert (NULL != wh);
284 metaDataR = NULL; 322 GNUNET_assert (GNUNET_SYSERR == GNUNET_BIO_write_spec_commit (wh, ws));
285 GNUNET_assert (GNUNET_SYSERR == 323 GNUNET_assert (GNUNET_SYSERR == GNUNET_BIO_write_close (wh, NULL));
286 GNUNET_BIO_read_meta_data (fileR, "Read meta error", 324
287 &metaDataR)); 325 rh = GNUNET_BIO_read_open_file ("/dev/null");
288 msg = NULL; 326 GNUNET_assert (NULL != rh);
289 GNUNET_BIO_read_close (fileR, &msg); 327 GNUNET_assert (GNUNET_SYSERR == GNUNET_BIO_read_spec_commit (rh, rs));
290 GNUNET_free (msg); 328 GNUNET_assert (GNUNET_SYSERR == GNUNET_BIO_read_close (rh, NULL));
291 GNUNET_assert (NULL == metaDataR); 329
330 GNUNET_assert (NULL == rString);
331 GNUNET_assert (NULL == mdR);
292#endif 332#endif
293 return 0; 333 return 0;
294} 334}
295 335
296 336
297static int 337static int
298test_fakestring_rw () 338test_fakestring_rw (void)
299{ 339{
300 char *msg; 340 struct GNUNET_BIO_WriteHandle *wh;
301 int32_t tmpInt = 2; 341 struct GNUNET_BIO_ReadHandle *rh;
302 char *readResult; 342 char *filename = GNUNET_DISK_mktemp ("gnunet_bio");
303 struct GNUNET_BIO_WriteHandle *fileW; 343 char *rString = NULL;
304 struct GNUNET_BIO_ReadHandle *fileR; 344
305 char *fileName = GNUNET_DISK_mktemp ("gnunet_bio"); 345 wh = GNUNET_BIO_write_open_file (filename);
306 346 GNUNET_assert (NULL != wh);
307 fileW = GNUNET_BIO_write_open (fileName); 347 GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_int32 (wh,
308 GNUNET_assert (NULL != fileW); 348 "test-fakestring-rw-int32",
309 GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_int32 (fileW, tmpInt)); 349 2));
310 GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_close (fileW)); 350 GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_close (wh, NULL));
311 351
312 fileR = GNUNET_BIO_read_open (fileName); 352 rh = GNUNET_BIO_read_open_file (filename);
313 GNUNET_assert (NULL != fileR); 353 GNUNET_assert (NULL != rh);
314 GNUNET_assert (GNUNET_SYSERR == 354 GNUNET_assert (GNUNET_SYSERR ==
315 GNUNET_BIO_read_string (fileR, "Read string error", 355 GNUNET_BIO_read_string (rh,
316 &readResult, 200)); 356 "test-fakestring-rw-string",
317 msg = NULL; 357 &rString, 200));
318 GNUNET_BIO_read_close (fileR, &msg); 358 GNUNET_assert (GNUNET_SYSERR == GNUNET_BIO_read_close (rh, NULL));
319 GNUNET_free (msg); 359
320 GNUNET_assert (GNUNET_OK == GNUNET_DISK_directory_remove (fileName)); 360 GNUNET_assert (NULL == rString);
321 GNUNET_free (fileName); 361
362 GNUNET_assert (GNUNET_OK == GNUNET_DISK_directory_remove (filename));
363 GNUNET_free (filename);
322 return 0; 364 return 0;
323} 365}
324 366
325 367
326static int 368static int
327test_fakemeta_rw () 369test_fakemeta_rw (void)
328{ 370{
329 char *msg; 371 struct GNUNET_BIO_WriteHandle *wh;
330 int32_t tmpInt = 2; 372 struct GNUNET_BIO_ReadHandle *rh;
331 struct GNUNET_BIO_WriteHandle *fileW; 373 char *filename = GNUNET_DISK_mktemp ("gnunet_bio");
332 struct GNUNET_BIO_ReadHandle *fileR; 374 struct GNUNET_CONTAINER_MetaData *mdR = NULL;
333 char *fileName = GNUNET_DISK_mktemp ("gnunet_bio"); 375
334 struct GNUNET_CONTAINER_MetaData *metaDataR; 376 wh = GNUNET_BIO_write_open_file (filename);
335 377 GNUNET_assert (NULL != wh);
336 fileW = GNUNET_BIO_write_open (fileName); 378 GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_int32 (wh,
337 GNUNET_assert (NULL != fileW); 379 "test-fakestring-rw-int32",
338 GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_int32 (fileW, tmpInt)); 380 2));
339 GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_close (fileW)); 381 GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_close (wh, NULL));
340 382
341 fileR = GNUNET_BIO_read_open (fileName); 383 rh = GNUNET_BIO_read_open_file (filename);
342 GNUNET_assert (NULL != fileR); 384 GNUNET_assert (NULL != rh);
343 metaDataR = NULL;
344 GNUNET_assert (GNUNET_SYSERR == 385 GNUNET_assert (GNUNET_SYSERR ==
345 GNUNET_BIO_read_meta_data (fileR, "Read meta error", 386 GNUNET_BIO_read_meta_data (rh,
346 &metaDataR)); 387 "test-fakestring-rw-metadata",
347 GNUNET_assert (NULL == metaDataR); 388 &mdR));
348 msg = NULL; 389 GNUNET_assert (GNUNET_SYSERR == GNUNET_BIO_read_close (rh, NULL));
349 GNUNET_BIO_read_close (fileR, &msg); 390
350 GNUNET_free (msg); 391 GNUNET_assert (NULL == mdR);
351 GNUNET_assert (GNUNET_OK == GNUNET_DISK_directory_remove (fileName)); 392
352 GNUNET_free (fileName); 393 GNUNET_assert (GNUNET_OK == GNUNET_DISK_directory_remove (filename));
394 GNUNET_free (filename);
353 return 0; 395 return 0;
354} 396}
355 397
356 398
357static int 399static int
358test_fakebigmeta_rw () 400test_fakebigmeta_rw (void)
359{ 401{
360 char *msg; 402 struct GNUNET_BIO_WriteHandle *wh;
361 int32_t tmpInt = 1024 * 1024 * 10; 403 struct GNUNET_BIO_ReadHandle *rh;
362 struct GNUNET_BIO_WriteHandle *fileW; 404 char *filename = GNUNET_DISK_mktemp ("gnunet_bio");
363 struct GNUNET_BIO_ReadHandle *fileR; 405 struct GNUNET_CONTAINER_MetaData *mdR = NULL;
364 char *fileName = GNUNET_DISK_mktemp ("gnunet_bio"); 406 int32_t wNum = 1024 * 1024 * 10;
365 struct GNUNET_CONTAINER_MetaData *metaDataR; 407
366 408 wh = GNUNET_BIO_write_open_file (filename);
367 fileW = GNUNET_BIO_write_open (fileName); 409 GNUNET_assert (NULL != wh);
368 GNUNET_assert (NULL != fileW); 410 GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_int32 (wh,
369 GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_int32 (fileW, tmpInt)); 411 "test-fakebigmeta-rw-int32",
370 GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_close (fileW)); 412 wNum));
371 413 GNUNET_assert (GNUNET_OK == GNUNET_BIO_write_close (wh, NULL));
372 fileR = GNUNET_BIO_read_open (fileName); 414
373 GNUNET_assert (NULL != fileR); 415 rh = GNUNET_BIO_read_open_file (filename);
374 metaDataR = NULL; 416 GNUNET_assert (NULL != rh);
375 GNUNET_assert (GNUNET_SYSERR == 417 GNUNET_assert (GNUNET_SYSERR ==
376 GNUNET_BIO_read_meta_data (fileR, "Read meta error", 418 GNUNET_BIO_read_meta_data (rh,
377 &metaDataR)); 419 "test-fakebigmeta-rw-metadata",
378 msg = NULL; 420 &mdR));
379 GNUNET_BIO_read_close (fileR, &msg); 421 GNUNET_assert (GNUNET_SYSERR == GNUNET_BIO_read_close (rh, NULL));
380 GNUNET_free (msg); 422
381 GNUNET_assert (GNUNET_OK == GNUNET_DISK_directory_remove (fileName)); 423 GNUNET_assert (NULL == mdR);
382 GNUNET_assert (NULL == metaDataR); 424
383 GNUNET_free (fileName); 425 GNUNET_assert (GNUNET_OK == GNUNET_DISK_directory_remove (filename));
426 GNUNET_free (filename);
384 return 0; 427 return 0;
385} 428}
386 429
387 430
388static int 431static int
389check_string_rw () 432check_string_rw (void)
390{ 433{
391 GNUNET_assert (0 == test_nullstring_rw ()); 434 GNUNET_assert (0 == test_nullstring_rw ());
392 GNUNET_assert (0 == test_emptystring_rw ()); 435 GNUNET_assert (0 == test_emptystring_rw ());
@@ -397,7 +440,7 @@ check_string_rw ()
397 440
398 441
399static int 442static int
400check_metadata_rw () 443check_metadata_rw (void)
401{ 444{
402 GNUNET_assert (0 == test_fakebigmeta_rw ()); 445 GNUNET_assert (0 == test_fakebigmeta_rw ());
403 GNUNET_assert (0 == test_fakemeta_rw ()); 446 GNUNET_assert (0 == test_fakemeta_rw ());
@@ -407,7 +450,7 @@ check_metadata_rw ()
407 450
408 451
409static int 452static int
410check_file_rw () 453check_file_rw (void)
411{ 454{
412 GNUNET_assert (0 == test_normal_rw ()); 455 GNUNET_assert (0 == test_normal_rw ());
413 GNUNET_assert (0 == test_nullfile_rw ()); 456 GNUNET_assert (0 == test_nullfile_rw ());