diff options
author | Christian Grothoff <christian@grothoff.org> | 2009-08-24 09:26:47 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2009-08-24 09:26:47 +0000 |
commit | da7cc55488f90b3294dbb7aa186184e6e8501d7e (patch) | |
tree | 642f70be79ca8f2cbdbb3579d213086f3a25a4bf /src/util/bio.c | |
parent | 2518cfc0a86865ebe4d0550e0013ed52a494231b (diff) | |
download | gnunet-da7cc55488f90b3294dbb7aa186184e6e8501d7e.tar.gz gnunet-da7cc55488f90b3294dbb7aa186184e6e8501d7e.zip |
hxing
Diffstat (limited to 'src/util/bio.c')
-rw-r--r-- | src/util/bio.c | 545 |
1 files changed, 545 insertions, 0 deletions
diff --git a/src/util/bio.c b/src/util/bio.c new file mode 100644 index 000000000..060b6f94b --- /dev/null +++ b/src/util/bio.c | |||
@@ -0,0 +1,545 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2006, 2009 Christian Grothoff (and other contributing authors) | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 2, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | |||
22 | /** | ||
23 | * @file util/bio.c | ||
24 | * @brief functions for buffering IO | ||
25 | * @author Christian Grothoff | ||
26 | */ | ||
27 | #include "platform.h" | ||
28 | #include "gnunet_bio_lib.h" | ||
29 | |||
30 | |||
31 | /** | ||
32 | * Handle for buffered reading. | ||
33 | */ | ||
34 | struct GNUNET_BIO_ReadHandle | ||
35 | { | ||
36 | }; | ||
37 | |||
38 | |||
39 | /** | ||
40 | * Open a file for reading. | ||
41 | * | ||
42 | * @param fn file name to be opened | ||
43 | * @return IO handle on success, NULL on error | ||
44 | */ | ||
45 | struct GNUNET_BIO_ReadHandle *GNUNET_BIO_read_open (const char *fn) | ||
46 | { | ||
47 | return NULL; | ||
48 | } | ||
49 | |||
50 | |||
51 | /** | ||
52 | * Close an open file. Reports if any errors reading | ||
53 | * from the file were encountered. | ||
54 | * | ||
55 | * @param h file handle | ||
56 | * @param emsg set to the error message | ||
57 | * @return GNUNET_OK on success, GNUNET_SYSERR otherwise | ||
58 | */ | ||
59 | int GNUNET_BIO_read_close (struct GNUNET_BIO_ReadHandle *h, | ||
60 | char **emsg) | ||
61 | { | ||
62 | return GNUNET_SYSERR; | ||
63 | } | ||
64 | |||
65 | |||
66 | /** | ||
67 | * Read the contents of a binary file into a buffer. | ||
68 | * | ||
69 | * @param h handle to an open file | ||
70 | * @param what describes what is being read (for error message creation) | ||
71 | * @param result the buffer to write the result to | ||
72 | * @param len the number of bytes to read | ||
73 | * @return len on success, GNUNET_SYSERR on failure | ||
74 | */ | ||
75 | ssize_t GNUNET_BIO_read (struct GNUNET_BIO_ReadHandle *h, | ||
76 | const char *what, | ||
77 | void *result, | ||
78 | size_t len) | ||
79 | { | ||
80 | } | ||
81 | |||
82 | |||
83 | /** | ||
84 | * Read 0-terminated string from a file. | ||
85 | * | ||
86 | * @param h handle to an open file | ||
87 | * @param what describes what is being read (for error message creation) | ||
88 | * @param result the buffer to store a pointer to the (allocated) string to | ||
89 | * (note that *result could be set to NULL as well) | ||
90 | * @return GNUNET_OK on success, GNUNET_SYSERR on failure | ||
91 | */ | ||
92 | int GNUNET_BIO_read_string (struct GNUNET_BIO_ReadHandle *h, | ||
93 | const char *what, | ||
94 | char **result) | ||
95 | { | ||
96 | } | ||
97 | |||
98 | |||
99 | /** | ||
100 | * Read metadata container from a file. | ||
101 | * | ||
102 | * @param h handle to an open file | ||
103 | * @param what describes what is being read (for error message creation) | ||
104 | * @param result the buffer to store a pointer to the (allocated) metadata | ||
105 | * @return GNUNET_OK on success, GNUNET_SYSERR on failure | ||
106 | */ | ||
107 | int GNUNET_BIO_read_meta_data (struct GNUNET_BIO_ReadHandle *h, | ||
108 | const char *what, | ||
109 | struct GNUNET_CONTAINER_MetaData **result) | ||
110 | { | ||
111 | } | ||
112 | |||
113 | |||
114 | /** | ||
115 | * Read an (u)int32_t. | ||
116 | * | ||
117 | * @param h hande to open file | ||
118 | * @param what describes what is being read (for error message creation) | ||
119 | * @param i address of 32-bit integer to read | ||
120 | * @return GNUNET_OK on success, GNUNET_SYSERR on error | ||
121 | */ | ||
122 | int GNUNET_BIO_read_int32__ (struct GNUNET_BIO_ReadHandle *h, | ||
123 | const char *what, | ||
124 | int32_t *i); | ||
125 | |||
126 | |||
127 | /** | ||
128 | * Read an (u)int64_t. | ||
129 | * | ||
130 | * @param h hande to open file | ||
131 | * @param what describes what is being read (for error message creation) | ||
132 | * @param i address of 64-bit integer to read | ||
133 | * @return GNUNET_OK on success, GNUNET_SYSERR on error | ||
134 | */ | ||
135 | int GNUNET_BIO_read_int64__ (struct GNUNET_BIO_ReadHandle *h, | ||
136 | const char *what, | ||
137 | int64_t *i); | ||
138 | |||
139 | /** | ||
140 | * Handle for buffered writing. | ||
141 | */ | ||
142 | struct GNUNET_BIO_WriteHandle | ||
143 | { | ||
144 | }; | ||
145 | |||
146 | |||
147 | /** | ||
148 | * Open a file for writing. | ||
149 | * | ||
150 | * @param fn file name to be opened | ||
151 | * @return IO handle on success, NULL on error | ||
152 | */ | ||
153 | struct GNUNET_BIO_WriteHandle *GNUNET_BIO_write_open (const char *fn) | ||
154 | { | ||
155 | return NULL; | ||
156 | } | ||
157 | |||
158 | |||
159 | /** | ||
160 | * Close an open file for writing. | ||
161 | * | ||
162 | * @param h file handle | ||
163 | * @return GNUNET_OK on success, GNUNET_SYSERR otherwise | ||
164 | */ | ||
165 | int GNUNET_BIO_write_close (struct GNUNET_BIO_WriteHandle *h); | ||
166 | |||
167 | |||
168 | /** | ||
169 | * Write a buffer to a file. | ||
170 | * | ||
171 | * @param h handle to open file | ||
172 | * @param buffer the data to write | ||
173 | * @param n number of bytes to write | ||
174 | * @return GNUNET_OK on success, GNUNET_SYSERR on error | ||
175 | */ | ||
176 | ssize_t GNUNET_BIO_write (struct GNUNET_BIO_WriteHandle *h, | ||
177 | const void *buffer, | ||
178 | size_t n); | ||
179 | |||
180 | |||
181 | /** | ||
182 | * Write a string to a file. | ||
183 | * | ||
184 | * @param h handle to open file | ||
185 | * @param s string to write (can be NULL) | ||
186 | * @return GNUNET_OK on success, GNUNET_SYSERR on error | ||
187 | */ | ||
188 | int GNUNET_BIO_write_string (struct GNUNET_BIO_WriteHandle *h, | ||
189 | const char *s); | ||
190 | |||
191 | |||
192 | |||
193 | |||
194 | /** | ||
195 | * Write metadata container to a file. | ||
196 | * | ||
197 | * @param h handle to open file | ||
198 | * @param m metadata to write | ||
199 | * @return GNUNET_OK on success, GNUNET_SYSERR on error | ||
200 | */ | ||
201 | int GNUNET_BIO_write_meta_data (struct GNUNET_BIO_WriteHandle *h, | ||
202 | const struct GNUNET_CONTAINER_MetaData *m); | ||
203 | |||
204 | |||
205 | |||
206 | /** | ||
207 | * Write a float. | ||
208 | * | ||
209 | * @param h hande to open file | ||
210 | * @param f float to write (must be a variable) | ||
211 | */ | ||
212 | #define GNUNET_BIO_write_float(h, f) (sizeof(float) == GNUNET_BIO_write (h, &f, sizeof(float))) | ||
213 | |||
214 | |||
215 | |||
216 | /** | ||
217 | * Write a double. | ||
218 | * | ||
219 | * @param h hande to open file | ||
220 | * @param f double to write (must be a variable) | ||
221 | */ | ||
222 | #define GNUNET_BIO_write_float(h, f) (sizeof(double) == GNUNET_BIO_write (h, &f, sizeof(double))) | ||
223 | |||
224 | |||
225 | /** | ||
226 | * Write an (u)int32_t. | ||
227 | * | ||
228 | * @param h hande to open file | ||
229 | * @param i address of 32-bit integer to write | ||
230 | * @return GNUNET_OK on success, GNUNET_SYSERR on error | ||
231 | */ | ||
232 | int GNUNET_BIO_write_int32 (struct GNUNET_BIO_ReadHandle *h, | ||
233 | int32_t i); | ||
234 | |||
235 | |||
236 | /** | ||
237 | * Write an (u)int64_t. | ||
238 | * | ||
239 | * @param h hande to open file | ||
240 | * @param i address of 64-bit integer to write | ||
241 | * @return GNUNET_OK on success, GNUNET_SYSERR on error | ||
242 | */ | ||
243 | int GNUNET_BIO_write_int64 (struct GNUNET_BIO_ReadHandle *h, | ||
244 | int64_t i); | ||
245 | |||
246 | |||
247 | |||
248 | |||
249 | |||
250 | typedef struct | ||
251 | { | ||
252 | int fd; | ||
253 | unsigned int have; | ||
254 | unsigned int size; | ||
255 | char *buffer; | ||
256 | } WriteBuffer; | ||
257 | |||
258 | static void | ||
259 | write_buffered (WriteBuffer * wb, const void *s, unsigned int size) | ||
260 | { | ||
261 | const char *src = s; | ||
262 | unsigned int min; | ||
263 | unsigned int pos; | ||
264 | int ret; | ||
265 | |||
266 | if (wb->fd == -1) | ||
267 | return; | ||
268 | pos = 0; | ||
269 | do | ||
270 | { | ||
271 | /* first, just use buffer */ | ||
272 | min = wb->size - wb->have; | ||
273 | if (min > size - pos) | ||
274 | min = size - pos; | ||
275 | memcpy (&wb->buffer[wb->have], &src[pos], min); | ||
276 | pos += min; | ||
277 | wb->have += min; | ||
278 | if (pos == size) | ||
279 | return; /* done */ | ||
280 | GNUNET_GE_ASSERT (NULL, wb->have == wb->size); | ||
281 | ret = WRITE (wb->fd, wb->buffer, wb->size); | ||
282 | if (ret != wb->size) | ||
283 | { | ||
284 | CLOSE (wb->fd); | ||
285 | wb->fd = -1; | ||
286 | return; /* error */ | ||
287 | } | ||
288 | wb->have = 0; | ||
289 | } | ||
290 | while (pos < size); /* should always be true */ | ||
291 | } | ||
292 | |||
293 | |||
294 | static void | ||
295 | WRITEINT (WriteBuffer * wb, int val) | ||
296 | { | ||
297 | int big; | ||
298 | big = htonl (val); | ||
299 | write_buffered (wb, &big, sizeof (int)); | ||
300 | } | ||
301 | |||
302 | static void | ||
303 | WRITELONG (WriteBuffer * wb, long long val) | ||
304 | { | ||
305 | long long big; | ||
306 | big = GNUNET_htonll (val); | ||
307 | write_buffered (wb, &big, sizeof (long long)); | ||
308 | } | ||
309 | |||
310 | static void | ||
311 | writeURI (WriteBuffer * wb, const struct GNUNET_ECRS_URI *uri) | ||
312 | { | ||
313 | char *buf; | ||
314 | unsigned int size; | ||
315 | |||
316 | buf = GNUNET_ECRS_uri_to_string (uri); | ||
317 | size = strlen (buf); | ||
318 | WRITEINT (wb, size); | ||
319 | write_buffered (wb, buf, size); | ||
320 | GNUNET_free (buf); | ||
321 | } | ||
322 | |||
323 | static void | ||
324 | WRITESTRING (WriteBuffer * wb, const char *name) | ||
325 | { | ||
326 | GNUNET_GE_BREAK (NULL, name != NULL); | ||
327 | WRITEINT (wb, strlen (name)); | ||
328 | write_buffered (wb, name, strlen (name)); | ||
329 | } | ||
330 | |||
331 | static void | ||
332 | writeMetaData (struct GNUNET_GE_Context *ectx, | ||
333 | WriteBuffer * wb, const struct GNUNET_MetaData *meta) | ||
334 | { | ||
335 | unsigned int size; | ||
336 | char *buf; | ||
337 | |||
338 | size = GNUNET_meta_data_get_serialized_size (meta, | ||
339 | GNUNET_SERIALIZE_FULL | ||
340 | | | ||
341 | GNUNET_SERIALIZE_NO_COMPRESS); | ||
342 | if (size > 1024 * 1024) | ||
343 | size = 1024 * 1024; | ||
344 | buf = GNUNET_malloc (size); | ||
345 | GNUNET_meta_data_serialize (ectx, | ||
346 | meta, | ||
347 | buf, | ||
348 | size, | ||
349 | GNUNET_SERIALIZE_PART | | ||
350 | GNUNET_SERIALIZE_NO_COMPRESS); | ||
351 | WRITEINT (wb, size); | ||
352 | write_buffered (wb, buf, size); | ||
353 | GNUNET_free (buf); | ||
354 | } | ||
355 | |||
356 | |||
357 | static void | ||
358 | writeFileInfo (struct GNUNET_GE_Context *ectx, WriteBuffer * wb, | ||
359 | const GNUNET_ECRS_FileInfo * fi) | ||
360 | { | ||
361 | writeMetaData (ectx, wb, fi->meta); | ||
362 | writeURI (wb, fi->uri); | ||
363 | } | ||
364 | |||
365 | |||
366 | |||
367 | |||
368 | typedef struct | ||
369 | { | ||
370 | int fd; | ||
371 | unsigned int have; | ||
372 | unsigned int size; | ||
373 | unsigned int pos; | ||
374 | char *buffer; | ||
375 | } ReadBuffer; | ||
376 | |||
377 | static int | ||
378 | read_buffered (ReadBuffer * rb, void *d, unsigned int size) | ||
379 | { | ||
380 | char *dst = d; | ||
381 | unsigned int min; | ||
382 | unsigned int pos; | ||
383 | int ret; | ||
384 | |||
385 | if (rb->fd == -1) | ||
386 | return -1; | ||
387 | pos = 0; | ||
388 | do | ||
389 | { | ||
390 | /* first, use buffer */ | ||
391 | min = rb->have - rb->pos; | ||
392 | if (min > 0) | ||
393 | { | ||
394 | if (min > size - pos) | ||
395 | min = size - pos; | ||
396 | memcpy (&dst[pos], &rb->buffer[rb->pos], min); | ||
397 | rb->pos += min; | ||
398 | pos += min; | ||
399 | } | ||
400 | if (pos == size) | ||
401 | return pos; /* done! */ | ||
402 | GNUNET_GE_ASSERT (NULL, rb->have == rb->pos); | ||
403 | /* fill buffer */ | ||
404 | ret = READ (rb->fd, rb->buffer, rb->size); | ||
405 | if (ret == -1) | ||
406 | { | ||
407 | CLOSE (rb->fd); | ||
408 | rb->fd = -1; | ||
409 | return -1; | ||
410 | } | ||
411 | if (ret == 0) | ||
412 | return 0; | ||
413 | rb->pos = 0; | ||
414 | rb->have = ret; | ||
415 | } | ||
416 | while (pos < size); /* should always be true */ | ||
417 | return pos; | ||
418 | } | ||
419 | |||
420 | |||
421 | static int | ||
422 | read_int (ReadBuffer * rb, int *val) | ||
423 | { | ||
424 | int big; | ||
425 | |||
426 | if (sizeof (int) != read_buffered (rb, &big, sizeof (int))) | ||
427 | return GNUNET_SYSERR; | ||
428 | *val = ntohl (big); | ||
429 | return GNUNET_OK; | ||
430 | } | ||
431 | |||
432 | static unsigned int | ||
433 | read_uint (ReadBuffer * rb, unsigned int *val) | ||
434 | { | ||
435 | unsigned int big; | ||
436 | |||
437 | if (sizeof (unsigned int) != | ||
438 | read_buffered (rb, &big, sizeof (unsigned int))) | ||
439 | return GNUNET_SYSERR; | ||
440 | *val = ntohl (big); | ||
441 | return GNUNET_OK; | ||
442 | } | ||
443 | |||
444 | #define READINT(a) if (GNUNET_OK != read_int(rb, (int*) &a)) return GNUNET_SYSERR; | ||
445 | |||
446 | static int | ||
447 | read_long (ReadBuffer * rb, long long *val) | ||
448 | { | ||
449 | long long big; | ||
450 | |||
451 | if (sizeof (long long) != read_buffered (rb, &big, sizeof (long long))) | ||
452 | return GNUNET_SYSERR; | ||
453 | *val = GNUNET_ntohll (big); | ||
454 | return GNUNET_OK; | ||
455 | } | ||
456 | |||
457 | #define READLONG(a) if (GNUNET_OK != read_long(rb, (long long*) &a)) return GNUNET_SYSERR; | ||
458 | |||
459 | static struct GNUNET_ECRS_URI * | ||
460 | read_uri (struct GNUNET_GE_Context *ectx, ReadBuffer * rb) | ||
461 | { | ||
462 | char *buf; | ||
463 | struct GNUNET_ECRS_URI *ret; | ||
464 | unsigned int size; | ||
465 | |||
466 | if (GNUNET_OK != read_uint (rb, &size)) | ||
467 | return NULL; | ||
468 | buf = GNUNET_malloc (size + 1); | ||
469 | buf[size] = '\0'; | ||
470 | if (size != read_buffered (rb, buf, size)) | ||
471 | { | ||
472 | GNUNET_free (buf); | ||
473 | return NULL; | ||
474 | } | ||
475 | ret = GNUNET_ECRS_string_to_uri (ectx, buf); | ||
476 | GNUNET_GE_BREAK (ectx, ret != NULL); | ||
477 | GNUNET_free (buf); | ||
478 | return ret; | ||
479 | } | ||
480 | |||
481 | #define READURI(u) if (NULL == (u = read_uri(ectx, rb))) return GNUNET_SYSERR; | ||
482 | |||
483 | static char * | ||
484 | read_string (ReadBuffer * rb, unsigned int maxLen) | ||
485 | { | ||
486 | char *buf; | ||
487 | unsigned int big; | ||
488 | |||
489 | if (GNUNET_OK != read_uint (rb, &big)) | ||
490 | return NULL; | ||
491 | if (big > maxLen) | ||
492 | return NULL; | ||
493 | buf = GNUNET_malloc (big + 1); | ||
494 | buf[big] = '\0'; | ||
495 | if (big != read_buffered (rb, buf, big)) | ||
496 | { | ||
497 | GNUNET_free (buf); | ||
498 | return NULL; | ||
499 | } | ||
500 | return buf; | ||
501 | } | ||
502 | |||
503 | #define READSTRING(c, max) if (NULL == (c = read_string(rb, max))) return GNUNET_SYSERR; | ||
504 | |||
505 | /** | ||
506 | * Read file info from file. | ||
507 | * | ||
508 | * @return GNUNET_OK on success, GNUNET_SYSERR on error | ||
509 | */ | ||
510 | static struct GNUNET_MetaData * | ||
511 | read_meta (struct GNUNET_GE_Context *ectx, ReadBuffer * rb) | ||
512 | { | ||
513 | unsigned int size; | ||
514 | char *buf; | ||
515 | struct GNUNET_MetaData *meta; | ||
516 | |||
517 | if (read_uint (rb, &size) != GNUNET_OK) | ||
518 | { | ||
519 | GNUNET_GE_BREAK (ectx, 0); | ||
520 | return NULL; | ||
521 | } | ||
522 | if (size > 1024 * 1024) | ||
523 | { | ||
524 | GNUNET_GE_BREAK (ectx, 0); | ||
525 | return NULL; | ||
526 | } | ||
527 | buf = GNUNET_malloc (size); | ||
528 | if (size != read_buffered (rb, buf, size)) | ||
529 | { | ||
530 | GNUNET_free (buf); | ||
531 | GNUNET_GE_BREAK (ectx, 0); | ||
532 | return NULL; | ||
533 | } | ||
534 | meta = GNUNET_meta_data_deserialize (ectx, buf, size); | ||
535 | if (meta == NULL) | ||
536 | { | ||
537 | GNUNET_free (buf); | ||
538 | GNUNET_GE_BREAK (ectx, 0); | ||
539 | return NULL; | ||
540 | } | ||
541 | GNUNET_free (buf); | ||
542 | return meta; | ||
543 | } | ||
544 | |||
545 | /* end of bio.c */ | ||