GNUnet  0.11.x
disk.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2001--2013, 2016, 2018 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  */
26 #include "platform.h"
27 #include "disk.h"
28 #include "gnunet_strings_lib.h"
29 #include "gnunet_disk_lib.h"
30 
31 #define LOG(kind, ...) GNUNET_log_from (kind, "util-disk", __VA_ARGS__)
32 
33 #define LOG_STRERROR(kind, syscall) \
34  GNUNET_log_from_strerror (kind, "util-disk", syscall)
35 
36 #define LOG_STRERROR_FILE(kind, syscall, filename) \
37  GNUNET_log_from_strerror_file (kind, "util-disk", syscall, filename)
38 
42 #define COPY_BLK_SIZE 65536
43 
44 #include <sys/types.h>
45 #if HAVE_SYS_VFS_H
46 #include <sys/vfs.h>
47 #endif
48 #if HAVE_SYS_PARAM_H
49 #include <sys/param.h>
50 #endif
51 #if HAVE_SYS_MOUNT_H
52 #include <sys/mount.h>
53 #endif
54 #if HAVE_SYS_STATVFS_H
55 #include <sys/statvfs.h>
56 #endif
57 
58 #ifndef S_ISLNK
59 #define _IFMT 0170000 /* type of file */
60 #define _IFLNK 0120000 /* symbolic link */
61 #define S_ISLNK(m) (((m) & _IFMT) == _IFLNK)
62 #endif
63 
64 
69 {
75 };
76 
77 
83 {
87  uint64_t total;
88 
93 
98 };
99 
100 
108 static int
110 {
111  int mode;
112 
113  mode = 0;
114  if (perm & GNUNET_DISK_PERM_USER_READ)
115  mode |= S_IRUSR;
116  if (perm & GNUNET_DISK_PERM_USER_WRITE)
117  mode |= S_IWUSR;
118  if (perm & GNUNET_DISK_PERM_USER_EXEC)
119  mode |= S_IXUSR;
120  if (perm & GNUNET_DISK_PERM_GROUP_READ)
121  mode |= S_IRGRP;
122  if (perm & GNUNET_DISK_PERM_GROUP_WRITE)
123  mode |= S_IWGRP;
124  if (perm & GNUNET_DISK_PERM_GROUP_EXEC)
125  mode |= S_IXGRP;
126  if (perm & GNUNET_DISK_PERM_OTHER_READ)
127  mode |= S_IROTH;
128  if (perm & GNUNET_DISK_PERM_OTHER_WRITE)
129  mode |= S_IWOTH;
130  if (perm & GNUNET_DISK_PERM_OTHER_EXEC)
131  mode |= S_IXOTH;
132 
133  return mode;
134 }
135 
136 
145 static int
146 getSizeRec (void *cls, const char *fn)
147 {
148  struct GetFileSizeData *gfsd = cls;
149 
150 #if defined(HAVE_STAT64) && \
151  ! (defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64)
152  struct stat64 buf;
153 
154  if (0 != stat64 (fn, &buf))
155  {
157  return GNUNET_SYSERR;
158  }
159 #else
160  struct stat buf;
161 
162  if (0 != stat (fn, &buf))
163  {
165  return GNUNET_SYSERR;
166  }
167 #endif
168  if ((S_ISDIR (buf.st_mode)) && (gfsd->single_file_mode == GNUNET_YES))
169  {
170  errno = EISDIR;
171  return GNUNET_SYSERR;
172  }
173  if ((! S_ISLNK (buf.st_mode)) || (gfsd->include_sym_links == GNUNET_YES))
174  gfsd->total += buf.st_size;
175  if ((S_ISDIR (buf.st_mode)) && (0 == access (fn, X_OK)) &&
176  ((! S_ISLNK (buf.st_mode)) || (gfsd->include_sym_links == GNUNET_YES)))
177  {
179  return GNUNET_SYSERR;
180  }
181  return GNUNET_OK;
182 }
183 
184 
191 int
193 {
194  return ((! h) || (h->fd == -1)) ? GNUNET_YES : GNUNET_NO;
195 }
196 
197 
205 int
207 {
208  struct stat sbuf;
209 
210  if (0 != fstat (fh->fd, &sbuf))
211  return GNUNET_SYSERR;
212  *size = sbuf.st_size;
213  return GNUNET_OK;
214 }
215 
216 
225 off_t
227  off_t offset,
228  enum GNUNET_DISK_Seek whence)
229 {
230  if (h == NULL)
231  {
232  errno = EINVAL;
233  return GNUNET_SYSERR;
234  }
235 
236  static int t[] = { SEEK_SET, SEEK_CUR, SEEK_END };
237 
238  return lseek (h->fd, offset, t[whence]);
239 }
240 
241 
256 int
258  uint64_t *size,
259  int include_symbolic_links,
260  int single_file_mode)
261 {
262  struct GetFileSizeData gfsd;
263  int ret;
264 
265  GNUNET_assert (size != NULL);
266  gfsd.total = 0;
267  gfsd.include_sym_links = include_symbolic_links;
269  ret = getSizeRec (&gfsd, filename);
270  *size = gfsd.total;
271  return ret;
272 }
273 
274 
290 int
292  uint64_t *dev,
293  uint64_t *ino)
294 {
295 #if HAVE_STAT
296  {
297  struct stat sbuf;
298 
299  if (0 != stat (filename, &sbuf))
300  {
301  return GNUNET_SYSERR;
302  }
303  *ino = (uint64_t) sbuf.st_ino;
304  }
305 #else
306  *ino = 0;
307 #endif
308 #if HAVE_STATVFS
309  {
310  struct statvfs fbuf;
311 
312  if (0 != statvfs (filename, &fbuf))
313  {
314  return GNUNET_SYSERR;
315  }
316  *dev = (uint64_t) fbuf.f_fsid;
317  }
318 #elif HAVE_STATFS
319  {
320  struct statfs fbuf;
321 
322  if (0 != statfs (filename, &fbuf))
323  {
324  return GNUNET_SYSERR;
325  }
326  *dev =
327  ((uint64_t) fbuf.f_fsid.val[0]) << 32 || ((uint64_t) fbuf.f_fsid.val[1]);
328  }
329 #else
330  *dev = 0;
331 #endif
332  return GNUNET_OK;
333 }
334 
335 
342 static char *
343 mktemp_name (const char *t)
344 {
345  const char *tmpdir;
346  char *tmpl;
347  char *fn;
348 
349  if ((t[0] != '/') && (t[0] != '\\'))
350  {
351  /* FIXME: This uses system codepage on W32, not UTF-8 */
352  tmpdir = getenv ("TMPDIR");
353  if (NULL == tmpdir)
354  tmpdir = getenv ("TMP");
355  if (NULL == tmpdir)
356  tmpdir = getenv ("TEMP");
357  if (NULL == tmpdir)
358  tmpdir = "/tmp";
359  GNUNET_asprintf (&tmpl, "%s/%s%s", tmpdir, t, "XXXXXX");
360  }
361  else
362  {
363  GNUNET_asprintf (&tmpl, "%s%s", t, "XXXXXX");
364  }
365  fn = tmpl;
366  return fn;
367 }
368 
369 
378 void
380  int require_uid_match,
381  int require_gid_match)
382 {
383  mode_t mode;
384 
385  if (GNUNET_YES == require_uid_match)
386  mode = S_IRUSR | S_IWUSR | S_IXUSR;
387  else if (GNUNET_YES == require_gid_match)
388  mode = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP;
389  else
390  mode = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH
391  | S_IWOTH | S_IXOTH;
392  if (0 != chmod (fn, mode))
394 }
395 
396 
408 char *
409 GNUNET_DISK_mkdtemp (const char *t)
410 {
411  char *fn;
412  mode_t omask;
413 
414  omask = umask (S_IWGRP | S_IWOTH | S_IRGRP | S_IROTH);
415  fn = mktemp_name (t);
416  if (fn != mkdtemp (fn))
417  {
419  GNUNET_free (fn);
420  umask (omask);
421  return NULL;
422  }
423  umask (omask);
424  return fn;
425 }
426 
427 
435 void
436 GNUNET_DISK_file_backup (const char *fil)
437 {
438  size_t slen;
439  char *target;
440  unsigned int num;
441 
442  slen = strlen (fil) + 20;
443  target = GNUNET_malloc (slen);
444  num = 0;
445  do
446  {
447  GNUNET_snprintf (target, slen, "%s.%u~", fil, num++);
448  }
449  while (0 == access (target, F_OK));
450  if (0 != rename (fil, target))
452  GNUNET_free (target);
453 }
454 
455 
467 char *
468 GNUNET_DISK_mktemp (const char *t)
469 {
470  int fd;
471  char *fn;
472  mode_t omask;
473 
474  omask = umask (S_IWGRP | S_IWOTH | S_IRGRP | S_IROTH);
475  fn = mktemp_name (t);
476  if (-1 == (fd = mkstemp (fn)))
477  {
479  GNUNET_free (fn);
480  umask (omask);
481  return NULL;
482  }
483  umask (omask);
484  if (0 != close (fd))
486  return fn;
487 }
488 
489 
502 int
503 GNUNET_DISK_directory_test (const char *fil, int is_readable)
504 {
505  struct stat filestat;
506  int ret;
507 
508  ret = stat (fil, &filestat);
509  if (ret != 0)
510  {
511  if (errno != ENOENT)
513  return GNUNET_SYSERR;
514  }
515  if (! S_ISDIR (filestat.st_mode))
516  {
518  "A file already exits with the same name %s\n",
519  fil);
520  return GNUNET_NO;
521  }
522  if (GNUNET_YES == is_readable)
523  ret = access (fil, R_OK | X_OK);
524  else
525  ret = access (fil, X_OK);
526  if (ret < 0)
527  {
529  return GNUNET_NO;
530  }
531  return GNUNET_YES;
532 }
533 
534 
543 int
544 GNUNET_DISK_file_test (const char *fil)
545 {
546  struct stat filestat;
547  int ret;
548  char *rdir;
549 
550  rdir = GNUNET_STRINGS_filename_expand (fil);
551  if (rdir == NULL)
552  return GNUNET_SYSERR;
553 
554  ret = stat (rdir, &filestat);
555  if (ret != 0)
556  {
557  if (errno != ENOENT)
558  {
560  GNUNET_free (rdir);
561  return GNUNET_SYSERR;
562  }
563  GNUNET_free (rdir);
564  return GNUNET_NO;
565  }
566  if (! S_ISREG (filestat.st_mode))
567  {
568  GNUNET_free (rdir);
569  return GNUNET_NO;
570  }
571  if (access (rdir, F_OK) < 0)
572  {
574  GNUNET_free (rdir);
575  return GNUNET_SYSERR;
576  }
577  GNUNET_free (rdir);
578  return GNUNET_YES;
579 }
580 
581 
588 int
590 {
591  char *rdir;
592  unsigned int len;
593  unsigned int pos;
594  unsigned int pos2;
595  int ret = GNUNET_OK;
596 
597  rdir = GNUNET_STRINGS_filename_expand (dir);
598  if (rdir == NULL)
599  {
600  GNUNET_break (0);
601  return GNUNET_SYSERR;
602  }
603 
604  len = strlen (rdir);
605 
606  pos = 1; /* skip heading '/' */
607 
608  /* Check which low level directories already exist */
609  pos2 = len;
610  rdir[len] = DIR_SEPARATOR;
611  while (pos <= pos2)
612  {
613  if (DIR_SEPARATOR == rdir[pos2])
614  {
615  rdir[pos2] = '\0';
617  if (GNUNET_NO == ret)
618  {
620  "Creating directory `%s' failed",
621  rdir);
622  GNUNET_free (rdir);
623  return GNUNET_SYSERR;
624  }
625  rdir[pos2] = DIR_SEPARATOR;
626  if (GNUNET_YES == ret)
627  {
628  pos2++;
629  break;
630  }
631  }
632  pos2--;
633  }
634  rdir[len] = '\0';
635  if (pos < pos2)
636  pos = pos2;
637  /* Start creating directories */
638  while (pos <= len)
639  {
640  if ((rdir[pos] == DIR_SEPARATOR) || (pos == len))
641  {
642  rdir[pos] = '\0';
644  if (GNUNET_NO == ret)
645  {
647  "Creating directory `%s' failed",
648  rdir);
649  GNUNET_free (rdir);
650  return GNUNET_SYSERR;
651  }
652  if (GNUNET_SYSERR == ret)
653  {
654  ret = mkdir (rdir,
655  S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH
656  | S_IXOTH); /* 755 */
657 
658  if ((ret != 0) && (errno != EEXIST))
659  {
661  GNUNET_free (rdir);
662  return GNUNET_SYSERR;
663  }
664  }
665  rdir[pos] = DIR_SEPARATOR;
666  }
667  pos++;
668  }
669  GNUNET_free (rdir);
670  return GNUNET_OK;
671 }
672 
673 
683 int
685 {
686  char *rdir;
687  size_t len;
688  int ret;
689  int eno;
690 
691  rdir = GNUNET_STRINGS_filename_expand (filename);
692  if (NULL == rdir)
693  {
694  errno = EINVAL;
695  return GNUNET_SYSERR;
696  }
697  if (0 == access (rdir, W_OK))
698  {
699  GNUNET_free (rdir);
700  return GNUNET_OK;
701  }
702 
703  len = strlen (rdir);
704  while ((len > 0) && (rdir[len] != DIR_SEPARATOR))
705  len--;
706  rdir[len] = '\0';
707  /* The empty path is invalid and in this case refers to / */
708  if (0 == len)
709  {
710  GNUNET_free (rdir);
711  rdir = GNUNET_strdup ("/");
712  }
713  ret = GNUNET_DISK_directory_create (rdir);
714  if ((GNUNET_OK == ret) && (0 != access (rdir, W_OK)))
715  ret = GNUNET_NO;
716  eno = errno;
717  GNUNET_free (rdir);
718  errno = eno;
719  return ret;
720 }
721 
722 
731 ssize_t
733  void *result,
734  size_t len)
735 {
736  if (NULL == h)
737  {
738  errno = EINVAL;
739  return GNUNET_SYSERR;
740  }
741 
742  return read (h->fd, result, len);
743 }
744 
745 
756 ssize_t
758  void *result,
759  size_t len)
760 {
761  if (NULL == h)
762  {
763  errno = EINVAL;
764  return GNUNET_SYSERR;
765  }
766 
767  int flags;
768  ssize_t ret;
769 
770  /* set to non-blocking, read, then set back */
771  flags = fcntl (h->fd, F_GETFL);
772  if (0 == (flags & O_NONBLOCK))
773  (void) fcntl (h->fd, F_SETFL, flags | O_NONBLOCK);
774  ret = read (h->fd, result, len);
775  if (0 == (flags & O_NONBLOCK))
776  {
777  int eno = errno;
778  (void) fcntl (h->fd, F_SETFL, flags);
779  errno = eno;
780  }
781  return ret;
782 }
783 
784 
793 ssize_t
794 GNUNET_DISK_fn_read (const char *fn, void *result, size_t len)
795 {
796  struct GNUNET_DISK_FileHandle *fh;
797  ssize_t ret;
798  int eno;
799 
801  if (NULL == fh)
802  return GNUNET_SYSERR;
803  ret = GNUNET_DISK_file_read (fh, result, len);
804  eno = errno;
806  errno = eno;
807  return ret;
808 }
809 
810 
819 ssize_t
821  const void *buffer,
822  size_t n)
823 {
824  if (NULL == h)
825  {
826  errno = EINVAL;
827  return GNUNET_SYSERR;
828  }
829 
830  return write (h->fd, buffer, n);
831 }
832 
833 
842 ssize_t
844  const void *buffer,
845  size_t n)
846 {
847  if (NULL == h)
848  {
849  errno = EINVAL;
850  return GNUNET_SYSERR;
851  }
852 
853 
854  int flags;
855  ssize_t ret;
856 
857  /* set to blocking, write, then set back */
858  flags = fcntl (h->fd, F_GETFL);
859  if (0 != (flags & O_NONBLOCK))
860  (void) fcntl (h->fd, F_SETFL, flags - O_NONBLOCK);
861  ret = write (h->fd, buffer, n);
862  if (0 == (flags & O_NONBLOCK))
863  (void) fcntl (h->fd, F_SETFL, flags);
864  return ret;
865 }
866 
867 
878 ssize_t
880  const void *buffer,
881  size_t n,
883 {
884  struct GNUNET_DISK_FileHandle *fh;
885  ssize_t ret;
886 
887  fh =
891  mode);
892  if (! fh)
893  return GNUNET_SYSERR;
894  ret = GNUNET_DISK_file_write (fh, buffer, n);
896  return ret;
897 }
898 
899 
910 int
912  GNUNET_FileNameCallback callback,
913  void *callback_cls)
914 {
915  DIR *dinfo;
916  struct dirent *finfo;
917  struct stat istat;
918  int count = 0;
919  int ret;
920  char *name;
921  char *dname;
922  unsigned int name_len;
923  unsigned int n_size;
924 
925  GNUNET_assert (NULL != dir_name);
926  dname = GNUNET_STRINGS_filename_expand (dir_name);
927  if (NULL == dname)
928  return GNUNET_SYSERR;
929  while ((strlen (dname) > 0) && (dname[strlen (dname) - 1] == DIR_SEPARATOR))
930  dname[strlen (dname) - 1] = '\0';
931  if (0 != stat (dname, &istat))
932  {
934  GNUNET_free (dname);
935  return GNUNET_SYSERR;
936  }
937  if (! S_ISDIR (istat.st_mode))
938  {
940  _ ("Expected `%s' to be a directory!\n"),
941  dir_name);
942  GNUNET_free (dname);
943  return GNUNET_SYSERR;
944  }
945  errno = 0;
946  dinfo = opendir (dname);
947  if ((EACCES == errno) || (NULL == dinfo))
948  {
949  LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "opendir", dname);
950  if (NULL != dinfo)
951  closedir (dinfo);
952  GNUNET_free (dname);
953  return GNUNET_SYSERR;
954  }
955  name_len = 256;
956  n_size = strlen (dname) + name_len + strlen (DIR_SEPARATOR_STR) + 1;
957  name = GNUNET_malloc (n_size);
958  while (NULL != (finfo = readdir (dinfo)))
959  {
960  if ((0 == strcmp (finfo->d_name, ".")) ||
961  (0 == strcmp (finfo->d_name, "..")))
962  continue;
963  if (NULL != callback)
964  {
965  if (name_len < strlen (finfo->d_name))
966  {
967  GNUNET_free (name);
968  name_len = strlen (finfo->d_name);
969  n_size = strlen (dname) + name_len + strlen (DIR_SEPARATOR_STR) + 1;
970  name = GNUNET_malloc (n_size);
971  }
972  /* dname can end in "/" only if dname == "/";
973  * if dname does not end in "/", we need to add
974  * a "/" (otherwise, we must not!) */
975  GNUNET_snprintf (name,
976  n_size,
977  "%s%s%s",
978  dname,
979  (0 == strcmp (dname, DIR_SEPARATOR_STR))
980  ? ""
982  finfo->d_name);
983  ret = callback (callback_cls, name);
984  if (GNUNET_OK != ret)
985  {
986  closedir (dinfo);
987  GNUNET_free (name);
988  GNUNET_free (dname);
989  if (GNUNET_NO == ret)
990  return count;
991  return GNUNET_SYSERR;
992  }
993  }
994  count++;
995  }
996  closedir (dinfo);
997  GNUNET_free (name);
998  GNUNET_free (dname);
999  return count;
1000 }
1001 
1002 
1011 static int
1012 remove_helper (void *unused, const char *fn)
1013 {
1014  (void) unused;
1015  (void) GNUNET_DISK_directory_remove (fn);
1016  return GNUNET_OK;
1017 }
1018 
1019 
1027 int
1029 {
1030  struct stat istat;
1031 
1032  if (NULL == filename)
1033  {
1034  GNUNET_break (0);
1035  return GNUNET_SYSERR;
1036  }
1037  if (0 != lstat (filename, &istat))
1038  return GNUNET_NO; /* file may not exist... */
1039  (void) chmod (filename, S_IWUSR | S_IRUSR | S_IXUSR);
1040  if (0 == unlink (filename))
1041  return GNUNET_OK;
1042  if ((errno != EISDIR) &&
1043  /* EISDIR is not sufficient in all cases, e.g.
1044  * sticky /tmp directory may result in EPERM on BSD.
1045  * So we also explicitly check "isDirectory" */
1047  {
1048  LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "rmdir", filename);
1049  return GNUNET_SYSERR;
1050  }
1051  if (GNUNET_SYSERR ==
1052  GNUNET_DISK_directory_scan (filename, &remove_helper, NULL))
1053  return GNUNET_SYSERR;
1054  if (0 != rmdir (filename))
1055  {
1056  LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "rmdir", filename);
1057  return GNUNET_SYSERR;
1058  }
1059  return GNUNET_OK;
1060 }
1061 
1062 
1070 int
1071 GNUNET_DISK_file_copy (const char *src, const char *dst)
1072 {
1073  char *buf;
1074  uint64_t pos;
1075  uint64_t size;
1076  size_t len;
1077  ssize_t sret;
1078  struct GNUNET_DISK_FileHandle *in;
1079  struct GNUNET_DISK_FileHandle *out;
1080 
1081  if (GNUNET_OK != GNUNET_DISK_file_size (src, &size, GNUNET_YES, GNUNET_YES))
1082  {
1084  return GNUNET_SYSERR;
1085  }
1086  pos = 0;
1087  in =
1089  if (! in)
1090  {
1092  return GNUNET_SYSERR;
1093  }
1094  out =
1095  GNUNET_DISK_file_open (dst,
1102  if (! out)
1103  {
1106  return GNUNET_SYSERR;
1107  }
1108  buf = GNUNET_malloc (COPY_BLK_SIZE);
1109  while (pos < size)
1110  {
1111  len = COPY_BLK_SIZE;
1112  if (len > size - pos)
1113  len = size - pos;
1114  sret = GNUNET_DISK_file_read (in, buf, len);
1115  if ((sret < 0) || (len != (size_t) sret))
1116  goto FAIL;
1117  sret = GNUNET_DISK_file_write (out, buf, len);
1118  if ((sret < 0) || (len != (size_t) sret))
1119  goto FAIL;
1120  pos += len;
1121  }
1122  GNUNET_free (buf);
1124  GNUNET_DISK_file_close (out);
1125  return GNUNET_OK;
1126 FAIL:
1127  GNUNET_free (buf);
1129  GNUNET_DISK_file_close (out);
1130  return GNUNET_SYSERR;
1131 }
1132 
1133 
1138 void
1140 {
1141  char *idx;
1142  char c;
1143 
1144  for (idx = fn; *idx; idx++)
1145  {
1146  c = *idx;
1147 
1148  if ((c == '/') || (c == '\\') || (c == ':') || (c == '*') || (c == '?') ||
1149  (c ==
1150  '"')
1151  ||
1152  (c == '<') || (c == '>') || (c == '|') )
1153  {
1154  *idx = '_';
1155  }
1156  }
1157 }
1158 
1159 
1167 int
1168 GNUNET_DISK_file_change_owner (const char *filename, const char *user)
1169 {
1170  struct passwd *pws;
1171 
1172  pws = getpwnam (user);
1173  if (NULL == pws)
1174  {
1176  _ ("Cannot obtain information about user `%s': %s\n"),
1177  user,
1178  strerror (errno));
1179  return GNUNET_SYSERR;
1180  }
1181  if (0 != chown (filename, pws->pw_uid, pws->pw_gid))
1182  {
1183  LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "chown", filename);
1184  return GNUNET_SYSERR;
1185  }
1186  return GNUNET_OK;
1187 }
1188 
1189 
1202 struct GNUNET_DISK_FileHandle *
1204  enum GNUNET_DISK_OpenFlags flags,
1206 {
1207  char *expfn;
1208  struct GNUNET_DISK_FileHandle *ret;
1209 
1210  int oflags;
1211  int mode;
1212  int fd;
1213 
1214  expfn = GNUNET_STRINGS_filename_expand (fn);
1215  if (NULL == expfn)
1216  return NULL;
1217 
1218  mode = 0;
1220  oflags = O_RDWR; /* note: O_RDWR is NOT always O_RDONLY | O_WRONLY */
1221  else if (flags & GNUNET_DISK_OPEN_READ)
1222  oflags = O_RDONLY;
1223  else if (flags & GNUNET_DISK_OPEN_WRITE)
1224  oflags = O_WRONLY;
1225  else
1226  {
1227  GNUNET_break (0);
1228  GNUNET_free (expfn);
1229  return NULL;
1230  }
1231  if (flags & GNUNET_DISK_OPEN_FAILIFEXISTS)
1232  oflags |= (O_CREAT | O_EXCL);
1233  if (flags & GNUNET_DISK_OPEN_TRUNCATE)
1234  oflags |= O_TRUNC;
1235  if (flags & GNUNET_DISK_OPEN_APPEND)
1236  oflags |= O_APPEND;
1237  if (GNUNET_NO == GNUNET_DISK_file_test (fn))
1238  {
1239  if (flags & GNUNET_DISK_OPEN_CREATE)
1240  {
1242  oflags |= O_CREAT;
1243  mode = translate_unix_perms (perm);
1244  }
1245  }
1246 
1247  fd = open (expfn,
1248  oflags
1249 #if O_CLOEXEC
1250  | O_CLOEXEC
1251 #endif
1252  | O_LARGEFILE,
1253  mode);
1254  if (fd == -1)
1255  {
1256  if (0 == (flags & GNUNET_DISK_OPEN_FAILIFEXISTS))
1258  else
1259  LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_DEBUG, "open", expfn);
1260  GNUNET_free (expfn);
1261  return NULL;
1262  }
1263 
1264  ret = GNUNET_new (struct GNUNET_DISK_FileHandle);
1265 
1266  ret->fd = fd;
1267 
1268  GNUNET_free (expfn);
1269  return ret;
1270 }
1271 
1272 
1279 int
1281 {
1282  int ret;
1283 
1284  if (h == NULL)
1285  {
1286  errno = EINVAL;
1287  return GNUNET_SYSERR;
1288  }
1289 
1290  ret = GNUNET_OK;
1291 
1292  if (close (h->fd) != 0)
1293  {
1295  ret = GNUNET_SYSERR;
1296  }
1297 
1298  GNUNET_free (h);
1299  return ret;
1300 }
1301 
1302 
1309 struct GNUNET_DISK_FileHandle *
1311 {
1312  struct GNUNET_DISK_FileHandle *fh;
1313 
1314  if ((((off_t) -1) == lseek (fno, 0, SEEK_CUR)) && (EBADF == errno))
1315  return NULL; /* invalid FD */
1316 
1317  fh = GNUNET_new (struct GNUNET_DISK_FileHandle);
1318 
1319  fh->fd = fno;
1320 
1321  return fh;
1322 }
1323 
1324 
1331 struct GNUNET_DISK_FileHandle *
1333 {
1334  int fno;
1335 
1336  fno = fileno (fd);
1337  if (-1 == fno)
1338  return NULL;
1339 
1341 }
1342 
1343 
1348 {
1352  void *addr;
1353 
1357  size_t len;
1358 };
1359 
1360 
1361 #ifndef MAP_FAILED
1362 #define MAP_FAILED ((void *) -1)
1363 #endif
1364 
1374 void *
1376  struct GNUNET_DISK_MapHandle **m,
1377  enum GNUNET_DISK_MapType access,
1378  size_t len)
1379 {
1380  if (NULL == h)
1381  {
1382  errno = EINVAL;
1383  return NULL;
1384  }
1385 
1386  int prot;
1387 
1388  prot = 0;
1389  if (access & GNUNET_DISK_MAP_TYPE_READ)
1390  prot = PROT_READ;
1391  if (access & GNUNET_DISK_MAP_TYPE_WRITE)
1392  prot |= PROT_WRITE;
1393  *m = GNUNET_new (struct GNUNET_DISK_MapHandle);
1394  (*m)->addr = mmap (NULL, len, prot, MAP_SHARED, h->fd, 0);
1395  GNUNET_assert (NULL != (*m)->addr);
1396  if (MAP_FAILED == (*m)->addr)
1397  {
1398  GNUNET_free (*m);
1399  return NULL;
1400  }
1401  (*m)->len = len;
1402  return (*m)->addr;
1403 }
1404 
1405 
1411 int
1413 {
1414  int ret;
1415 
1416  if (h == NULL)
1417  {
1418  errno = EINVAL;
1419  return GNUNET_SYSERR;
1420  }
1421 
1422  ret = munmap (h->addr, h->len) != -1 ? GNUNET_OK : GNUNET_SYSERR;
1423 
1424  GNUNET_free (h);
1425  return ret;
1426 }
1427 
1428 
1434 int
1436 {
1437  if (h == NULL)
1438  {
1439  errno = EINVAL;
1440  return GNUNET_SYSERR;
1441  }
1442 
1443 #if ! defined(__linux__) || ! defined(GNU)
1444  return fsync (h->fd) == -1 ? GNUNET_SYSERR : GNUNET_OK;
1445 #else
1446  return fdatasync (h->fd) == -1 ? GNUNET_SYSERR : GNUNET_OK;
1447 #endif
1448 }
1449 
1450 
1460 struct GNUNET_DISK_PipeHandle *
1461 GNUNET_DISK_pipe (int blocking_read,
1462  int blocking_write,
1463  int inherit_read,
1464  int inherit_write)
1465 {
1466  int fd[2];
1467  int ret;
1468  int eno;
1469 
1470  (void) inherit_read;
1471  (void) inherit_write;
1472  ret = pipe (fd);
1473  if (ret == -1)
1474  {
1475  eno = errno;
1477  errno = eno;
1478  return NULL;
1479  }
1480  return GNUNET_DISK_pipe_from_fd (blocking_read, blocking_write, fd);
1481 }
1482 
1483 
1494 struct GNUNET_DISK_PipeHandle *
1495 GNUNET_DISK_pipe_from_fd (int blocking_read, int blocking_write, int fd[2])
1496 {
1497  struct GNUNET_DISK_PipeHandle *p;
1498 
1499  p = GNUNET_new (struct GNUNET_DISK_PipeHandle);
1500 
1501  int ret;
1502  int flags;
1503  int eno = 0; /* make gcc happy */
1504 
1505  ret = 0;
1506  if (fd[0] >= 0)
1507  {
1508  p->fd[0] = GNUNET_new (struct GNUNET_DISK_FileHandle);
1509  p->fd[0]->fd = fd[0];
1510  if (! blocking_read)
1511  {
1512  flags = fcntl (fd[0], F_GETFL);
1513  flags |= O_NONBLOCK;
1514  if (0 > fcntl (fd[0], F_SETFL, flags))
1515  {
1516  ret = -1;
1517  eno = errno;
1518  }
1519  }
1520  flags = fcntl (fd[0], F_GETFD);
1521  flags |= FD_CLOEXEC;
1522  if (0 > fcntl (fd[0], F_SETFD, flags))
1523  {
1524  ret = -1;
1525  eno = errno;
1526  }
1527  }
1528 
1529  if (fd[1] >= 0)
1530  {
1531  p->fd[1] = GNUNET_new (struct GNUNET_DISK_FileHandle);
1532  p->fd[1]->fd = fd[1];
1533  if (! blocking_write)
1534  {
1535  flags = fcntl (fd[1], F_GETFL);
1536  flags |= O_NONBLOCK;
1537  if (0 > fcntl (fd[1], F_SETFL, flags))
1538  {
1539  ret = -1;
1540  eno = errno;
1541  }
1542  }
1543  flags = fcntl (fd[1], F_GETFD);
1544  flags |= FD_CLOEXEC;
1545  if (0 > fcntl (fd[1], F_SETFD, flags))
1546  {
1547  ret = -1;
1548  eno = errno;
1549  }
1550  }
1551  if (ret == -1)
1552  {
1553  errno = eno;
1555  if (p->fd[0]->fd >= 0)
1556  GNUNET_break (0 == close (p->fd[0]->fd));
1557  if (p->fd[1]->fd >= 0)
1558  GNUNET_break (0 == close (p->fd[1]->fd));
1559  GNUNET_free (p->fd[0]);
1560  GNUNET_free (p->fd[1]);
1561  GNUNET_free (p);
1562  errno = eno;
1563  return NULL;
1564  }
1565 
1566  return p;
1567 }
1568 
1569 
1577 int
1579  enum GNUNET_DISK_PipeEnd end)
1580 {
1581  int ret = GNUNET_OK;
1582 
1583  if (end == GNUNET_DISK_PIPE_END_READ)
1584  {
1585  if (p->fd[0])
1586  {
1587  ret = GNUNET_DISK_file_close (p->fd[0]);
1588  p->fd[0] = NULL;
1589  }
1590  }
1591  else if (end == GNUNET_DISK_PIPE_END_WRITE)
1592  {
1593  if (p->fd[1])
1594  {
1595  ret = GNUNET_DISK_file_close (p->fd[1]);
1596  p->fd[1] = NULL;
1597  }
1598  }
1599 
1600  return ret;
1601 }
1602 
1603 
1616 struct GNUNET_DISK_FileHandle *
1618  enum GNUNET_DISK_PipeEnd end)
1619 {
1620  struct GNUNET_DISK_FileHandle *ret = NULL;
1621 
1622  if (end == GNUNET_DISK_PIPE_END_READ)
1623  {
1624  if (p->fd[0])
1625  {
1626  ret = p->fd[0];
1627  p->fd[0] = NULL;
1628  }
1629  }
1630  else if (end == GNUNET_DISK_PIPE_END_WRITE)
1631  {
1632  if (p->fd[1])
1633  {
1634  ret = p->fd[1];
1635  p->fd[1] = NULL;
1636  }
1637  }
1638 
1639  return ret;
1640 }
1641 
1642 
1649 int
1651 {
1652  int ret = GNUNET_OK;
1653 
1654  int read_end_close;
1655  int write_end_close;
1656  int read_end_close_errno;
1657  int write_end_close_errno;
1658 
1660  read_end_close_errno = errno;
1662  write_end_close_errno = errno;
1663  GNUNET_free (p);
1664 
1665  if (GNUNET_OK != read_end_close)
1666  {
1667  errno = read_end_close_errno;
1668  ret = read_end_close;
1669  }
1670  else if (GNUNET_OK != write_end_close)
1671  {
1672  errno = write_end_close_errno;
1673  ret = write_end_close;
1674  }
1675 
1676  return ret;
1677 }
1678 
1679 
1687 const struct GNUNET_DISK_FileHandle *
1689  enum GNUNET_DISK_PipeEnd n)
1690 {
1691  switch (n)
1692  {
1695  return p->fd[n];
1696 
1697  default:
1698  GNUNET_break (0);
1699  return NULL;
1700  }
1701 }
1702 
1703 
1712 int
1714  void *dst,
1715  size_t dst_len)
1716 {
1717  if (NULL == fh)
1718  return GNUNET_SYSERR;
1719 
1720  if (dst_len < sizeof(int))
1721  return GNUNET_SYSERR;
1722  *((int *) dst) = fh->fd;
1723 
1724  return GNUNET_OK;
1725 }
1726 
1727 
1735 static int
1737 {
1738  const char *option = cls;
1739  char *tmpname;
1740 
1741  if (GNUNET_OK !=
1742  GNUNET_CONFIGURATION_get_value_filename (cfg, "PATHS", option, &tmpname))
1743  {
1745  return GNUNET_NO;
1746  }
1748  {
1750  GNUNET_free (tmpname);
1751  return GNUNET_OK;
1752  }
1753  GNUNET_free (tmpname);
1754  return GNUNET_OK;
1755 }
1756 
1757 
1765 void
1767 {
1769  GNUNET_CONFIGURATION_parse_and_run (cfg_filename,
1770  &purge_cfg_dir,
1771  (void *) option));
1772 }
1773 
1774 
1775 /* end of disk.c */
void GNUNET_DISK_purge_cfg_dir(const char *cfg_filename, const char *option)
Remove the directory given under option in section [PATHS] in configuration under cfg_filename...
Definition: disk.c:1766
int GNUNET_DISK_file_test(const char *fil)
Check that fil corresponds to a filename (of a file that exists and that is not a directory)...
Definition: disk.c:544
Open the file for reading.
int GNUNET_DISK_file_sync(const struct GNUNET_DISK_FileHandle *h)
Write file changes to disk.
Definition: disk.c:1435
static char * cfg_filename
Name of the configuration file.
static char * dir
Set to the directory where runtime files are stored.
Definition: gnunet-arm.c:89
Create file if it doesn&#39;t exist.
GNUNET_DISK_MapType
Specifies what type of memory map is desired.
void * addr
Address where the map is in memory.
Definition: disk.c:1352
static const char * dir_name
Top-level directory we monitor to auto-publish.
int GNUNET_DISK_file_close(struct GNUNET_DISK_FileHandle *h)
Close an open file.
Definition: disk.c:1280
static const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration we are using.
Definition: gnunet-abd.c:36
int GNUNET_DISK_file_copy(const char *src, const char *dst)
Copy a file.
Definition: disk.c:1071
static int end
Set if we are to shutdown all services (including ARM).
Definition: gnunet-arm.c:34
uint64_t total
Set to the total file size.
Definition: disk.c:87
int single_file_mode
GNUNET_YES if mode is file-only (return total == -1 for directories).
Definition: disk.c:97
Closure for the recursion to determine the file size of a directory.
Definition: disk.c:82
int GNUNET_snprintf(char *buf, size_t size, const char *format,...)
Like snprintf, just aborts if the buffer is of insufficient size.
#define MAP_FAILED
Definition: disk.c:1362
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_DISK_directory_create(const char *dir)
Implementation of "mkdir -p".
Definition: disk.c:589
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
void * GNUNET_DISK_file_map(const struct GNUNET_DISK_FileHandle *h, struct GNUNET_DISK_MapHandle **m, enum GNUNET_DISK_MapType access, size_t len)
Map a file into memory.
Definition: disk.c:1375
Everybody can execute.
int GNUNET_DISK_directory_test(const char *fil, int is_readable)
Test if fil is a directory and listable.
Definition: disk.c:503
Nobody is allowed to do anything to the file.
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
GNUNET_DISK_Seek
Constants for specifying how to seek.
int GNUNET_DISK_directory_create_for_file(const char *filename)
Create the directory structure for storing a file.
Definition: disk.c:684
Append to the file.
int GNUNET_DISK_file_get_identifiers(const char *filename, uint64_t *dev, uint64_t *ino)
Obtain some unique identifiers for the given file that can be used to identify it in the local system...
Definition: disk.c:291
#define GNUNET_new(type)
Allocate a struct or union of the given type.
int GNUNET_DISK_directory_scan(const char *dir_name, GNUNET_FileNameCallback callback, void *callback_cls)
Scan a directory for files.
Definition: disk.c:911
static struct GNUNET_SCHEDULER_Task * t
Main task.
off_t GNUNET_DISK_file_seek(const struct GNUNET_DISK_FileHandle *h, off_t offset, enum GNUNET_DISK_Seek whence)
Move the read/write pointer in a file.
Definition: disk.c:226
static enum @8 mode
Should we do a PUT (mode = 0) or GET (mode = 1);.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define LOG_STRERROR(kind, syscall)
Definition: disk.c:33
ssize_t GNUNET_DISK_fn_write(const char *fn, const void *buffer, size_t n, enum GNUNET_DISK_AccessPermissions mode)
Write a buffer to a file.
Definition: disk.c:879
static int translate_unix_perms(enum GNUNET_DISK_AccessPermissions perm)
Translate GNUnet-internal permission bitmap to UNIX file access permission bitmap.
Definition: disk.c:109
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
int GNUNET_DISK_handle_invalid(const struct GNUNET_DISK_FileHandle *h)
Checks whether a handle is invalid.
Definition: disk.c:192
const struct GNUNET_DISK_FileHandle * GNUNET_DISK_pipe_handle(const struct GNUNET_DISK_PipeHandle *p, enum GNUNET_DISK_PipeEnd n)
Get the handle to a particular pipe end.
Definition: disk.c:1688
static struct GNUNET_ARM_Handle * h
Connection with ARM.
Definition: gnunet-arm.c:99
#define O_LARGEFILE
Definition: platform.h:224
#define _(String)
GNU gettext support macro.
Definition: platform.h:184
static struct GNUNET_ARM_MonitorHandle * m
Monitor connection with ARM.
Definition: gnunet-arm.c:104
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
struct GNUNET_DISK_FileHandle * fd[2]
File descriptors for the pipe.
Definition: disk.c:74
char * GNUNET_DISK_mktemp(const char *t)
Create an (empty) temporary file on disk.
Definition: disk.c:468
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-qr.c:59
void GNUNET_log_config_missing(enum GNUNET_ErrorType kind, const char *section, const char *option)
Log error message about missing configuration option.
size_t len
Number of bytes mapped.
Definition: disk.c:1357
struct GNUNET_DISK_FileHandle * GNUNET_DISK_pipe_detach_end(struct GNUNET_DISK_PipeHandle *p, enum GNUNET_DISK_PipeEnd end)
Detaches one of the ends from the pipe.
Definition: disk.c:1617
#define GNUNET_log_strerror_file(level, cmd, filename)
Log an error message at log-level &#39;level&#39; that indicates a failure of the command &#39;cmd&#39; with the mess...
static char * fn
Filename of the unique file.
static int remove_helper(void *unused, const char *fn)
Function that removes the given directory by calling GNUNET_DISK_directory_remove().
Definition: disk.c:1012
#define COPY_BLK_SIZE
Block size for IO for copying files.
Definition: disk.c:42
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
#define DIR_SEPARATOR_STR
Definition: platform.h:171
int GNUNET_DISK_directory_remove(const char *filename)
Remove all files in a directory (rm -r).
Definition: disk.c:1028
Read-only memory map.
static char * option
Name of the option.
Definition: gnunet-config.c:38
static char buf[2048]
static char * filename
static int result
Global testing status.
GNUNET_DISK_AccessPermissions
File access permissions, UNIX-style.
The writing-end of a pipe.
int include_sym_links
GNUNET_YES if symbolic links should be included.
Definition: disk.c:92
The reading-end of a pipe.
static int fh
Handle to the unique file.
void GNUNET_DISK_file_backup(const char *fil)
Move a file out of the way (create a backup) by renaming it to "orig.NUM~" where NUM is the smallest ...
Definition: disk.c:436
int(* GNUNET_FileNameCallback)(void *cls, const char *filename)
Function called with a filename.
#define LOG(kind,...)
Definition: disk.c:31
ssize_t GNUNET_DISK_file_write_blocking(const struct GNUNET_DISK_FileHandle *h, const void *buffer, size_t n)
Write a buffer to a file, blocking, if necessary.
Definition: disk.c:843
struct GNUNET_DISK_PipeHandle * GNUNET_DISK_pipe(int blocking_read, int blocking_write, int inherit_read, int inherit_write)
Creates an interprocess channel.
Definition: disk.c:1461
static int getSizeRec(void *cls, const char *fn)
Iterate over all files in the given directory and accumulate their size.
Definition: disk.c:146
#define DIR_SEPARATOR
Definition: platform.h:170
static unsigned int size
Size of the "table".
Definition: peer.c:67
int GNUNET_DISK_internal_file_handle_(const struct GNUNET_DISK_FileHandle *fh, void *dst, size_t dst_len)
Retrieve OS file handle.
Definition: disk.c:1713
Everybody can write.
int GNUNET_DISK_file_unmap(struct GNUNET_DISK_MapHandle *h)
Unmap a file.
Definition: disk.c:1412
Open the file for writing.
char * GNUNET_DISK_mkdtemp(const char *t)
Create an (empty) temporary directory on disk.
Definition: disk.c:409
char * GNUNET_STRINGS_filename_expand(const char *fil)
Complete filename (a la shell) from abbrevition.
Definition: strings.c:617
char * getenv()
int GNUNET_DISK_file_size(const char *filename, uint64_t *size, int include_symbolic_links, int single_file_mode)
Get the size of the file (or directory) of the given file (in bytes).
Definition: disk.c:257
#define S_ISLNK(m)
Definition: disk.c:61
int GNUNET_DISK_pipe_close(struct GNUNET_DISK_PipeHandle *p)
Closes an interprocess channel.
Definition: disk.c:1650
struct GNUNET_DISK_PipeHandle * GNUNET_DISK_pipe_from_fd(int blocking_read, int blocking_write, int fd[2])
Creates a pipe object from a couple of file descriptors.
Definition: disk.c:1495
#define LOG_STRERROR_FILE(kind, syscall, filename)
Definition: disk.c:36
Everybody can read.
int GNUNET_DISK_pipe_close_end(struct GNUNET_DISK_PipeHandle *p, enum GNUNET_DISK_PipeEnd end)
Closes an interprocess channel.
Definition: disk.c:1578
static int purge_cfg_dir(void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg)
Helper function for GNUNET_DISK_purge_cfg_dir.
Definition: disk.c:1736
struct GNUNET_DISK_FileHandle * GNUNET_DISK_get_handle_from_int_fd(int fno)
Get a handle from a native integer FD.
Definition: disk.c:1310
configuration data
Definition: configuration.c:84
const char * name
int GNUNET_DISK_file_handle_size(struct GNUNET_DISK_FileHandle *fh, off_t *size)
Get the size of an open file.
Definition: disk.c:206
#define GNUNET_log(kind,...)
GNUNET_DISK_OpenFlags
Specifies how a file should be opened.
Open the file for both reading and writing.
int GNUNET_DISK_file_change_owner(const char *filename, const char *user)
Change owner of a file.
Definition: disk.c:1168
int GNUNET_CONFIGURATION_get_value_filename(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be the name of a file or directory.
Write-able memory map.
void GNUNET_DISK_fix_permissions(const char *fn, int require_uid_match, int require_gid_match)
Update POSIX permissions mask of a file on disk.
Definition: disk.c:379
static char * mktemp_name(const char *t)
Create the name for a temporary file or directory from a template.
Definition: disk.c:343
int fd
File handle on Unix-like systems.
Fail if file already exists.
ssize_t GNUNET_DISK_file_read_non_blocking(const struct GNUNET_DISK_FileHandle *h, void *result, size_t len)
Read the contents of a binary file into a buffer.
Definition: disk.c:757
struct GNUNET_DISK_FileHandle * GNUNET_DISK_get_handle_from_native(FILE *fd)
Get a handle from a native streaming FD.
Definition: disk.c:1332
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:1203
GNUNET_DISK_PipeEnd
Enumeration identifying the two ends of a pipe.
Handle used to access files (and pipes).
Handle used to manage a pipe.
Definition: disk.c:68
int GNUNET_CONFIGURATION_parse_and_run(const char *filename, GNUNET_CONFIGURATION_Callback cb, void *cb_cls)
Parse a configuration file filename and run the function cb with the resulting configuration object...
#define GNUNET_malloc(size)
Wrapper around malloc.
ssize_t GNUNET_DISK_fn_read(const char *fn, void *result, size_t len)
Read the contents of a binary file into a buffer.
Definition: disk.c:794
void GNUNET_DISK_filename_canonicalize(char *fn)
Removes special characters as &#39;:&#39; from a filename.
Definition: disk.c:1139
Handle for a memory-mapping operation.
Definition: disk.c:1347
Internal DISK related helper functions.
#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...