GNUnet  0.19.2
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  */
27 #include "platform.h"
28 #include "gnunet_util_lib.h"
29 
30 #define LOG(kind, ...) GNUNET_log_from (kind, "util-disk", __VA_ARGS__)
31 
32 #define LOG_STRERROR(kind, syscall) \
33  GNUNET_log_from_strerror (kind, "util-disk", syscall)
34 
35 #define LOG_STRERROR_FILE(kind, syscall, filename) \
36  GNUNET_log_from_strerror_file (kind, "util-disk", syscall, filename)
37 
41 #define COPY_BLK_SIZE 65536
42 
43 #include <sys/types.h>
44 #if HAVE_SYS_VFS_H
45 #include <sys/vfs.h>
46 #endif
47 #if HAVE_SYS_PARAM_H
48 #include <sys/param.h>
49 #endif
50 #if HAVE_SYS_MOUNT_H
51 #include <sys/mount.h>
52 #endif
53 #if HAVE_SYS_STATVFS_H
54 #include <sys/statvfs.h>
55 #endif
56 
57 #ifndef S_ISLNK
58 #define _IFMT 0170000 /* type of file */
59 #define _IFLNK 0120000 /* symbolic link */
60 #define S_ISLNK(m) (((m) & _IFMT) == _IFLNK)
61 #endif
62 
63 
68 {
74 };
75 
76 
82 {
86  uint64_t total;
87 
92 
97 };
98 
99 
107 static int
109 {
110  int mode;
111 
112  mode = 0;
113  if (perm & GNUNET_DISK_PERM_USER_READ)
114  mode |= S_IRUSR;
115  if (perm & GNUNET_DISK_PERM_USER_WRITE)
116  mode |= S_IWUSR;
117  if (perm & GNUNET_DISK_PERM_USER_EXEC)
118  mode |= S_IXUSR;
119  if (perm & GNUNET_DISK_PERM_GROUP_READ)
120  mode |= S_IRGRP;
121  if (perm & GNUNET_DISK_PERM_GROUP_WRITE)
122  mode |= S_IWGRP;
123  if (perm & GNUNET_DISK_PERM_GROUP_EXEC)
124  mode |= S_IXGRP;
125  if (perm & GNUNET_DISK_PERM_OTHER_READ)
126  mode |= S_IROTH;
127  if (perm & GNUNET_DISK_PERM_OTHER_WRITE)
128  mode |= S_IWOTH;
129  if (perm & GNUNET_DISK_PERM_OTHER_EXEC)
130  mode |= S_IXOTH;
131 
132  return mode;
133 }
134 
135 
144 static enum GNUNET_GenericReturnValue
145 get_size_rec (void *cls, const char *fn)
146 {
147  struct GetFileSizeData *gfsd = cls;
148 
149 #if defined(HAVE_STAT64) && \
150  ! (defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64)
151  struct stat64 buf;
152 
153  if (0 != stat64 (fn, &buf))
154  {
156  return GNUNET_SYSERR;
157  }
158 #else
159  struct stat buf;
160 
161  if (0 != stat (fn, &buf))
162  {
164  return GNUNET_SYSERR;
165  }
166 #endif
167  if ((S_ISDIR (buf.st_mode)) && (gfsd->single_file_mode == GNUNET_YES))
168  {
169  errno = EISDIR;
170  return GNUNET_SYSERR;
171  }
172  if ((! S_ISLNK (buf.st_mode)) || (gfsd->include_sym_links == GNUNET_YES))
173  gfsd->total += buf.st_size;
174  if ((S_ISDIR (buf.st_mode)) && (0 == access (fn, X_OK)) &&
175  ((! S_ISLNK (buf.st_mode)) || (gfsd->include_sym_links == GNUNET_YES)))
176  {
178  return GNUNET_SYSERR;
179  }
180  return GNUNET_OK;
181 }
182 
183 
186 {
187  return ((! h) || (h->fd == -1)) ? GNUNET_YES : GNUNET_NO;
188 }
189 
190 
193  off_t *size)
194 {
195  struct stat sbuf;
196 
197  if (0 != fstat (fh->fd, &sbuf))
198  return GNUNET_SYSERR;
199  *size = sbuf.st_size;
200  return GNUNET_OK;
201 }
202 
203 
204 off_t
206  off_t offset,
207  enum GNUNET_DISK_Seek whence)
208 {
209  static int t[] = { SEEK_SET, SEEK_CUR, SEEK_END };
210 
211  if (h == NULL)
212  {
213  errno = EINVAL;
214  return GNUNET_SYSERR;
215  }
216  return lseek (h->fd, offset, t[whence]);
217 }
218 
219 
221 GNUNET_DISK_file_size (const char *filename,
222  uint64_t *size,
223  int include_symbolic_links,
224  int single_file_mode)
225 {
226  struct GetFileSizeData gfsd;
228 
229  GNUNET_assert (size != NULL);
230  gfsd.total = 0;
231  gfsd.include_sym_links = include_symbolic_links;
233  ret = get_size_rec (&gfsd, filename);
234  *size = gfsd.total;
235  return ret;
236 }
237 
238 
241  uint64_t *dev,
242  uint64_t *ino)
243 {
244 #if HAVE_STAT
245  {
246  struct stat sbuf;
247 
248  if (0 != stat (filename, &sbuf))
249  {
250  return GNUNET_SYSERR;
251  }
252  *ino = (uint64_t) sbuf.st_ino;
253  }
254 #else
255  *ino = 0;
256 #endif
257 #if HAVE_STATVFS
258  {
259  struct statvfs fbuf;
260 
261  if (0 != statvfs (filename, &fbuf))
262  {
263  return GNUNET_SYSERR;
264  }
265  *dev = (uint64_t) fbuf.f_fsid;
266  }
267 #elif HAVE_STATFS
268  {
269  struct statfs fbuf;
270 
271  if (0 != statfs (filename, &fbuf))
272  {
273  return GNUNET_SYSERR;
274  }
275  *dev =
276  ((uint64_t) fbuf.f_fsid.val[0]) << 32 || ((uint64_t) fbuf.f_fsid.val[1]);
277  }
278 #else
279  *dev = 0;
280 #endif
281  return GNUNET_OK;
282 }
283 
284 
291 static char *
292 mktemp_name (const char *t)
293 {
294  const char *tmpdir;
295  char *tmpl;
296  char *fn;
297 
298  if ((t[0] != '/') && (t[0] != '\\'))
299  {
300  /* FIXME: This uses system codepage on W32, not UTF-8 */
301  tmpdir = getenv ("TMPDIR");
302  if (NULL == tmpdir)
303  tmpdir = getenv ("TMP");
304  if (NULL == tmpdir)
305  tmpdir = getenv ("TEMP");
306  if (NULL == tmpdir)
307  tmpdir = "/tmp";
308  GNUNET_asprintf (&tmpl, "%s/%s%s", tmpdir, t, "XXXXXX");
309  }
310  else
311  {
312  GNUNET_asprintf (&tmpl, "%s%s", t, "XXXXXX");
313  }
314  fn = tmpl;
315  return fn;
316 }
317 
318 
319 void
321  int require_uid_match,
322  int require_gid_match)
323 {
324  mode_t mode;
325 
326  if (GNUNET_YES == require_uid_match)
327  mode = S_IRUSR | S_IWUSR | S_IXUSR;
328  else if (GNUNET_YES == require_gid_match)
329  mode = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP;
330  else
331  mode = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH
332  | S_IWOTH | S_IXOTH;
333  if (0 != chmod (fn, mode))
335 }
336 
337 
338 char *
339 GNUNET_DISK_mkdtemp (const char *t)
340 {
341  char *fn;
342  mode_t omask;
343 
344  omask = umask (S_IWGRP | S_IWOTH | S_IRGRP | S_IROTH);
345  fn = mktemp_name (t);
346  if (fn != mkdtemp (fn))
347  {
349  GNUNET_free (fn);
350  umask (omask);
351  return NULL;
352  }
353  umask (omask);
354  return fn;
355 }
356 
357 
358 void
359 GNUNET_DISK_file_backup (const char *fil)
360 {
361  size_t slen;
362  char *target;
363  unsigned int num;
364 
365  slen = strlen (fil) + 20;
366  target = GNUNET_malloc (slen);
367  num = 0;
368  do
369  {
370  GNUNET_snprintf (target, slen, "%s.%u~", fil, num++);
371  }
372  while (0 == access (target, F_OK));
373  if (0 != rename (fil, target))
375  GNUNET_free (target);
376 }
377 
378 
379 char *
380 GNUNET_DISK_mktemp (const char *t)
381 {
382  int fd;
383  char *fn;
384  mode_t omask;
385 
386  omask = umask (S_IWGRP | S_IWOTH | S_IRGRP | S_IROTH);
387  fn = mktemp_name (t);
388  if (-1 == (fd = mkstemp (fn)))
389  {
391  GNUNET_free (fn);
392  umask (omask);
393  return NULL;
394  }
395  umask (omask);
396  if (0 != close (fd))
398  return fn;
399 }
400 
401 
403 GNUNET_DISK_directory_test (const char *fil, int is_readable)
404 {
405  struct stat filestat;
406  int ret;
407 
408  ret = stat (fil, &filestat);
409  if (ret != 0)
410  {
411  if (errno != ENOENT)
413  return GNUNET_SYSERR;
414  }
415  if (! S_ISDIR (filestat.st_mode))
416  {
418  "A file already exits with the same name %s\n",
419  fil);
420  return GNUNET_NO;
421  }
422  if (GNUNET_YES == is_readable)
423  ret = access (fil, R_OK | X_OK);
424  else
425  ret = access (fil, X_OK);
426  if (ret < 0)
427  {
429  return GNUNET_NO;
430  }
431  return GNUNET_YES;
432 }
433 
441 static enum GNUNET_GenericReturnValue
442 file_test_internal (const char *fil, int amode)
443 {
444  struct stat filestat;
445  int ret;
446  char *rdir;
447 
448  rdir = GNUNET_STRINGS_filename_expand (fil);
449  if (rdir == NULL)
450  return GNUNET_SYSERR;
451 
452  ret = stat (rdir, &filestat);
453  if (0 != ret)
454  {
455  if (errno != ENOENT)
456  {
458  GNUNET_free (rdir);
459  return GNUNET_SYSERR;
460  }
461  GNUNET_free (rdir);
462  return GNUNET_NO;
463  }
464  if (! S_ISREG (filestat.st_mode))
465  {
466  GNUNET_free (rdir);
467  return GNUNET_NO;
468  }
469  if (access (rdir, amode) < 0)
470  {
471  LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_DEBUG, "access", rdir);
472  GNUNET_free (rdir);
473  return GNUNET_SYSERR;
474  }
475  GNUNET_free (rdir);
476  return GNUNET_YES;
477 }
478 
479 
481 GNUNET_DISK_file_test (const char *fil)
482 {
483  return file_test_internal (fil, F_OK);
484 }
485 
486 
488 GNUNET_DISK_file_test_read (const char *fil)
489 {
490  return file_test_internal (fil, R_OK);
491 }
492 
493 
495 GNUNET_DISK_directory_create (const char *dir)
496 {
497  char *rdir;
498  unsigned int len;
499  unsigned int pos;
500  unsigned int pos2;
501  int ret = GNUNET_OK;
502 
504  if (rdir == NULL)
505  {
506  GNUNET_break (0);
507  return GNUNET_SYSERR;
508  }
509 
510  len = strlen (rdir);
511 
512  pos = 1; /* skip heading '/' */
513 
514  /* Check which low level directories already exist */
515  pos2 = len;
516  rdir[len] = DIR_SEPARATOR;
517  while (pos <= pos2)
518  {
519  if (DIR_SEPARATOR == rdir[pos2])
520  {
521  rdir[pos2] = '\0';
523  if (GNUNET_NO == ret)
524  {
526  "Creating directory `%s' failed",
527  rdir);
528  GNUNET_free (rdir);
529  return GNUNET_SYSERR;
530  }
531  rdir[pos2] = DIR_SEPARATOR;
532  if (GNUNET_YES == ret)
533  {
534  pos2++;
535  break;
536  }
537  }
538  pos2--;
539  }
540  rdir[len] = '\0';
541  if (pos < pos2)
542  pos = pos2;
543  /* Start creating directories */
544  while (pos <= len)
545  {
546  if ((rdir[pos] == DIR_SEPARATOR) || (pos == len))
547  {
548  rdir[pos] = '\0';
550  if (GNUNET_NO == ret)
551  {
553  "Creating directory `%s' failed",
554  rdir);
555  GNUNET_free (rdir);
556  return GNUNET_SYSERR;
557  }
558  if (GNUNET_SYSERR == ret)
559  {
560  ret = mkdir (rdir,
561  S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH
562  | S_IXOTH); /* 755 */
563 
564  if ((ret != 0) && (errno != EEXIST))
565  {
567  GNUNET_free (rdir);
568  return GNUNET_SYSERR;
569  }
570  }
571  rdir[pos] = DIR_SEPARATOR;
572  }
573  pos++;
574  }
575  GNUNET_free (rdir);
576  return GNUNET_OK;
577 }
578 
579 
582 {
583  char *rdir;
584  size_t len;
585  int eno;
587 
589  if (NULL == rdir)
590  {
591  errno = EINVAL;
592  return GNUNET_SYSERR;
593  }
594  if (0 == access (rdir, W_OK))
595  {
596  GNUNET_free (rdir);
597  return GNUNET_OK;
598  }
599  len = strlen (rdir);
600  while ((len > 0) && (rdir[len] != DIR_SEPARATOR))
601  len--;
602  rdir[len] = '\0';
603  /* The empty path is invalid and in this case refers to / */
604  if (0 == len)
605  {
606  GNUNET_free (rdir);
607  rdir = GNUNET_strdup ("/");
608  }
610  if ( (GNUNET_OK == res) &&
611  (0 != access (rdir, W_OK)) )
612  res = GNUNET_NO;
613  eno = errno;
614  GNUNET_free (rdir);
615  errno = eno;
616  return res;
617 }
618 
619 
620 ssize_t
622  void *result,
623  size_t len)
624 {
625  if (NULL == h)
626  {
627  errno = EINVAL;
628  return GNUNET_SYSERR;
629  }
630  return read (h->fd, result, len);
631 }
632 
633 
634 ssize_t
636  void *result,
637  size_t len)
638 {
639  int flags;
640  ssize_t ret;
641 
642  if (NULL == h)
643  {
644  errno = EINVAL;
645  return GNUNET_SYSERR;
646  }
647  /* set to non-blocking, read, then set back */
648  flags = fcntl (h->fd, F_GETFL);
649  if (0 == (flags & O_NONBLOCK))
650  (void) fcntl (h->fd, F_SETFL, flags | O_NONBLOCK);
651  ret = read (h->fd, result, len);
652  if (0 == (flags & O_NONBLOCK))
653  {
654  int eno = errno;
655  (void) fcntl (h->fd, F_SETFL, flags);
656  errno = eno;
657  }
658  return ret;
659 }
660 
661 
662 ssize_t
663 GNUNET_DISK_fn_read (const char *fn,
664  void *result,
665  size_t len)
666 {
667  struct GNUNET_DISK_FileHandle *fh;
668  ssize_t ret;
669  int eno;
670 
674  if (NULL == fh)
675  return GNUNET_SYSERR;
677  eno = errno;
679  errno = eno;
680  return ret;
681 }
682 
683 
684 ssize_t
686  const void *buffer,
687  size_t n)
688 {
689  if (NULL == h)
690  {
691  errno = EINVAL;
692  return GNUNET_SYSERR;
693  }
694 
695  return write (h->fd, buffer, n);
696 }
697 
698 
699 ssize_t
701  const void *buffer,
702  size_t n)
703 {
704  int flags;
705  ssize_t ret;
706 
707  if (NULL == h)
708  {
709  errno = EINVAL;
710  return GNUNET_SYSERR;
711  }
712  /* set to blocking, write, then set back */
713  flags = fcntl (h->fd, F_GETFL);
714  if (0 != (flags & O_NONBLOCK))
715  (void) fcntl (h->fd, F_SETFL, flags - O_NONBLOCK);
716  ret = write (h->fd, buffer, n);
717  if (0 == (flags & O_NONBLOCK))
718  (void) fcntl (h->fd, F_SETFL, flags);
719  return ret;
720 }
721 
722 
724 GNUNET_DISK_fn_write (const char *fn,
725  const void *buf,
726  size_t buf_size,
728 {
729  char *tmpl;
730  int fd;
731 
732  if (GNUNET_OK !=
734  {
736  "mkstemp",
737  fn);
738  return GNUNET_SYSERR;
739  }
740  {
741  char *dname;
742 
743  dname = GNUNET_strdup (fn);
744  GNUNET_asprintf (&tmpl,
745  "%s/XXXXXX",
746  dirname (dname));
747  GNUNET_free (dname);
748  }
749  fd = mkstemp (tmpl);
750  if (-1 == fd)
751  {
753  "mkstemp",
754  tmpl);
755  GNUNET_free (tmpl);
756  return GNUNET_SYSERR;
757  }
758 
759  if (0 != fchmod (fd,
761  {
763  "chmod",
764  tmpl);
765  GNUNET_assert (0 == close (fd));
766  if (0 != unlink (tmpl))
768  "unlink",
769  tmpl);
770  GNUNET_free (tmpl);
771  return GNUNET_SYSERR;
772  }
773  if (buf_size !=
774  write (fd,
775  buf,
776  buf_size))
777  {
779  "write",
780  tmpl);
781  GNUNET_assert (0 == close (fd));
782  if (0 != unlink (tmpl))
784  "unlink",
785  tmpl);
786  GNUNET_free (tmpl);
787  return GNUNET_SYSERR;
788  }
789  GNUNET_assert (0 == close (fd));
790 
791  if (0 != link (tmpl,
792  fn))
793  {
794  if (0 != unlink (tmpl))
796  "unlink",
797  tmpl);
798  GNUNET_free (tmpl);
799  return GNUNET_NO;
800  }
801  if (0 != unlink (tmpl))
803  "unlink",
804  tmpl);
805  GNUNET_free (tmpl);
806  return GNUNET_OK;
807 
808 
809 }
810 
811 
812 int
814  GNUNET_FileNameCallback callback,
815  void *callback_cls)
816 {
817  DIR *dinfo;
818  struct dirent *finfo;
819  struct stat istat;
820  int count = 0;
822  char *name;
823  char *dname;
824  unsigned int name_len;
825  unsigned int n_size;
826 
827  GNUNET_assert (NULL != dir_name);
829  if (NULL == dname)
830  return GNUNET_SYSERR;
831  while ((strlen (dname) > 0) && (dname[strlen (dname) - 1] == DIR_SEPARATOR))
832  dname[strlen (dname) - 1] = '\0';
833  if (0 != stat (dname, &istat))
834  {
836  GNUNET_free (dname);
837  return GNUNET_SYSERR;
838  }
839  if (! S_ISDIR (istat.st_mode))
840  {
842  _ ("Expected `%s' to be a directory!\n"),
843  dir_name);
844  GNUNET_free (dname);
845  return GNUNET_SYSERR;
846  }
847  errno = 0;
848  dinfo = opendir (dname);
849  if ((EACCES == errno) || (NULL == dinfo))
850  {
851  LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "opendir", dname);
852  if (NULL != dinfo)
853  closedir (dinfo);
854  GNUNET_free (dname);
855  return GNUNET_SYSERR;
856  }
857  name_len = 256;
858  n_size = strlen (dname) + name_len + strlen (DIR_SEPARATOR_STR) + 1;
859  name = GNUNET_malloc (n_size);
860  while (NULL != (finfo = readdir (dinfo)))
861  {
862  if ((0 == strcmp (finfo->d_name, ".")) ||
863  (0 == strcmp (finfo->d_name, "..")))
864  continue;
865  if (NULL != callback)
866  {
867  if (name_len < strlen (finfo->d_name))
868  {
869  GNUNET_free (name);
870  name_len = strlen (finfo->d_name);
871  n_size = strlen (dname) + name_len + strlen (DIR_SEPARATOR_STR) + 1;
872  name = GNUNET_malloc (n_size);
873  }
874  /* dname can end in "/" only if dname == "/";
875  * if dname does not end in "/", we need to add
876  * a "/" (otherwise, we must not!) */
878  n_size,
879  "%s%s%s",
880  dname,
881  (0 == strcmp (dname, DIR_SEPARATOR_STR))
882  ? ""
884  finfo->d_name);
885  ret = callback (callback_cls, name);
886  if (GNUNET_OK != ret)
887  {
888  closedir (dinfo);
889  GNUNET_free (name);
890  GNUNET_free (dname);
891  if (GNUNET_NO == ret)
892  return count;
893  return GNUNET_SYSERR;
894  }
895  }
896  count++;
897  }
898  closedir (dinfo);
899  GNUNET_free (name);
900  GNUNET_free (dname);
901  return count;
902 }
903 
913 static bool
914 glob_match (const char *pattern, const char *str)
915 {
916  /* Position in the input string */
917  const char *str_pos = str;
918  /* Position in the pattern */
919  const char *pat_pos = pattern;
920  /* Backtrack position in string */
921  const char *str_bt = NULL;
922  /* Backtrack position in pattern */
923  const char *pat_bt = NULL;
924 
925  for (;;)
926  {
927  if (*pat_pos == '*')
928  {
929  str_bt = str_pos;
930  pat_bt = pat_pos++;
931  }
932  else if (*pat_pos == *str_pos)
933  {
934  if ('\0' == *pat_pos)
935  return true;
936  str_pos++;
937  pat_pos++;
938  }
939  else
940  {
941  if (NULL == str_bt)
942  return false;
943  /* Backtrack to match one more
944  character as part of the asterisk. */
945  str_pos = str_bt + 1;
946  if ('\0' == *str_pos)
947  return false;
948  pat_pos = pat_bt;
949  }
950  }
951 }
952 
954 {
955  const char *glob;
957  void *cls;
958 
962  int nres;
963 };
964 
974 static enum GNUNET_GenericReturnValue
975 glob_cb (void *cls,
976  const char *filename)
977 {
978  struct GlobClosure *gc = cls;
979  const char *fn;
980 
981  fn = strrchr (filename, DIR_SEPARATOR);
982  fn = (NULL == fn) ? filename : (fn + 1);
983 
985  "checking glob '%s' against '%s'\n",
986  gc->glob,
987  fn);
988 
989  if (glob_match (gc->glob, fn))
990  {
991  enum GNUNET_GenericReturnValue cbret;
992 
994  "found glob match '%s'\n",
995  filename);
996  gc->nres++;
997  cbret = gc->cb (gc->cls, filename);
998  if (GNUNET_OK != cbret)
999  return cbret;
1000  }
1001  return GNUNET_OK;
1002 }
1003 
1004 
1005 int
1006 GNUNET_DISK_glob (const char *glob_pattern,
1007  GNUNET_FileNameCallback callback,
1008  void *callback_cls)
1009 {
1010  char *mypat = GNUNET_strdup (glob_pattern);
1011  char *sep;
1012  int ret;
1013 
1014  if ( (NULL != strrchr (glob_pattern, '+')) ||
1015  (NULL != strrchr (glob_pattern, '[')) ||
1016  (NULL != strrchr (glob_pattern, '+')) ||
1017  (NULL != strrchr (glob_pattern, '~')) )
1018  {
1020  "unsupported glob pattern: '%s'\n",
1021  glob_pattern);
1022  GNUNET_free (mypat);
1023  return -1;
1024  }
1025 
1026  sep = strrchr (mypat, DIR_SEPARATOR);
1027  if (NULL == sep)
1028  {
1029  GNUNET_free (mypat);
1030  return -1;
1031  }
1032 
1033  *sep = '\0';
1034 
1035  if (NULL != strchr (mypat, '*'))
1036  {
1037  GNUNET_free (mypat);
1038  GNUNET_break (0);
1040  "glob pattern may only contain '*' in the final path component\n");
1041  return -1;
1042  }
1043 
1044  {
1045  struct GlobClosure gc = {
1046  .glob = sep + 1,
1047  .cb = callback,
1048  .cls = callback_cls,
1049  .nres = 0,
1050  };
1052  "scanning directory '%s' for glob matches on '%s'\n",
1053  mypat,
1054  gc.glob);
1056  glob_cb,
1057  &gc
1058  );
1059  GNUNET_free (mypat);
1060  return (ret < 0) ? ret : gc.nres;
1061  }
1062 }
1063 
1064 
1073 static enum GNUNET_GenericReturnValue
1074 remove_helper (void *unused,
1075  const char *fn)
1076 {
1077  (void) unused;
1078  (void) GNUNET_DISK_directory_remove (fn);
1079  return GNUNET_OK;
1080 }
1081 
1082 
1085 {
1086  struct stat istat;
1087 
1088  if (NULL == filename)
1089  {
1090  GNUNET_break (0);
1091  return GNUNET_SYSERR;
1092  }
1093  if (0 != lstat (filename, &istat))
1094  return GNUNET_NO; /* file may not exist... */
1095  (void) chmod (filename,
1096  S_IWUSR | S_IRUSR | S_IXUSR);
1097  if (0 == unlink (filename))
1098  return GNUNET_OK;
1099  if ( (errno != EISDIR) &&
1100  /* EISDIR is not sufficient in all cases, e.g.
1101  * sticky /tmp directory may result in EPERM on BSD.
1102  * So we also explicitly check "isDirectory" */
1103  (GNUNET_YES !=
1105  GNUNET_YES)) )
1106  {
1108  return GNUNET_SYSERR;
1109  }
1110  if (GNUNET_SYSERR ==
1112  return GNUNET_SYSERR;
1113  if (0 != rmdir (filename))
1114  {
1116  return GNUNET_SYSERR;
1117  }
1118  return GNUNET_OK;
1119 }
1120 
1121 
1123 GNUNET_DISK_file_copy (const char *src,
1124  const char *dst)
1125 {
1126  char *buf;
1127  uint64_t pos;
1128  uint64_t size;
1129  size_t len;
1130  ssize_t sret;
1131  struct GNUNET_DISK_FileHandle *in;
1132  struct GNUNET_DISK_FileHandle *out;
1133 
1135  {
1137  return GNUNET_SYSERR;
1138  }
1139  pos = 0;
1140  in =
1142  if (! in)
1143  {
1145  return GNUNET_SYSERR;
1146  }
1147  out =
1148  GNUNET_DISK_file_open (dst,
1155  if (! out)
1156  {
1159  return GNUNET_SYSERR;
1160  }
1162  while (pos < size)
1163  {
1164  len = COPY_BLK_SIZE;
1165  if (len > size - pos)
1166  len = size - pos;
1167  sret = GNUNET_DISK_file_read (in, buf, len);
1168  if ((sret < 0) || (len != (size_t) sret))
1169  goto FAIL;
1170  sret = GNUNET_DISK_file_write (out, buf, len);
1171  if ((sret < 0) || (len != (size_t) sret))
1172  goto FAIL;
1173  pos += len;
1174  }
1175  GNUNET_free (buf);
1177  GNUNET_DISK_file_close (out);
1178  return GNUNET_OK;
1179  FAIL:
1180  GNUNET_free (buf);
1182  GNUNET_DISK_file_close (out);
1183  return GNUNET_SYSERR;
1184 }
1185 
1186 
1187 void
1189 {
1190  char *idx;
1191  char c;
1192 
1193  for (idx = fn; *idx; idx++)
1194  {
1195  c = *idx;
1196 
1197  if ((c == '/') || (c == '\\') || (c == ':') || (c == '*') || (c == '?') ||
1198  (c ==
1199  '"')
1200  ||
1201  (c == '<') || (c == '>') || (c == '|') )
1202  {
1203  *idx = '_';
1204  }
1205  }
1206 }
1207 
1208 
1211  const char *user)
1212 {
1213  struct passwd *pws;
1214 
1215  pws = getpwnam (user);
1216  if (NULL == pws)
1217  {
1219  _ ("Cannot obtain information about user `%s': %s\n"),
1220  user,
1221  strerror (errno));
1222  return GNUNET_SYSERR;
1223  }
1224  if (0 != chown (filename, pws->pw_uid, pws->pw_gid))
1225  {
1227  return GNUNET_SYSERR;
1228  }
1229  return GNUNET_OK;
1230 }
1231 
1232 
1233 struct GNUNET_DISK_FileHandle *
1234 GNUNET_DISK_file_open (const char *fn,
1235  enum GNUNET_DISK_OpenFlags flags,
1237 {
1238  char *expfn;
1239  struct GNUNET_DISK_FileHandle *ret;
1240 
1241  int oflags;
1242  int mode;
1243  int fd;
1244 
1245  expfn = GNUNET_STRINGS_filename_expand (fn);
1246  if (NULL == expfn)
1247  return NULL;
1248 
1249  mode = 0;
1251  oflags = O_RDWR; /* note: O_RDWR is NOT always O_RDONLY | O_WRONLY */
1252  else if (flags & GNUNET_DISK_OPEN_READ)
1253  oflags = O_RDONLY;
1254  else if (flags & GNUNET_DISK_OPEN_WRITE)
1255  oflags = O_WRONLY;
1256  else
1257  {
1258  GNUNET_break (0);
1259  GNUNET_free (expfn);
1260  return NULL;
1261  }
1262  if (flags & GNUNET_DISK_OPEN_FAILIFEXISTS)
1263  oflags |= (O_CREAT | O_EXCL);
1264  if (flags & GNUNET_DISK_OPEN_TRUNCATE)
1265  oflags |= O_TRUNC;
1266  if (flags & GNUNET_DISK_OPEN_APPEND)
1267  oflags |= O_APPEND;
1268  if (GNUNET_NO == GNUNET_DISK_file_test (fn))
1269  {
1270  if (flags & GNUNET_DISK_OPEN_CREATE)
1271  {
1273  oflags |= O_CREAT;
1274  mode = translate_unix_perms (perm);
1275  }
1276  }
1277 
1278  fd = open (expfn,
1279  oflags
1280 #if O_CLOEXEC
1281  | O_CLOEXEC
1282 #endif
1283  | O_LARGEFILE,
1284  mode);
1285  if (fd == -1)
1286  {
1287  if (0 == (flags & GNUNET_DISK_OPEN_FAILIFEXISTS))
1289  else
1290  LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_DEBUG, "open", expfn);
1291  GNUNET_free (expfn);
1292  return NULL;
1293  }
1294 
1296 
1297  ret->fd = fd;
1298 
1299  GNUNET_free (expfn);
1300  return ret;
1301 }
1302 
1303 
1306 {
1308 
1309  if (NULL == h)
1310  {
1311  errno = EINVAL;
1312  return GNUNET_SYSERR;
1313  }
1314 
1315  ret = GNUNET_OK;
1316  if (0 != close (h->fd))
1317  {
1319  ret = GNUNET_SYSERR;
1320  }
1321  GNUNET_free (h);
1322  return ret;
1323 }
1324 
1325 
1326 struct GNUNET_DISK_FileHandle *
1328 {
1329  struct GNUNET_DISK_FileHandle *fh;
1330 
1331  if ((((off_t) -1) == lseek (fno, 0, SEEK_CUR)) && (EBADF == errno))
1332  return NULL; /* invalid FD */
1333 
1335 
1336  fh->fd = fno;
1337 
1338  return fh;
1339 }
1340 
1341 
1342 struct GNUNET_DISK_FileHandle *
1344 {
1345  int fno;
1346 
1347  fno = fileno (fd);
1348  if (-1 == fno)
1349  return NULL;
1351 }
1352 
1353 
1358 {
1362  void *addr;
1363 
1367  size_t len;
1368 };
1369 
1370 
1371 #ifndef MAP_FAILED
1372 #define MAP_FAILED ((void *) -1)
1373 #endif
1374 
1375 
1376 void *
1378  struct GNUNET_DISK_MapHandle **m,
1379  enum GNUNET_DISK_MapType access,
1380  size_t len)
1381 {
1382  int prot;
1383 
1384  if (NULL == h)
1385  {
1386  errno = EINVAL;
1387  return NULL;
1388  }
1389  prot = 0;
1390  if (access & GNUNET_DISK_MAP_TYPE_READ)
1391  prot = PROT_READ;
1392  if (access & GNUNET_DISK_MAP_TYPE_WRITE)
1393  prot |= PROT_WRITE;
1394  *m = GNUNET_new (struct GNUNET_DISK_MapHandle);
1395  (*m)->addr = mmap (NULL, len, prot, MAP_SHARED, h->fd, 0);
1396  GNUNET_assert (NULL != (*m)->addr);
1397  if (MAP_FAILED == (*m)->addr)
1398  {
1399  GNUNET_free (*m);
1400  return NULL;
1401  }
1402  (*m)->len = len;
1403  return (*m)->addr;
1404 }
1405 
1406 
1409 {
1411 
1412  if (NULL == h)
1413  {
1414  errno = EINVAL;
1415  return GNUNET_SYSERR;
1416  }
1417  ret = munmap (h->addr, h->len) != -1 ? GNUNET_OK : GNUNET_SYSERR;
1418  GNUNET_free (h);
1419  return ret;
1420 }
1421 
1422 
1425 {
1426  if (h == NULL)
1427  {
1428  errno = EINVAL;
1429  return GNUNET_SYSERR;
1430  }
1431 
1432 #if ! defined(__linux__) || ! defined(GNU)
1433  return fsync (h->fd) == -1 ? GNUNET_SYSERR : GNUNET_OK;
1434 #else
1435  return fdatasync (h->fd) == -1 ? GNUNET_SYSERR : GNUNET_OK;
1436 #endif
1437 }
1438 
1439 
1440 struct GNUNET_DISK_PipeHandle *
1442 {
1443  int fd[2];
1444 
1445  if (-1 == pipe (fd))
1446  {
1447  int eno = errno;
1448 
1450  errno = eno;
1451  return NULL;
1452  }
1453  return GNUNET_DISK_pipe_from_fd (pf, fd);
1454 }
1455 
1456 
1457 struct GNUNET_DISK_PipeHandle *
1459  int fd[2])
1460 {
1461  struct GNUNET_DISK_PipeHandle *p;
1462  int ret = 0;
1463  int flags;
1464  int eno = 0; /* make gcc happy */
1465 
1466  p = GNUNET_new (struct GNUNET_DISK_PipeHandle);
1467  if (fd[0] >= 0)
1468  {
1469  p->fd[0] = GNUNET_new (struct GNUNET_DISK_FileHandle);
1470  p->fd[0]->fd = fd[0];
1471  if (0 == (GNUNET_DISK_PF_BLOCKING_READ & pf))
1472  {
1473  flags = fcntl (fd[0], F_GETFL);
1474  flags |= O_NONBLOCK;
1475  if (0 > fcntl (fd[0], F_SETFL, flags))
1476  {
1477  ret = -1;
1478  eno = errno;
1479  }
1480  }
1481  flags = fcntl (fd[0], F_GETFD);
1482  flags |= FD_CLOEXEC;
1483  if (0 > fcntl (fd[0], F_SETFD, flags))
1484  {
1485  ret = -1;
1486  eno = errno;
1487  }
1488  }
1489 
1490  if (fd[1] >= 0)
1491  {
1492  p->fd[1] = GNUNET_new (struct GNUNET_DISK_FileHandle);
1493  p->fd[1]->fd = fd[1];
1494  if (0 == (GNUNET_DISK_PF_BLOCKING_WRITE & pf))
1495  {
1496  flags = fcntl (fd[1], F_GETFL);
1497  flags |= O_NONBLOCK;
1498  if (0 > fcntl (fd[1], F_SETFL, flags))
1499  {
1500  ret = -1;
1501  eno = errno;
1502  }
1503  }
1504  flags = fcntl (fd[1], F_GETFD);
1505  flags |= FD_CLOEXEC;
1506  if (0 > fcntl (fd[1], F_SETFD, flags))
1507  {
1508  ret = -1;
1509  eno = errno;
1510  }
1511  }
1512  if (ret == -1)
1513  {
1514  errno = eno;
1516  if (p->fd[0]->fd >= 0)
1517  GNUNET_break (0 == close (p->fd[0]->fd));
1518  if (p->fd[1]->fd >= 0)
1519  GNUNET_break (0 == close (p->fd[1]->fd));
1520  GNUNET_free (p->fd[0]);
1521  GNUNET_free (p->fd[1]);
1522  GNUNET_free (p);
1523  errno = eno;
1524  return NULL;
1525  }
1526  return p;
1527 }
1528 
1529 
1532  enum GNUNET_DISK_PipeEnd end)
1533 {
1535 
1537  {
1538  if (p->fd[0])
1539  {
1540  ret = GNUNET_DISK_file_close (p->fd[0]);
1541  p->fd[0] = NULL;
1542  }
1543  }
1544  else if (end == GNUNET_DISK_PIPE_END_WRITE)
1545  {
1546  if (p->fd[1])
1547  {
1548  ret = GNUNET_DISK_file_close (p->fd[1]);
1549  p->fd[1] = NULL;
1550  }
1551  }
1552  return ret;
1553 }
1554 
1555 
1556 struct GNUNET_DISK_FileHandle *
1558  enum GNUNET_DISK_PipeEnd end)
1559 {
1560  struct GNUNET_DISK_FileHandle *ret = NULL;
1561 
1563  {
1564  if (p->fd[0])
1565  {
1566  ret = p->fd[0];
1567  p->fd[0] = NULL;
1568  }
1569  }
1570  else if (end == GNUNET_DISK_PIPE_END_WRITE)
1571  {
1572  if (p->fd[1])
1573  {
1574  ret = p->fd[1];
1575  p->fd[1] = NULL;
1576  }
1577  }
1578 
1579  return ret;
1580 }
1581 
1582 
1585 {
1586  int ret = GNUNET_OK;
1587 
1588  int read_end_close;
1589  int write_end_close;
1590  int read_end_close_errno;
1591  int write_end_close_errno;
1592 
1594  read_end_close_errno = errno;
1596  write_end_close_errno = errno;
1597  GNUNET_free (p);
1598 
1599  if (GNUNET_OK != read_end_close)
1600  {
1601  errno = read_end_close_errno;
1602  ret = read_end_close;
1603  }
1604  else if (GNUNET_OK != write_end_close)
1605  {
1606  errno = write_end_close_errno;
1607  ret = write_end_close;
1608  }
1609 
1610  return ret;
1611 }
1612 
1613 
1614 const struct GNUNET_DISK_FileHandle *
1616  enum GNUNET_DISK_PipeEnd n)
1617 {
1618  switch (n)
1619  {
1622  return p->fd[n];
1623 
1624  default:
1625  GNUNET_break (0);
1626  return NULL;
1627  }
1628 }
1629 
1630 
1633  void *dst,
1634  size_t dst_len)
1635 {
1636  if (NULL == fh)
1637  return GNUNET_SYSERR;
1638  if (dst_len < sizeof(int))
1639  return GNUNET_SYSERR;
1640  *((int *) dst) = fh->fd;
1641  return GNUNET_OK;
1642 }
1643 
1644 
1652 static enum GNUNET_GenericReturnValue
1653 purge_cfg_dir (void *cls,
1654  const struct GNUNET_CONFIGURATION_Handle *cfg)
1655 {
1656  const char *option = cls;
1657  char *tmpname;
1658 
1659  if (GNUNET_OK !=
1660  GNUNET_CONFIGURATION_get_value_filename (cfg, "PATHS", option, &tmpname))
1661  {
1663  return GNUNET_NO;
1664  }
1666  {
1668  GNUNET_free (tmpname);
1669  return GNUNET_OK;
1670  }
1671  GNUNET_free (tmpname);
1672  return GNUNET_OK;
1673 }
1674 
1675 
1676 void
1678  const char *option)
1679 {
1682  &purge_cfg_dir,
1683  (void *) option));
1684 }
1685 
1686 
1687 /* end of disk.c */
static enum GNUNET_GenericReturnValue get_size_rec(void *cls, const char *fn)
Iterate over all files in the given directory and accumulate their size.
Definition: disk.c:145
#define COPY_BLK_SIZE
Block size for IO for copying files.
Definition: disk.c:41
static char * mktemp_name(const char *t)
Create the name for a temporary file or directory from a template.
Definition: disk.c:292
static enum GNUNET_GenericReturnValue glob_cb(void *cls, const char *filename)
Function called with a filename.
Definition: disk.c:975
#define LOG_STRERROR_FILE(kind, syscall, filename)
Definition: disk.c:35
static int translate_unix_perms(enum GNUNET_DISK_AccessPermissions perm)
Translate GNUnet-internal permission bitmap to UNIX file access permission bitmap.
Definition: disk.c:108
static enum GNUNET_GenericReturnValue file_test_internal(const char *fil, int amode)
Check if fil can be accessed using amode.
Definition: disk.c:442
#define S_ISLNK(m)
Definition: disk.c:60
#define MAP_FAILED
Definition: disk.c:1372
static bool glob_match(const char *pattern, const char *str)
Check for a simple wildcard match.
Definition: disk.c:914
static enum GNUNET_GenericReturnValue purge_cfg_dir(void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg)
Helper function for GNUNET_DISK_purge_cfg_dir.
Definition: disk.c:1653
enum GNUNET_GenericReturnValue GNUNET_DISK_internal_file_handle_(const struct GNUNET_DISK_FileHandle *fh, void *dst, size_t dst_len)
Retrieve OS file handle.
Definition: disk.c:1632
#define LOG(kind,...)
Definition: disk.c:30
#define LOG_STRERROR(kind, syscall)
Definition: disk.c:32
static enum GNUNET_GenericReturnValue remove_helper(void *unused, const char *fn)
Function that removes the given directory by calling GNUNET_DISK_directory_remove().
Definition: disk.c:1074
char * getenv()
static const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration we are using.
Definition: gnunet-abd.c:36
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
static struct GNUNET_ARM_MonitorHandle * m
Monitor connection with ARM.
Definition: gnunet-arm.c:104
static struct GNUNET_ARM_Handle * h
Connection with ARM.
Definition: gnunet-arm.c:99
static char * dir
Set to the directory where runtime files are stored.
Definition: gnunet-arm.c:89
static int end
Set if we are to shutdown all services (including ARM).
Definition: gnunet-arm.c:34
static int res
static const char * dir_name
Top-level directory we monitor to auto-publish.
static char * cfg_filename
Name of the configuration file.
static char * filename
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...
static int result
Global testing status.
static char buf[2048]
static struct GNUNET_DISK_FileHandle * fh
File handle to STDIN, for reading restart/quit commands.
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-uri.c:38
static struct GNUNET_SCHEDULER_Task * t
Main task.
static enum @8 mode
Should we do a PUT (mode = 0) or GET (mode = 1);.
@ FAIL
enum GNUNET_GenericReturnValue 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.
enum GNUNET_GenericReturnValue 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.
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:1234
void GNUNET_DISK_filename_canonicalize(char *fn)
Removes special characters as ':' from a filename.
Definition: disk.c:1188
int GNUNET_DISK_glob(const char *glob_pattern, GNUNET_FileNameCallback callback, void *callback_cls)
Find all files matching a glob pattern.
Definition: disk.c:1006
enum GNUNET_GenericReturnValue GNUNET_DISK_file_change_owner(const char *filename, const char *user)
Change owner of a file.
Definition: disk.c:1210
enum GNUNET_GenericReturnValue 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:481
enum GNUNET_GenericReturnValue 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:240
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:320
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:1557
char * GNUNET_DISK_mktemp(const char *t)
Create an (empty) temporary file on disk.
Definition: disk.c:380
struct GNUNET_DISK_FileHandle * GNUNET_DISK_get_handle_from_native(FILE *fd)
Get a handle from a native FD.
Definition: disk.c:1343
GNUNET_DISK_OpenFlags
Specifies how a file should be opened.
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:685
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:635
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:1677
GNUNET_DISK_PipeFlags
Flags for GNUNET_DISK_pipe().
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:205
enum GNUNET_GenericReturnValue GNUNET_DISK_file_test_read(const char *fil)
Check that fil corresponds to a filename and the file has read permissions.
Definition: disk.c:488
enum GNUNET_GenericReturnValue 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:221
GNUNET_DISK_AccessPermissions
File access permissions, UNIX-style.
enum GNUNET_GenericReturnValue GNUNET_DISK_pipe_close(struct GNUNET_DISK_PipeHandle *p)
Closes an interprocess channel.
Definition: disk.c:1584
enum GNUNET_GenericReturnValue GNUNET_DISK_fn_write(const char *fn, const void *buf, size_t buf_size, enum GNUNET_DISK_AccessPermissions mode)
Write a buffer to a file atomically.
Definition: disk.c:724
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:1377
struct GNUNET_DISK_PipeHandle * GNUNET_DISK_pipe_from_fd(enum GNUNET_DISK_PipeFlags pf, int fd[2])
Creates a pipe object from a couple of file descriptors.
Definition: disk.c:1458
enum GNUNET_GenericReturnValue GNUNET_DISK_file_copy(const char *src, const char *dst)
Copy a file.
Definition: disk.c:1123
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_remove(const char *filename)
Remove all files in a directory (rm -rf).
Definition: disk.c:1084
enum GNUNET_GenericReturnValue GNUNET_DISK_file_sync(const struct GNUNET_DISK_FileHandle *h)
Write file changes to disk.
Definition: disk.c:1424
GNUNET_DISK_Seek
Constants for specifying how to seek.
enum GNUNET_GenericReturnValue GNUNET_DISK_handle_invalid(const struct GNUNET_DISK_FileHandle *h)
Checks whether a handle is invalid.
Definition: disk.c:185
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_test(const char *fil, int is_readable)
Test if fil is a directory and listable.
Definition: disk.c:403
enum GNUNET_GenericReturnValue GNUNET_DISK_file_close(struct GNUNET_DISK_FileHandle *h)
Close an open file.
Definition: disk.c:1305
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:359
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_create_for_file(const char *filename)
Create the directory structure for storing a file.
Definition: disk.c:581
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:621
enum GNUNET_GenericReturnValue GNUNET_DISK_file_handle_size(struct GNUNET_DISK_FileHandle *fh, off_t *size)
Get the size of an open file.
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:1615
struct GNUNET_DISK_FileHandle * GNUNET_DISK_get_handle_from_int_fd(int fno)
Get a handle from a native integer FD.
Definition: disk.c:1327
enum GNUNET_GenericReturnValue GNUNET_DISK_pipe_close_end(struct GNUNET_DISK_PipeHandle *p, enum GNUNET_DISK_PipeEnd end)
Closes one half of an interprocess channel.
Definition: disk.c:1531
char * GNUNET_DISK_mkdtemp(const char *t)
Create an (empty) temporary directory on disk.
Definition: disk.c:339
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:700
enum GNUNET_GenericReturnValue GNUNET_DISK_file_unmap(struct GNUNET_DISK_MapHandle *h)
Unmap a file.
Definition: disk.c:1408
struct GNUNET_DISK_PipeHandle * GNUNET_DISK_pipe(enum GNUNET_DISK_PipeFlags pf)
Creates an interprocess channel.
Definition: disk.c:1441
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_create(const char *dir)
Implementation of "mkdir -p".
Definition: disk.c:495
GNUNET_DISK_PipeEnd
Enumeration identifying the two ends of a pipe.
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:663
GNUNET_DISK_MapType
Specifies what type of memory map is desired.
int GNUNET_DISK_directory_scan(const char *dir_name, GNUNET_FileNameCallback callback, void *callback_cls)
Scan a directory for files.
Definition: disk.c:813
@ GNUNET_DISK_OPEN_READ
Open the file for reading.
@ GNUNET_DISK_OPEN_FAILIFEXISTS
Fail if file already exists.
@ GNUNET_DISK_OPEN_WRITE
Open the file for writing.
@ GNUNET_DISK_OPEN_TRUNCATE
Truncate file if it exists.
@ GNUNET_DISK_OPEN_CREATE
Create file if it doesn't exist.
@ GNUNET_DISK_OPEN_APPEND
Append to the file.
@ GNUNET_DISK_OPEN_READWRITE
Open the file for both reading and writing.
@ GNUNET_DISK_PF_BLOCKING_WRITE
Configure write end to block when writing if set.
@ GNUNET_DISK_PF_BLOCKING_READ
Configure read end to block when reading if set.
@ GNUNET_DISK_PERM_OTHER_EXEC
Everybody can execute.
@ GNUNET_DISK_PERM_USER_EXEC
Owner can execute.
@ GNUNET_DISK_PERM_USER_READ
Owner can read.
@ GNUNET_DISK_PERM_NONE
Nobody is allowed to do anything to the file.
@ GNUNET_DISK_PERM_GROUP_READ
Group can read.
@ GNUNET_DISK_PERM_GROUP_EXEC
Group can execute.
@ GNUNET_DISK_PERM_GROUP_WRITE
Group can write.
@ GNUNET_DISK_PERM_USER_WRITE
Owner can write.
@ GNUNET_DISK_PERM_OTHER_READ
Everybody can read.
@ GNUNET_DISK_PERM_OTHER_WRITE
Everybody can write.
@ GNUNET_DISK_PIPE_END_WRITE
The writing-end of a pipe.
@ GNUNET_DISK_PIPE_END_READ
The reading-end of a pipe.
@ GNUNET_DISK_MAP_TYPE_WRITE
Write-able memory map.
@ GNUNET_DISK_MAP_TYPE_READ
Read-only memory map.
enum GNUNET_GenericReturnValue(* GNUNET_FileNameCallback)(void *cls, const char *filename)
Function called with a filename.
#define GNUNET_log(kind,...)
GNUNET_GenericReturnValue
Named constants for return values.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
void GNUNET_log_config_missing(enum GNUNET_ErrorType kind, const char *section, const char *option)
Log error message about missing configuration option.
#define GNUNET_log_strerror_file(level, cmd, filename)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
int GNUNET_snprintf(char *buf, size_t size, const char *format,...) __attribute__((format(printf
Like snprintf, just aborts if the buffer is of insufficient size.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
char * GNUNET_STRINGS_filename_expand(const char *fil)
Complete filename (a la shell) from abbrevition.
Definition: strings.c:494
static unsigned int size
Size of the "table".
Definition: peer.c:68
#define DIR_SEPARATOR
Definition: platform.h:164
#define O_LARGEFILE
Definition: platform.h:211
#define DIR_SEPARATOR_STR
Definition: platform.h:165
#define _(String)
GNU gettext support macro.
Definition: platform.h:177
const char * name
Handle used to access files (and pipes).
int fd
File handle on Unix-like systems.
Handle for a memory-mapping operation.
Definition: disk.c:1358
void * addr
Address where the map is in memory.
Definition: disk.c:1362
size_t len
Number of bytes mapped.
Definition: disk.c:1367
Handle used to manage a pipe.
Definition: disk.c:68
struct GNUNET_DISK_FileHandle * fd[2]
File descriptors for the pipe.
Definition: disk.c:73
Closure for the recursion to determine the file size of a directory.
Definition: disk.c:82
uint64_t total
Set to the total file size.
Definition: disk.c:86
int include_sym_links
GNUNET_YES if symbolic links should be included.
Definition: disk.c:91
int single_file_mode
GNUNET_YES if mode is file-only (return total == -1 for directories).
Definition: disk.c:96
GNUNET_FileNameCallback cb
Definition: disk.c:956
void * cls
Definition: disk.c:957
int nres
Number of files that actually matched the glob pattern.
Definition: disk.c:962
const char * glob
Definition: disk.c:955