GNUnet  0.11.x
bio.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2006, 2009, 2013 GNUnet e.V.
4 
5  GNUnet is free software: you can redistribute it and/or modify it
6  under the terms of the GNU Affero General Public License as published
7  by the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  GNUnet is distributed in the hope that it will be useful, but
11  WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Affero General Public License for more details.
14 
15  You should have received a copy of the GNU Affero General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  SPDX-License-Identifier: AGPL3.0-or-later
19  */
25 #include "platform.h"
26 #include "gnunet_util_lib.h"
27 
28 #define LOG(kind, ...) GNUNET_log_from (kind, "util-bio", __VA_ARGS__)
29 
30 #ifndef PATH_MAX
31 
34 #define PATH_MAX 4096
35 #endif
36 
37 
41 #define BIO_BUFFER_SIZE 65536
42 
47 #define MAX_META_DATA (1024 * 1024)
48 
49 
54 {
59 
63  char *emsg;
64 
68  char *buffer;
69 
73  size_t have;
74 
78  size_t size;
79 
83  off_t pos;
84 };
85 
86 
93 struct GNUNET_BIO_ReadHandle *
94 GNUNET_BIO_read_open (const char *fn)
95 {
96  struct GNUNET_DISK_FileHandle *fd;
97  struct GNUNET_BIO_ReadHandle *h;
98 
100  if (NULL == fd)
101  return NULL;
102  h = GNUNET_malloc (sizeof(struct GNUNET_BIO_ReadHandle) + BIO_BUFFER_SIZE);
103  h->buffer = (char *) &h[1];
104  h->size = BIO_BUFFER_SIZE;
105  h->fd = fd;
106  return h;
107 }
108 
109 
118 int
120 {
121  int err;
122 
123  err = (NULL == h->emsg) ? GNUNET_OK : GNUNET_SYSERR;
124  if (emsg != NULL)
125  *emsg = h->emsg;
126  else
129  GNUNET_free (h);
130  return err;
131 }
132 
133 
143 int
145  const char *what,
146  void *result,
147  size_t len)
148 {
149  char *dst = result;
150  size_t min;
151  size_t pos;
152  ssize_t ret;
153 
154  if (NULL != h->emsg)
155  return GNUNET_SYSERR;
156  pos = 0;
157  do
158  {
159  /* first, use buffer */
160  min = h->have - h->pos;
161  if (min > 0)
162  {
163  if (min > len - pos)
164  min = len - pos;
165  GNUNET_memcpy (&dst[pos], &h->buffer[h->pos], min);
166  h->pos += min;
167  pos += min;
168  }
169  if (pos == len)
170  return GNUNET_OK; /* done! */
171  GNUNET_assert (((off_t) h->have) == h->pos);
172  /* fill buffer */
173  ret = GNUNET_DISK_file_read (h->fd, h->buffer, h->size);
174  if (-1 == ret)
175  {
176  GNUNET_asprintf (&h->emsg,
177  _ ("Error reading `%s': %s"),
178  what,
179  strerror (errno));
180  return GNUNET_SYSERR;
181  }
182  if (0 == ret)
183  {
184  GNUNET_asprintf (&h->emsg,
185  _ ("Error reading `%s': %s"),
186  what,
187  _ ("End of file"));
188  return GNUNET_SYSERR;
189  }
190  h->pos = 0;
191  h->have = ret;
192  }
193  while (pos < len); /* should always be true */
194  return GNUNET_OK;
195 }
196 
197 
208 int
210  const char *file,
211  int line,
212  void *result,
213  size_t len)
214 {
215  char what[PATH_MAX + 1024];
216 
217  GNUNET_snprintf (what, sizeof(what), "%s:%d", file, line);
218  return GNUNET_BIO_read (h, what, result, len);
219 }
220 
221 
232 int
234  const char *what,
235  char **result,
236  size_t max_length)
237 {
238  char *buf;
239  uint32_t big;
240 
241  if (GNUNET_OK != GNUNET_BIO_read_int32 (h, &big))
242  {
244  GNUNET_asprintf (&h->emsg, _ ("Error reading length of string `%s'"), what);
245  return GNUNET_SYSERR;
246  }
247  if (0 == big)
248  {
249  *result = NULL;
250  return GNUNET_OK;
251  }
252  if (big > max_length)
253  {
254  GNUNET_asprintf (&h->emsg,
255  _ ("String `%s' longer than allowed (%u > %u)"),
256  what,
257  big,
258  max_length);
259  return GNUNET_SYSERR;
260  }
261  buf = GNUNET_malloc (big);
262  *result = buf;
263  buf[--big] = '\0';
264  if (0 == big)
265  return GNUNET_OK;
266  if (GNUNET_OK != GNUNET_BIO_read (h, what, buf, big))
267  {
268  GNUNET_free (buf);
269  *result = NULL;
270  return GNUNET_SYSERR;
271  }
272  return GNUNET_OK;
273 }
274 
275 
284 int
286  const char *what,
288 {
289  uint32_t size;
290  char *buf;
292 
293  if (GNUNET_OK != GNUNET_BIO_read_int32 (h, (int32_t *) &size))
294  return GNUNET_SYSERR;
295  if (size == 0)
296  {
297  *result = NULL;
298  return GNUNET_OK;
299  }
300  if (size > MAX_META_DATA)
301  {
302  GNUNET_asprintf (&h->emsg,
303  _ ("Serialized metadata `%s' larger than allowed (%u>%u)"),
304  what,
305  size,
306  MAX_META_DATA);
307  return GNUNET_SYSERR;
308  }
309  buf = GNUNET_malloc (size);
310  if (GNUNET_OK != GNUNET_BIO_read (h, what, buf, size))
311  {
312  GNUNET_free (buf);
313  return GNUNET_SYSERR;
314  }
315  meta = GNUNET_CONTAINER_meta_data_deserialize (buf, size);
316  if (NULL == meta)
317  {
318  GNUNET_free (buf);
319  GNUNET_asprintf (&h->emsg, _ ("Metadata `%s' failed to deserialize"), what);
320  return GNUNET_SYSERR;
321  }
322  GNUNET_free (buf);
323  *result = meta;
324  return GNUNET_OK;
325 }
326 
327 
337 int
339  const char *file,
340  int line,
341  int32_t *i)
342 {
343  int32_t big;
344 
345  if (GNUNET_OK != GNUNET_BIO_read_fn (h, file, line, &big, sizeof(int32_t)))
346  return GNUNET_SYSERR;
347  *i = ntohl (big);
348  return GNUNET_OK;
349 }
350 
351 
361 int
363  const char *file,
364  int line,
365  int64_t *i)
366 {
367  int64_t big;
368 
369  if (GNUNET_OK != GNUNET_BIO_read_fn (h, file, line, &big, sizeof(int64_t)))
370  return GNUNET_SYSERR;
371  *i = GNUNET_ntohll (big);
372  return GNUNET_OK;
373 }
374 
375 
380 {
385 
389  char *buffer;
390 
394  size_t have;
395 
399  size_t size;
400 };
401 
402 
409 struct GNUNET_BIO_WriteHandle *
411 {
412  struct GNUNET_DISK_FileHandle *fd;
413  struct GNUNET_BIO_WriteHandle *h;
414 
415  fd =
421  if (NULL == fd)
422  return NULL;
424  h->buffer = (char *) &h[1];
425  h->size = BIO_BUFFER_SIZE;
426  h->fd = fd;
427  return h;
428 }
429 
430 
437 int
439 {
440  int ret;
441 
442  ret = GNUNET_SYSERR;
443  if ((NULL != h->fd) && (GNUNET_OK == (ret = GNUNET_BIO_flush (h))))
445  GNUNET_free (h);
446  return ret;
447 }
448 
449 
457 int
459 {
460  ssize_t ret;
461 
462  ret = GNUNET_DISK_file_write (h->fd, h->buffer, h->have);
463  if (ret != (ssize_t) h->have)
464  {
466  h->fd = NULL;
467  return GNUNET_SYSERR; /* error */
468  }
469  h->have = 0;
470  return GNUNET_OK;
471 }
472 
473 
482 int
484  const void *buffer,
485  size_t n)
486 {
487  const char *src = buffer;
488  size_t min;
489  size_t pos;
490 
491  if (NULL == h->fd)
492  return GNUNET_SYSERR;
493  pos = 0;
494  do
495  {
496  /* first, just use buffer */
497  min = h->size - h->have;
498  if (min > n - pos)
499  min = n - pos;
500  GNUNET_memcpy (&h->buffer[h->have], &src[pos], min);
501  pos += min;
502  h->have += min;
503  if (pos == n)
504  return GNUNET_OK; /* done */
505  GNUNET_assert (h->have == h->size);
506  if (GNUNET_OK != GNUNET_BIO_flush (h))
507  return GNUNET_SYSERR; /* error */
508  }
509  while (pos < n); /* should always be true */
510  GNUNET_break (0);
511  return GNUNET_OK;
512 }
513 
514 
522 int
524 {
525  uint32_t slen;
526 
527  slen = (uint32_t) ((s == NULL) ? 0 : strlen (s) + 1);
528  if (GNUNET_OK != GNUNET_BIO_write_int32 (h, slen))
529  return GNUNET_SYSERR;
530  if (0 != slen)
531  return GNUNET_BIO_write (h, s, slen - 1);
532  return GNUNET_OK;
533 }
534 
535 
543 int
545  const struct GNUNET_CONTAINER_MetaData *m)
546 {
547  ssize_t size;
548  char *buf;
549 
550  if (m == NULL)
551  return GNUNET_BIO_write_int32 (h, 0);
552  buf = NULL;
554  m,
555  &buf,
558  if (size == -1)
559  {
560  GNUNET_free (buf);
561  return GNUNET_SYSERR;
562  }
563  if ((GNUNET_OK != GNUNET_BIO_write_int32 (h, (uint32_t) size)) ||
564  (GNUNET_OK != GNUNET_BIO_write (h, buf, size)))
565  {
566  GNUNET_free (buf);
567  return GNUNET_SYSERR;
568  }
569  GNUNET_free (buf);
570  return GNUNET_OK;
571 }
572 
573 
581 int
583 {
584  int32_t big;
585 
586  big = htonl (i);
587  return GNUNET_BIO_write (h, &big, sizeof(int32_t));
588 }
589 
590 
598 int
600 {
601  int64_t big;
602 
603  big = GNUNET_htonll (i);
604  return GNUNET_BIO_write (h, &big, sizeof(int64_t));
605 }
606 
607 
608 /* end of bio.c */
int GNUNET_BIO_write_meta_data(struct GNUNET_BIO_WriteHandle *h, const struct GNUNET_CONTAINER_MetaData *m)
Write metadata container to a file.
Definition: bio.c:544
Open the file for reading.
Create file if it doesn&#39;t exist.
ssize_t GNUNET_CONTAINER_meta_data_serialize(const struct GNUNET_CONTAINER_MetaData *md, char **target, size_t max, enum GNUNET_CONTAINER_MetaDataSerializationOptions opt)
Serialize meta-data to target.
int GNUNET_DISK_file_close(struct GNUNET_DISK_FileHandle *h)
Close an open file.
Definition: disk.c:1345
If not enough space is available, it is acceptable to only serialize some of the metadata.
int GNUNET_snprintf(char *buf, size_t size, const char *format,...)
Like snprintf, just aborts if the buffer is of insufficient size.
ssize_t GNUNET_DISK_file_read(const struct GNUNET_DISK_FileHandle *h, void *result, size_t len)
Read the contents of a binary file into a buffer.
Definition: disk.c:732
int GNUNET_BIO_write_string(struct GNUNET_BIO_WriteHandle *h, const char *s)
Write a string to a file.
Definition: bio.c:523
int GNUNET_BIO_flush(struct GNUNET_BIO_WriteHandle *h)
Force a buffered writer to flush its buffer.
Definition: bio.c:458
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
int GNUNET_BIO_write_int64(struct GNUNET_BIO_WriteHandle *h, int64_t i)
Write an (u)int64_t.
Definition: bio.c:599
int GNUNET_BIO_read_int32__(struct GNUNET_BIO_ReadHandle *h, const char *file, int line, int32_t *i)
Read an (u)int32_t.
Definition: bio.c:338
struct GNUNET_DISK_FileHandle * fd
Underlying file abstraction.
Definition: bio.c:58
Nobody is allowed to do anything to the file.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
struct GNUNET_CONTAINER_MetaData * GNUNET_CONTAINER_meta_data_deserialize(const char *input, size_t size)
Deserialize meta-data.
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
#define MAX_META_DATA
Maximum size allowed for meta data written/read from disk.
Definition: bio.c:47
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
#define BIO_BUFFER_SIZE
Size for I/O buffers.
Definition: bio.c:41
struct GNUNET_DISK_FileHandle * fd
Underlying file handle.
Definition: bio.c:384
int GNUNET_BIO_read_close(struct GNUNET_BIO_ReadHandle *h, char **emsg)
Close an open file.
Definition: bio.c:119
size_t size
Total size of buffer.
Definition: bio.c:78
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
static struct GNUNET_ARM_Handle * h
Connection with ARM.
Definition: gnunet-arm.c:99
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
struct GNUNET_BIO_ReadHandle * GNUNET_BIO_read_open(const char *fn)
Open a file for reading.
Definition: bio.c:94
static struct GNUNET_ARM_MonitorHandle * m
Monitor connection with ARM.
Definition: gnunet-arm.c:104
int GNUNET_BIO_read(struct GNUNET_BIO_ReadHandle *h, const char *what, void *result, size_t len)
Read the contents of a binary file into a buffer.
Definition: bio.c:144
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
Meta data to associate with a file, directory or namespace.
static char * line
Desired phone line (string to be converted to a hash).
static char * fn
Filename of the unique file.
Truncate file if it exists.
ssize_t GNUNET_DISK_file_write(const struct GNUNET_DISK_FileHandle *h, const void *buffer, size_t n)
Write a buffer to a file.
Definition: disk.c:820
static char buf[2048]
size_t have
Number of bytes available in read buffer.
Definition: bio.c:73
size_t have
Number of bytes already in buffer.
Definition: bio.c:394
static int result
Global testing status.
char * buffer
I/O buffer.
Definition: bio.c:389
Handle for buffered writing.
Definition: bio.c:379
char * buffer
I/O buffer.
Definition: bio.c:68
off_t pos
Current read offset in buffer.
Definition: bio.c:83
int GNUNET_BIO_read_string(struct GNUNET_BIO_ReadHandle *h, const char *what, char **result, size_t max_length)
Read 0-terminated string from a file.
Definition: bio.c:233
uint64_t GNUNET_htonll(uint64_t n)
Convert unsigned 64-bit integer to network byte order.
Definition: common_endian.c:35
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
#define GNUNET_BIO_read_int32(h, i)
Read an (u)int32_t.
Open the file for writing.
int GNUNET_BIO_write_close(struct GNUNET_BIO_WriteHandle *h)
Close an open file for writing.
Definition: bio.c:438
#define PATH_MAX
Assumed maximum path length (for source file names).
Definition: bio.c:34
int GNUNET_BIO_read_fn(struct GNUNET_BIO_ReadHandle *h, const char *file, int line, void *result, size_t len)
Read the contents of a binary file into a buffer.
Definition: bio.c:209
struct GNUNET_BIO_WriteHandle * GNUNET_BIO_write_open(const char *fn)
Open a file for writing.
Definition: bio.c:410
static struct GNUNET_CONTAINER_MetaData * meta
Meta-data provided via command-line option.
int GNUNET_BIO_read_int64__(struct GNUNET_BIO_ReadHandle *h, const char *file, int line, int64_t *i)
Read an (u)int64_t.
Definition: bio.c:362
size_t size
Total size of buffer.
Definition: bio.c:399
int GNUNET_BIO_write_int32(struct GNUNET_BIO_WriteHandle *h, int32_t i)
Write an (u)int32_t.
Definition: bio.c:582
int GNUNET_BIO_read_meta_data(struct GNUNET_BIO_ReadHandle *h, const char *what, struct GNUNET_CONTAINER_MetaData **result)
Read metadata container from a file.
Definition: bio.c:285
int GNUNET_BIO_write(struct GNUNET_BIO_WriteHandle *h, const void *buffer, size_t n)
Write a buffer to a file.
Definition: bio.c:483
struct GNUNET_DISK_FileHandle * GNUNET_DISK_file_open(const char *fn, enum GNUNET_DISK_OpenFlags flags, enum GNUNET_DISK_AccessPermissions perm)
Open a file.
Definition: disk.c:1268
char * emsg
Error message, NULL if there were no errors.
Definition: bio.c:63
Handle used to access files (and pipes).
#define GNUNET_malloc(size)
Wrapper around malloc.
Handle for buffered reading.
Definition: bio.c:53
uint64_t GNUNET_ntohll(uint64_t n)
Convert unsigned 64-bit integer to host byte order.
Definition: common_endian.c:48
#define GNUNET_free(ptr)
Wrapper around free.
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...