GNUnet  0.10.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 
58 
62  char *emsg;
63 
67  char *buffer;
68 
72  size_t have;
73 
77  size_t size;
78 
82  off_t pos;
83 };
84 
85 
92 struct GNUNET_BIO_ReadHandle *
94 {
95  struct GNUNET_DISK_FileHandle *fd;
96  struct GNUNET_BIO_ReadHandle *h;
97 
99  if (NULL == fd)
100  return NULL;
102  h->buffer = (char *)&h[1];
103  h->size = BIO_BUFFER_SIZE;
104  h->fd = fd;
105  return h;
106 }
107 
108 
117 int
119 {
120  int err;
121 
122  err = (NULL == h->emsg) ? GNUNET_OK : GNUNET_SYSERR;
123  if (emsg != NULL)
124  *emsg = h->emsg;
125  else
128  GNUNET_free(h);
129  return err;
130 }
131 
132 
142 int
144  const char *what,
145  void *result,
146  size_t len)
147 {
148  char *dst = result;
149  size_t min;
150  size_t pos;
151  ssize_t ret;
152 
153  if (NULL != h->emsg)
154  return GNUNET_SYSERR;
155  pos = 0;
156  do
157  {
158  /* first, use buffer */
159  min = h->have - h->pos;
160  if (min > 0)
161  {
162  if (min > len - pos)
163  min = len - pos;
164  GNUNET_memcpy(&dst[pos], &h->buffer[h->pos], min);
165  h->pos += min;
166  pos += min;
167  }
168  if (pos == len)
169  return GNUNET_OK; /* done! */
170  GNUNET_assert(((off_t)h->have) == h->pos);
171  /* fill buffer */
172  ret = GNUNET_DISK_file_read(h->fd, h->buffer, h->size);
173  if (-1 == ret)
174  {
175  GNUNET_asprintf(&h->emsg,
176  _("Error reading `%s': %s"),
177  what,
178  strerror(errno));
179  return GNUNET_SYSERR;
180  }
181  if (0 == ret)
182  {
183  GNUNET_asprintf(&h->emsg,
184  _("Error reading `%s': %s"),
185  what,
186  _("End of file"));
187  return GNUNET_SYSERR;
188  }
189  h->pos = 0;
190  h->have = ret;
191  }
192  while (pos < len); /* should always be true */
193  return GNUNET_OK;
194 }
195 
196 
207 int
209  const char *file,
210  int line,
211  void *result,
212  size_t len)
213 {
214  char what[PATH_MAX + 1024];
215 
216  GNUNET_snprintf(what, sizeof(what), "%s:%d", file, line);
217  return GNUNET_BIO_read(h, what, result, len);
218 }
219 
220 
231 int
233  const char *what,
234  char **result,
235  size_t max_length)
236 {
237  char *buf;
238  uint32_t big;
239 
240  if (GNUNET_OK != GNUNET_BIO_read_int32(h, &big))
241  {
243  GNUNET_asprintf(&h->emsg, _("Error reading length of string `%s'"), what);
244  return GNUNET_SYSERR;
245  }
246  if (0 == big)
247  {
248  *result = NULL;
249  return GNUNET_OK;
250  }
251  if (big > max_length)
252  {
253  GNUNET_asprintf(&h->emsg,
254  _("String `%s' longer than allowed (%u > %u)"),
255  what,
256  big,
257  max_length);
258  return GNUNET_SYSERR;
259  }
260  buf = GNUNET_malloc(big);
261  *result = buf;
262  buf[--big] = '\0';
263  if (0 == big)
264  return GNUNET_OK;
265  if (GNUNET_OK != GNUNET_BIO_read(h, what, buf, big))
266  {
267  GNUNET_free(buf);
268  *result = NULL;
269  return GNUNET_SYSERR;
270  }
271  return GNUNET_OK;
272 }
273 
274 
283 int
285  const char *what,
287 {
288  uint32_t size;
289  char *buf;
291 
292  if (GNUNET_OK != GNUNET_BIO_read_int32(h, (int32_t *)&size))
293  return GNUNET_SYSERR;
294  if (size == 0)
295  {
296  *result = NULL;
297  return GNUNET_OK;
298  }
299  if (size > MAX_META_DATA)
300  {
301  GNUNET_asprintf(&h->emsg,
302  _("Serialized metadata `%s' larger than allowed (%u>%u)"),
303  what,
304  size,
305  MAX_META_DATA);
306  return GNUNET_SYSERR;
307  }
308  buf = GNUNET_malloc(size);
309  if (GNUNET_OK != GNUNET_BIO_read(h, what, buf, size))
310  {
311  GNUNET_free(buf);
312  return GNUNET_SYSERR;
313  }
314  meta = GNUNET_CONTAINER_meta_data_deserialize(buf, size);
315  if (NULL == meta)
316  {
317  GNUNET_free(buf);
318  GNUNET_asprintf(&h->emsg, _("Metadata `%s' failed to deserialize"), what);
319  return GNUNET_SYSERR;
320  }
321  GNUNET_free(buf);
322  *result = meta;
323  return GNUNET_OK;
324 }
325 
326 
336 int
338  const char *file,
339  int line,
340  int32_t *i)
341 {
342  int32_t big;
343 
344  if (GNUNET_OK != GNUNET_BIO_read_fn(h, file, line, &big, sizeof(int32_t)))
345  return GNUNET_SYSERR;
346  *i = ntohl(big);
347  return GNUNET_OK;
348 }
349 
350 
360 int
362  const char *file,
363  int line,
364  int64_t *i)
365 {
366  int64_t big;
367 
368  if (GNUNET_OK != GNUNET_BIO_read_fn(h, file, line, &big, sizeof(int64_t)))
369  return GNUNET_SYSERR;
370  *i = GNUNET_ntohll(big);
371  return GNUNET_OK;
372 }
373 
374 
383 
387  char *buffer;
388 
392  size_t have;
393 
397  size_t size;
398 };
399 
400 
407 struct GNUNET_BIO_WriteHandle *
409 {
410  struct GNUNET_DISK_FileHandle *fd;
411  struct GNUNET_BIO_WriteHandle *h;
412 
413  fd =
419  if (NULL == fd)
420  return NULL;
422  h->buffer = (char *)&h[1];
423  h->size = BIO_BUFFER_SIZE;
424  h->fd = fd;
425  return h;
426 }
427 
428 
435 int
437 {
438  int ret;
439 
440  ret = GNUNET_SYSERR;
441  if ((NULL != h->fd) && (GNUNET_OK == (ret = GNUNET_BIO_flush(h))))
443  GNUNET_free(h);
444  return ret;
445 }
446 
447 
455 int
457 {
458  ssize_t ret;
459 
460  ret = GNUNET_DISK_file_write(h->fd, h->buffer, h->have);
461  if (ret != (ssize_t)h->have)
462  {
464  h->fd = NULL;
465  return GNUNET_SYSERR; /* error */
466  }
467  h->have = 0;
468  return GNUNET_OK;
469 }
470 
471 
480 int
482  const void *buffer,
483  size_t n)
484 {
485  const char *src = buffer;
486  size_t min;
487  size_t pos;
488 
489  if (NULL == h->fd)
490  return GNUNET_SYSERR;
491  pos = 0;
492  do
493  {
494  /* first, just use buffer */
495  min = h->size - h->have;
496  if (min > n - pos)
497  min = n - pos;
498  GNUNET_memcpy(&h->buffer[h->have], &src[pos], min);
499  pos += min;
500  h->have += min;
501  if (pos == n)
502  return GNUNET_OK; /* done */
503  GNUNET_assert(h->have == h->size);
504  if (GNUNET_OK != GNUNET_BIO_flush(h))
505  return GNUNET_SYSERR; /* error */
506  }
507  while (pos < n); /* should always be true */
508  GNUNET_break(0);
509  return GNUNET_OK;
510 }
511 
512 
520 int
522 {
523  uint32_t slen;
524 
525  slen = (uint32_t)((s == NULL) ? 0 : strlen(s) + 1);
526  if (GNUNET_OK != GNUNET_BIO_write_int32(h, slen))
527  return GNUNET_SYSERR;
528  if (0 != slen)
529  return GNUNET_BIO_write(h, s, slen - 1);
530  return GNUNET_OK;
531 }
532 
533 
541 int
543  const struct GNUNET_CONTAINER_MetaData *m)
544 {
545  ssize_t size;
546  char *buf;
547 
548  if (m == NULL)
549  return GNUNET_BIO_write_int32(h, 0);
550  buf = NULL;
552  m,
553  &buf,
556  if (size == -1)
557  {
558  GNUNET_free(buf);
559  return GNUNET_SYSERR;
560  }
561  if ((GNUNET_OK != GNUNET_BIO_write_int32(h, (uint32_t)size)) ||
562  (GNUNET_OK != GNUNET_BIO_write(h, buf, size)))
563  {
564  GNUNET_free(buf);
565  return GNUNET_SYSERR;
566  }
567  GNUNET_free(buf);
568  return GNUNET_OK;
569 }
570 
571 
579 int
581 {
582  int32_t big;
583 
584  big = htonl(i);
585  return GNUNET_BIO_write(h, &big, sizeof(int32_t));
586 }
587 
588 
596 int
598 {
599  int64_t big;
600 
601  big = GNUNET_htonll(i);
602  return GNUNET_BIO_write(h, &big, sizeof(int64_t));
603 }
604 
605 
606 /* 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:542
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:1339
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:729
int GNUNET_BIO_write_string(struct GNUNET_BIO_WriteHandle *h, const char *s)
Write a string to a file.
Definition: bio.c:521
int GNUNET_BIO_flush(struct GNUNET_BIO_WriteHandle *h)
Force a buffered writer to flush its buffer.
Definition: bio.c:456
#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:597
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:337
struct GNUNET_DISK_FileHandle * fd
Underlying file abstraction.
Definition: bio.c:57
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.
#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:382
static int ret
Final status code.
Definition: gnunet-arm.c:89
int GNUNET_BIO_read_close(struct GNUNET_BIO_ReadHandle *h, char **emsg)
Close an open file.
Definition: bio.c:118
size_t size
Total size of buffer.
Definition: bio.c:77
#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:94
#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:93
static struct GNUNET_ARM_MonitorHandle * m
Monitor connection with ARM.
Definition: gnunet-arm.c:99
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:143
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:817
static char buf[2048]
size_t have
Number of bytes available in read buffer.
Definition: bio.c:72
size_t have
Number of bytes already in buffer.
Definition: bio.c:392
static int result
Global testing status.
char * buffer
I/O buffer.
Definition: bio.c:387
Handle for buffered writing.
Definition: bio.c:378
char * buffer
I/O buffer.
Definition: bio.c:67
off_t pos
Current read offset in buffer.
Definition: bio.c:82
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:232
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:436
#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:208
struct GNUNET_BIO_WriteHandle * GNUNET_BIO_write_open(const char *fn)
Open a file for writing.
Definition: bio.c:408
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:361
size_t size
Total size of buffer.
Definition: bio.c:397
int GNUNET_BIO_write_int32(struct GNUNET_BIO_WriteHandle *h, int32_t i)
Write an (u)int32_t.
Definition: bio.c:580
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:284
int GNUNET_BIO_write(struct GNUNET_BIO_WriteHandle *h, const void *buffer, size_t n)
Write a buffer to a file.
Definition: bio.c:481
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:1262
char * emsg
Error message, NULL if there were no errors.
Definition: bio.c:62
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...