GNUnet  0.19.4
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 
434 
442 static enum GNUNET_GenericReturnValue
443 file_test_internal (const char *fil, int amode)
444 {
445  struct stat filestat;
446  int ret;
447  char *rdir;
448 
449  rdir = GNUNET_STRINGS_filename_expand (fil);
450  if (rdir == NULL)
451  return GNUNET_SYSERR;
452 
453  ret = stat (rdir, &filestat);
454  if (0 != ret)
455  {
456  if (errno != ENOENT)
457  {
459  GNUNET_free (rdir);
460  return GNUNET_SYSERR;
461  }
462  GNUNET_free (rdir);
463  return GNUNET_NO;
464  }
465  if (! S_ISREG (filestat.st_mode))
466  {
467  GNUNET_free (rdir);
468  return GNUNET_NO;
469  }
470  if (access (rdir, amode) < 0)
471  {
472  LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_DEBUG, "access", rdir);
473  GNUNET_free (rdir);
474  return GNUNET_SYSERR;
475  }
476  GNUNET_free (rdir);
477  return GNUNET_YES;
478 }
479 
480 
482 GNUNET_DISK_file_test (const char *fil)
483 {
484  return file_test_internal (fil, F_OK);
485 }
486 
487 
489 GNUNET_DISK_file_test_read (const char *fil)
490 {
491  return file_test_internal (fil, R_OK);
492 }
493 
494 
496 GNUNET_DISK_directory_create (const char *dir)
497 {
498  char *rdir;
499  unsigned int len;
500  unsigned int pos;
501  unsigned int pos2;
502  int ret = GNUNET_OK;
503 
505  if (rdir == NULL)
506  {
507  GNUNET_break (0);
508  return GNUNET_SYSERR;
509  }
510 
511  len = strlen (rdir);
512 
513  pos = 1; /* skip heading '/' */
514 
515  /* Check which low level directories already exist */
516  pos2 = len;
517  rdir[len] = DIR_SEPARATOR;
518  while (pos <= pos2)
519  {
520  if (DIR_SEPARATOR == rdir[pos2])
521  {
522  rdir[pos2] = '\0';
524  if (GNUNET_NO == ret)
525  {
527  "Creating directory `%s' failed",
528  rdir);
529  GNUNET_free (rdir);
530  return GNUNET_SYSERR;
531  }
532  rdir[pos2] = DIR_SEPARATOR;
533  if (GNUNET_YES == ret)
534  {
535  pos2++;
536  break;
537  }
538  }
539  pos2--;
540  }
541  rdir[len] = '\0';
542  if (pos < pos2)
543  pos = pos2;
544  /* Start creating directories */
545  while (pos <= len)
546  {
547  if ((rdir[pos] == DIR_SEPARATOR) || (pos == len))
548  {
549  rdir[pos] = '\0';
551  if (GNUNET_NO == ret)
552  {
554  "Creating directory `%s' failed",
555  rdir);
556  GNUNET_free (rdir);
557  return GNUNET_SYSERR;
558  }
559  if (GNUNET_SYSERR == ret)
560  {
561  ret = mkdir (rdir,
562  S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH
563  | S_IXOTH); /* 755 */
564 
565  if ((ret != 0) && (errno != EEXIST))
566  {
568  GNUNET_free (rdir);
569  return GNUNET_SYSERR;
570  }
571  }
572  rdir[pos] = DIR_SEPARATOR;
573  }
574  pos++;
575  }
576  GNUNET_free (rdir);
577  return GNUNET_OK;
578 }
579 
580 
583 {
584  char *rdir;
585  size_t len;
586  int eno;
588 
590  if (NULL == rdir)
591  {
592  errno = EINVAL;
593  return GNUNET_SYSERR;
594  }
595  if (0 == access (rdir, W_OK))
596  {
597  GNUNET_free (rdir);
598  return GNUNET_OK;
599  }
600  len = strlen (rdir);
601  while ((len > 0) && (rdir[len] != DIR_SEPARATOR))
602  len--;
603  rdir[len] = '\0';
604  /* The empty path is invalid and in this case refers to / */
605  if (0 == len)
606  {
607  GNUNET_free (rdir);
608  rdir = GNUNET_strdup ("/");
609  }
611  if ( (GNUNET_OK == res) &&
612  (0 != access (rdir, W_OK)) )
613  res = GNUNET_NO;
614  eno = errno;
615  GNUNET_free (rdir);
616  errno = eno;
617  return res;
618 }
619 
620 
621 ssize_t
623  void *result,
624  size_t len)
625 {
626  if (NULL == h)
627  {
628  errno = EINVAL;
629  return GNUNET_SYSERR;
630  }
631  return read (h->fd, result, len);
632 }
633 
634 
635 ssize_t
637  void *result,
638  size_t len)
639 {
640  int flags;
641  ssize_t ret;
642 
643  if (NULL == h)
644  {
645  errno = EINVAL;
646  return GNUNET_SYSERR;
647  }
648  /* set to non-blocking, read, then set back */
649  flags = fcntl (h->fd, F_GETFL);
650  if (0 == (flags & O_NONBLOCK))
651  (void) fcntl (h->fd, F_SETFL, flags | O_NONBLOCK);
652  ret = read (h->fd, result, len);
653  if (0 == (flags & O_NONBLOCK))
654  {
655  int eno = errno;
656  (void) fcntl (h->fd, F_SETFL, flags);
657  errno = eno;
658  }
659  return ret;
660 }
661 
662 
663 ssize_t
664 GNUNET_DISK_fn_read (const char *fn,
665  void *result,
666  size_t len)
667 {
668  struct GNUNET_DISK_FileHandle *fh;
669  ssize_t ret;
670  int eno;
671 
675  if (NULL == fh)
676  return GNUNET_SYSERR;
678  eno = errno;
680  errno = eno;
681  return ret;
682 }
683 
684 
685 ssize_t
687  const void *buffer,
688  size_t n)
689 {
690  if (NULL == h)
691  {
692  errno = EINVAL;
693  return GNUNET_SYSERR;
694  }
695 
696  return write (h->fd, buffer, n);
697 }
698 
699 
700 ssize_t
702  const void *buffer,
703  size_t n)
704 {
705  int flags;
706  ssize_t ret;
707 
708  if (NULL == h)
709  {
710  errno = EINVAL;
711  return GNUNET_SYSERR;
712  }
713  /* set to blocking, write, then set back */
714  flags = fcntl (h->fd, F_GETFL);
715  if (0 != (flags & O_NONBLOCK))
716  (void) fcntl (h->fd, F_SETFL, flags - O_NONBLOCK);
717  ret = write (h->fd, buffer, n);
718  if (0 == (flags & O_NONBLOCK))
719  (void) fcntl (h->fd, F_SETFL, flags);
720  return ret;
721 }
722 
723 
725 GNUNET_DISK_fn_write (const char *fn,
726  const void *buf,
727  size_t buf_size,
729 {
730  char *tmpl;
731  int fd;
732 
733  if (GNUNET_OK !=
735  {
737  "mkstemp",
738  fn);
739  return GNUNET_SYSERR;
740  }
741  {
742  char *dname;
743 
744  dname = GNUNET_strdup (fn);
745  GNUNET_asprintf (&tmpl,
746  "%s/XXXXXX",
747  dirname (dname));
748  GNUNET_free (dname);
749  }
750  fd = mkstemp (tmpl);
751  if (-1 == fd)
752  {
754  "mkstemp",
755  tmpl);
756  GNUNET_free (tmpl);
757  return GNUNET_SYSERR;
758  }
759 
760  if (0 != fchmod (fd,
762  {
764  "chmod",
765  tmpl);
766  GNUNET_assert (0 == close (fd));
767  if (0 != unlink (tmpl))
769  "unlink",
770  tmpl);
771  GNUNET_free (tmpl);
772  return GNUNET_SYSERR;
773  }
774  if (buf_size !=
775  write (fd,
776  buf,
777  buf_size))
778  {
780  "write",
781  tmpl);
782  GNUNET_assert (0 == close (fd));
783  if (0 != unlink (tmpl))
785  "unlink",
786  tmpl);
787  GNUNET_free (tmpl);
788  return GNUNET_SYSERR;
789  }
790  GNUNET_assert (0 == close (fd));
791 
792  if (0 != link (tmpl,
793  fn))
794  {
795  if (0 != unlink (tmpl))
797  "unlink",
798  tmpl);
799  GNUNET_free (tmpl);
800  return GNUNET_NO;
801  }
802  if (0 != unlink (tmpl))
804  "unlink",
805  tmpl);
806  GNUNET_free (tmpl);
807  return GNUNET_OK;
808 
809 
810 }
811 
812 
813 int
815  GNUNET_FileNameCallback callback,
816  void *callback_cls)
817 {
818  DIR *dinfo;
819  struct dirent *finfo;
820  struct stat istat;
821  int count = 0;
823  char *name;
824  char *dname;
825  unsigned int name_len;
826  unsigned int n_size;
827 
828  GNUNET_assert (NULL != dir_name);
830  if (NULL == dname)
831  return GNUNET_SYSERR;
832  while ((strlen (dname) > 0) && (dname[strlen (dname) - 1] == DIR_SEPARATOR))
833  dname[strlen (dname) - 1] = '\0';
834  if (0 != stat (dname, &istat))
835  {
837  GNUNET_free (dname);
838  return GNUNET_SYSERR;
839  }
840  if (! S_ISDIR (istat.st_mode))
841  {
843  _ ("Expected `%s' to be a directory!\n"),
844  dir_name);
845  GNUNET_free (dname);
846  return GNUNET_SYSERR;
847  }
848  errno = 0;
849  dinfo = opendir (dname);
850  if ((EACCES == errno) || (NULL == dinfo))
851  {
852  LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "opendir", dname);
853  if (NULL != dinfo)
854  closedir (dinfo);
855  GNUNET_free (dname);
856  return GNUNET_SYSERR;
857  }
858  name_len = 256;
859  n_size = strlen (dname) + name_len + strlen (DIR_SEPARATOR_STR) + 1;
860  name = GNUNET_malloc (n_size);
861  while (NULL != (finfo = readdir (dinfo)))
862  {
863  if ((0 == strcmp (finfo->d_name, ".")) ||
864  (0 == strcmp (finfo->d_name, "..")))
865  continue;
866  if (NULL != callback)
867  {
868  if (name_len < strlen (finfo->d_name))
869  {
870  GNUNET_free (name);
871  name_len = strlen (finfo->d_name);
872  n_size = strlen (dname) + name_len + strlen (DIR_SEPARATOR_STR) + 1;
873  name = GNUNET_malloc (n_size);
874  }
875  /* dname can end in "/" only if dname == "/";
876  * if dname does not end in "/", we need to add
877  * a "/" (otherwise, we must not!) */
879  n_size,
880  "%s%s%s",
881  dname,
882  (0 == strcmp (dname, DIR_SEPARATOR_STR))
883  ? ""
885  finfo->d_name);
886  ret = callback (callback_cls, name);
887  if (GNUNET_OK != ret)
888  {
889  closedir (dinfo);
890  GNUNET_free (name);
891  GNUNET_free (dname);
892  if (GNUNET_NO == ret)
893  return count;
894  return GNUNET_SYSERR;
895  }
896  }
897  count++;
898  }
899  closedir (dinfo);
900  GNUNET_free (name);
901  GNUNET_free (dname);
902  return count;
903 }
904 
905 
915 static bool
916 glob_match (const char *pattern, const char *str)
917 {
918  /* Position in the input string */
919  const char *str_pos = str;
920  /* Position in the pattern */
921  const char *pat_pos = pattern;
922  /* Backtrack position in string */
923  const char *str_bt = NULL;
924  /* Backtrack position in pattern */
925  const char *pat_bt = NULL;
926 
927  for (;;)
928  {
929  if (*pat_pos == '*')
930  {
931  str_bt = str_pos;
932  pat_bt = pat_pos++;
933  }
934  else if (*pat_pos == *str_pos)
935  {
936  if ('\0' == *pat_pos)
937  return true;
938  str_pos++;
939  pat_pos++;
940  }
941  else
942  {
943  if (NULL == str_bt)
944  return false;
945  /* Backtrack to match one more
946  character as part of the asterisk. */
947  str_pos = str_bt + 1;
948  if ('\0' == *str_pos)
949  return false;
950  pat_pos = pat_bt;
951  }
952  }
953 }
954 
955 
957 {
958  const char *glob;
960  void *cls;
961 
965  int nres;
966 };
967 
977 static enum GNUNET_GenericReturnValue
978 glob_cb (void *cls,
979  const char *filename)
980 {
981  struct GlobClosure *gc = cls;
982  const char *fn;
983 
984  fn = strrchr (filename, DIR_SEPARATOR);
985  fn = (NULL == fn) ? filename : (fn + 1);
986 
988  "checking glob '%s' against '%s'\n",
989  gc->glob,
990  fn);
991 
992  if (glob_match (gc->glob, fn))
993  {
994  enum GNUNET_GenericReturnValue cbret;
995 
997  "found glob match '%s'\n",
998  filename);
999  gc->nres++;
1000  cbret = gc->cb (gc->cls, filename);
1001  if (GNUNET_OK != cbret)
1002  return cbret;
1003  }
1004  return GNUNET_OK;
1005 }
1006 
1007 
1008 int
1009 GNUNET_DISK_glob (const char *glob_pattern,
1010  GNUNET_FileNameCallback callback,
1011  void *callback_cls)
1012 {
1013  char *mypat = GNUNET_strdup (glob_pattern);
1014  char *sep;
1015  int ret;
1016 
1017  if ( (NULL != strrchr (glob_pattern, '+')) ||
1018  (NULL != strrchr (glob_pattern, '[')) ||
1019  (NULL != strrchr (glob_pattern, '+')) ||
1020  (NULL != strrchr (glob_pattern, '~')) )
1021  {
1023  "unsupported glob pattern: '%s'\n",
1024  glob_pattern);
1025  GNUNET_free (mypat);
1026  return -1;
1027  }
1028 
1029  sep = strrchr (mypat, DIR_SEPARATOR);
1030  if (NULL == sep)
1031  {
1032  GNUNET_free (mypat);
1033  return -1;
1034  }
1035 
1036  *sep = '\0';
1037 
1038  if (NULL != strchr (mypat, '*'))
1039  {
1040  GNUNET_free (mypat);
1041  GNUNET_break (0);
1043  "glob pattern may only contain '*' in the final path component\n");
1044  return -1;
1045  }
1046 
1047  {
1048  struct GlobClosure gc = {
1049  .glob = sep + 1,
1050  .cb = callback,
1051  .cls = callback_cls,
1052  .nres = 0,
1053  };
1055  "scanning directory '%s' for glob matches on '%s'\n",
1056  mypat,
1057  gc.glob);
1059  glob_cb,
1060  &gc
1061  );
1062  GNUNET_free (mypat);
1063  return (ret < 0) ? ret : gc.nres;
1064  }
1065 }
1066 
1067 
1076 static enum GNUNET_GenericReturnValue
1077 remove_helper (void *unused,
1078  const char *fn)
1079 {
1080  (void) unused;
1081  (void) GNUNET_DISK_directory_remove (fn);
1082  return GNUNET_OK;
1083 }
1084 
1085 
1088 {
1089  struct stat istat;
1090 
1091  if (NULL == filename)
1092  {
1093  GNUNET_break (0);
1094  return GNUNET_SYSERR;
1095  }
1096  if (0 != lstat (filename, &istat))
1097  return GNUNET_NO; /* file may not exist... */
1098  (void) chmod (filename,
1099  S_IWUSR | S_IRUSR | S_IXUSR);
1100  if (0 == unlink (filename))
1101  return GNUNET_OK;
1102  if ( (errno != EISDIR) &&
1103  /* EISDIR is not sufficient in all cases, e.g.
1104  * sticky /tmp directory may result in EPERM on BSD.
1105  * So we also explicitly check "isDirectory" */
1106  (GNUNET_YES !=
1108  GNUNET_YES)) )
1109  {
1111  return GNUNET_SYSERR;
1112  }
1113  if (GNUNET_SYSERR ==
1115  return GNUNET_SYSERR;
1116  if (0 != rmdir (filename))
1117  {
1119  return GNUNET_SYSERR;
1120  }
1121  return GNUNET_OK;
1122 }
1123 
1124 
1126 GNUNET_DISK_file_copy (const char *src,
1127  const char *dst)
1128 {
1129  char *buf;
1130  uint64_t pos;
1131  uint64_t size;
1132  size_t len;
1133  ssize_t sret;
1134  struct GNUNET_DISK_FileHandle *in;
1135  struct GNUNET_DISK_FileHandle *out;
1136 
1138  {
1140  return GNUNET_SYSERR;
1141  }
1142  pos = 0;
1143  in =
1145  if (! in)
1146  {
1148  return GNUNET_SYSERR;
1149  }
1150  out =
1151  GNUNET_DISK_file_open (dst,
1158  if (! out)
1159  {
1162  return GNUNET_SYSERR;
1163  }
1165  while (pos < size)
1166  {
1167  len = COPY_BLK_SIZE;
1168  if (len > size - pos)
1169  len = size - pos;
1170  sret = GNUNET_DISK_file_read (in, buf, len);
1171  if ((sret < 0) || (len != (size_t) sret))
1172  goto FAIL;
1173  sret = GNUNET_DISK_file_write (out, buf, len);
1174  if ((sret < 0) || (len != (size_t) sret))
1175  goto FAIL;
1176  pos += len;
1177  }
1178  GNUNET_free (buf);
1180  GNUNET_DISK_file_close (out);
1181  return GNUNET_OK;
1182  FAIL:
1183  GNUNET_free (buf);
1185  GNUNET_DISK_file_close (out);
1186  return GNUNET_SYSERR;
1187 }
1188 
1189 
1190 void
1192 {
1193  char *idx;
1194  char c;
1195 
1196  for (idx = fn; *idx; idx++)
1197  {
1198  c = *idx;
1199 
1200  if ((c == '/') || (c == '\\') || (c == ':') || (c == '*') || (c == '?') ||
1201  (c ==
1202  '"')
1203  ||
1204  (c == '<') || (c == '>') || (c == '|') )
1205  {
1206  *idx = '_';
1207  }
1208  }
1209 }
1210 
1211 
1214  const char *user)
1215 {
1216  struct passwd *pws;
1217 
1218  pws = getpwnam (user);
1219  if (NULL == pws)
1220  {
1222  _ ("Cannot obtain information about user `%s': %s\n"),
1223  user,
1224  strerror (errno));
1225  return GNUNET_SYSERR;
1226  }
1227  if (0 != chown (filename, pws->pw_uid, pws->pw_gid))
1228  {
1230  return GNUNET_SYSERR;
1231  }
1232  return GNUNET_OK;
1233 }
1234 
1235 
1236 struct GNUNET_DISK_FileHandle *
1237 GNUNET_DISK_file_open (const char *fn,
1238  enum GNUNET_DISK_OpenFlags flags,
1240 {
1241  char *expfn;
1242  struct GNUNET_DISK_FileHandle *ret;
1243 
1244  int oflags;
1245  int mode;
1246  int fd;
1247 
1248  expfn = GNUNET_STRINGS_filename_expand (fn);
1249  if (NULL == expfn)
1250  return NULL;
1251 
1252  mode = 0;
1254  oflags = O_RDWR; /* note: O_RDWR is NOT always O_RDONLY | O_WRONLY */
1255  else if (flags & GNUNET_DISK_OPEN_READ)
1256  oflags = O_RDONLY;
1257  else if (flags & GNUNET_DISK_OPEN_WRITE)
1258  oflags = O_WRONLY;
1259  else
1260  {
1261  GNUNET_break (0);
1262  GNUNET_free (expfn);
1263  return NULL;
1264  }
1265  if (flags & GNUNET_DISK_OPEN_FAILIFEXISTS)
1266  oflags |= (O_CREAT | O_EXCL);
1267  if (flags & GNUNET_DISK_OPEN_TRUNCATE)
1268  oflags |= O_TRUNC;
1269  if (flags & GNUNET_DISK_OPEN_APPEND)
1270  oflags |= O_APPEND;
1271  if (GNUNET_NO == GNUNET_DISK_file_test (fn))
1272  {
1273  if (flags & GNUNET_DISK_OPEN_CREATE)
1274  {
1276  oflags |= O_CREAT;
1277  mode = translate_unix_perms (perm);
1278  }
1279  }
1280 
1281  fd = open (expfn,
1282  oflags
1283 #if O_CLOEXEC
1284  | O_CLOEXEC
1285 #endif
1286  | O_LARGEFILE,
1287  mode);
1288  if (fd == -1)
1289  {
1290  if (0 == (flags & GNUNET_DISK_OPEN_FAILIFEXISTS))
1292  else
1293  LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_DEBUG, "open", expfn);
1294  GNUNET_free (expfn);
1295  return NULL;
1296  }
1297 
1299 
1300  ret->fd = fd;
1301 
1302  GNUNET_free (expfn);
1303  return ret;
1304 }
1305 
1306 
1309 {
1311 
1312  if (NULL == h)
1313  {
1314  errno = EINVAL;
1315  return GNUNET_SYSERR;
1316  }
1317 
1318  ret = GNUNET_OK;
1319  if (0 != close (h->fd))
1320  {
1322  ret = GNUNET_SYSERR;
1323  }
1324  GNUNET_free (h);
1325  return ret;
1326 }
1327 
1328 
1329 struct GNUNET_DISK_FileHandle *
1331 {
1332  struct GNUNET_DISK_FileHandle *fh;
1333 
1334  if ((((off_t) -1) == lseek (fno, 0, SEEK_CUR)) && (EBADF == errno))
1335  return NULL; /* invalid FD */
1336 
1338 
1339  fh->fd = fno;
1340 
1341  return fh;
1342 }
1343 
1344 
1345 struct GNUNET_DISK_FileHandle *
1347 {
1348  int fno;
1349 
1350  fno = fileno (fd);
1351  if (-1 == fno)
1352  return NULL;
1354 }
1355 
1356 
1361 {
1365  void *addr;
1366 
1370  size_t len;
1371 };
1372 
1373 
1374 #ifndef MAP_FAILED
1375 #define MAP_FAILED ((void *) -1)
1376 #endif
1377 
1378 
1379 void *
1381  struct GNUNET_DISK_MapHandle **m,
1382  enum GNUNET_DISK_MapType access,
1383  size_t len)
1384 {
1385  int prot;
1386 
1387  if (NULL == h)
1388  {
1389  errno = EINVAL;
1390  return NULL;
1391  }
1392  prot = 0;
1393  if (access & GNUNET_DISK_MAP_TYPE_READ)
1394  prot = PROT_READ;
1395  if (access & GNUNET_DISK_MAP_TYPE_WRITE)
1396  prot |= PROT_WRITE;
1397  *m = GNUNET_new (struct GNUNET_DISK_MapHandle);
1398  (*m)->addr = mmap (NULL, len, prot, MAP_SHARED, h->fd, 0);
1399  GNUNET_assert (NULL != (*m)->addr);
1400  if (MAP_FAILED == (*m)->addr)
1401  {
1402  GNUNET_free (*m);
1403  return NULL;
1404  }
1405  (*m)->len = len;
1406  return (*m)->addr;
1407 }
1408 
1409 
1412 {
1414 
1415  if (NULL == h)
1416  {
1417  errno = EINVAL;
1418  return GNUNET_SYSERR;
1419  }
1420  ret = munmap (h->addr, h->len) != -1 ? GNUNET_OK : GNUNET_SYSERR;
1421  GNUNET_free (h);
1422  return ret;
1423 }
1424 
1425 
1428 {
1429  if (h == NULL)
1430  {
1431  errno = EINVAL;
1432  return GNUNET_SYSERR;
1433  }
1434 
1435 #if ! defined(__linux__) || ! defined(GNU)
1436  return fsync (h->fd) == -1 ? GNUNET_SYSERR : GNUNET_OK;
1437 #else
1438  return fdatasync (h->fd) == -1 ? GNUNET_SYSERR : GNUNET_OK;
1439 #endif
1440 }
1441 
1442 
1443 struct GNUNET_DISK_PipeHandle *
1445 {
1446  int fd[2];
1447 
1448  if (-1 == pipe (fd))
1449  {
1450  int eno = errno;
1451 
1453  errno = eno;
1454  return NULL;
1455  }
1456  return GNUNET_DISK_pipe_from_fd (pf, fd);
1457 }
1458 
1459 
1460 struct GNUNET_DISK_PipeHandle *
1462  int fd[2])
1463 {
1464  struct GNUNET_DISK_PipeHandle *p;
1465  int ret = 0;
1466  int flags;
1467  int eno = 0; /* make gcc happy */
1468 
1469  p = GNUNET_new (struct GNUNET_DISK_PipeHandle);
1470  if (fd[0] >= 0)
1471  {
1472  p->fd[0] = GNUNET_new (struct GNUNET_DISK_FileHandle);
1473  p->fd[0]->fd = fd[0];
1474  if (0 == (GNUNET_DISK_PF_BLOCKING_READ & pf))
1475  {
1476  flags = fcntl (fd[0], F_GETFL);
1477  flags |= O_NONBLOCK;
1478  if (0 > fcntl (fd[0], F_SETFL, flags))
1479  {
1480  ret = -1;
1481  eno = errno;
1482  }
1483  }
1484  flags = fcntl (fd[0], F_GETFD);
1485  flags |= FD_CLOEXEC;
1486  if (0 > fcntl (fd[0], F_SETFD, flags))
1487  {
1488  ret = -1;
1489  eno = errno;
1490  }
1491  }
1492 
1493  if (fd[1] >= 0)
1494  {
1495  p->fd[1] = GNUNET_new (struct GNUNET_DISK_FileHandle);
1496  p->fd[1]->fd = fd[1];
1497  if (0 == (GNUNET_DISK_PF_BLOCKING_WRITE & pf))
1498  {
1499  flags = fcntl (fd[1], F_GETFL);
1500  flags |= O_NONBLOCK;
1501  if (0 > fcntl (fd[1], F_SETFL, flags))
1502  {
1503  ret = -1;
1504  eno = errno;
1505  }
1506  }
1507  flags = fcntl (fd[1], F_GETFD);
1508  flags |= FD_CLOEXEC;
1509  if (0 > fcntl (fd[1], F_SETFD, flags))
1510  {
1511  ret = -1;
1512  eno = errno;
1513  }
1514  }
1515  if (ret == -1)
1516  {
1517  errno = eno;
1519  if (p->fd[0]->fd >= 0)
1520  GNUNET_break (0 == close (p->fd[0]->fd));
1521  if (p->fd[1]->fd >= 0)
1522  GNUNET_break (0 == close (p->fd[1]->fd));
1523  GNUNET_free (p->fd[0]);
1524  GNUNET_free (p->fd[1]);
1525  GNUNET_free (p);
1526  errno = eno;
1527  return NULL;
1528  }
1529  return p;
1530 }
1531 
1532 
1535  enum GNUNET_DISK_PipeEnd end)
1536 {
1538 
1540  {
1541  if (p->fd[0])
1542  {
1543  ret = GNUNET_DISK_file_close (p->fd[0]);
1544  p->fd[0] = NULL;
1545  }
1546  }
1547  else if (end == GNUNET_DISK_PIPE_END_WRITE)
1548  {
1549  if (p->fd[1])
1550  {
1551  ret = GNUNET_DISK_file_close (p->fd[1]);
1552  p->fd[1] = NULL;
1553  }
1554  }
1555  return ret;
1556 }
1557 
1558 
1559 struct GNUNET_DISK_FileHandle *
1561  enum GNUNET_DISK_PipeEnd end)
1562 {
1563  struct GNUNET_DISK_FileHandle *ret = NULL;
1564 
1566  {
1567  if (p->fd[0])
1568  {
1569  ret = p->fd[0];
1570  p->fd[0] = NULL;
1571  }
1572  }
1573  else if (end == GNUNET_DISK_PIPE_END_WRITE)
1574  {
1575  if (p->fd[1])
1576  {
1577  ret = p->fd[1];
1578  p->fd[1] = NULL;
1579  }
1580  }
1581 
1582  return ret;
1583 }
1584 
1585 
1588 {
1590  enum GNUNET_GenericReturnValue read_end_close;
1591  enum GNUNET_GenericReturnValue write_end_close;
1592  int read_end_close_errno;
1593  int write_end_close_errno;
1594 
1596  read_end_close_errno = errno;
1598  write_end_close_errno = errno;
1599  GNUNET_free (p);
1600 
1601  if (GNUNET_OK != read_end_close)
1602  {
1603  errno = read_end_close_errno;
1604  ret = read_end_close;
1605  }
1606  else if (GNUNET_OK != write_end_close)
1607  {
1608  errno = write_end_close_errno;
1609  ret = write_end_close;
1610  }
1611 
1612  return ret;
1613 }
1614 
1615 
1616 const struct GNUNET_DISK_FileHandle *
1618  enum GNUNET_DISK_PipeEnd n)
1619 {
1620  switch (n)
1621  {
1624  return p->fd[n];
1625 
1626  default:
1627  GNUNET_break (0);
1628  return NULL;
1629  }
1630 }
1631 
1632 
1635  void *dst,
1636  size_t dst_len)
1637 {
1638  if (NULL == fh)
1639  return GNUNET_SYSERR;
1640  if (dst_len < sizeof(int))
1641  return GNUNET_SYSERR;
1642  *((int *) dst) = fh->fd;
1643  return GNUNET_OK;
1644 }
1645 
1646 
1654 static enum GNUNET_GenericReturnValue
1655 purge_cfg_dir (void *cls,
1656  const struct GNUNET_CONFIGURATION_Handle *cfg)
1657 {
1658  const char *option = cls;
1659  char *tmpname;
1660 
1661  if (GNUNET_OK !=
1662  GNUNET_CONFIGURATION_get_value_filename (cfg, "PATHS", option, &tmpname))
1663  {
1665  return GNUNET_NO;
1666  }
1668  {
1670  GNUNET_free (tmpname);
1671  return GNUNET_OK;
1672  }
1673  GNUNET_free (tmpname);
1674  return GNUNET_OK;
1675 }
1676 
1677 
1678 void
1680  const char *option)
1681 {
1684  &purge_cfg_dir,
1685  (void *) option));
1686 }
1687 
1688 
1689 /* 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:978
#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:443
#define S_ISLNK(m)
Definition: disk.c:60
#define MAP_FAILED
Definition: disk.c:1375
static bool glob_match(const char *pattern, const char *str)
Check for a simple wildcard match.
Definition: disk.c:916
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:1655
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:1634
#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:1077
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:1237
void GNUNET_DISK_filename_canonicalize(char *fn)
Removes special characters as ':' from a filename.
Definition: disk.c:1191
int GNUNET_DISK_glob(const char *glob_pattern, GNUNET_FileNameCallback callback, void *callback_cls)
Find all files matching a glob pattern.
Definition: disk.c:1009
enum GNUNET_GenericReturnValue GNUNET_DISK_file_change_owner(const char *filename, const char *user)
Change owner of a file.
Definition: disk.c:1213
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:482
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:1560
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:1346
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:686
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:636
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:1679
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:489
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:1587
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:725
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:1380
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:1461
enum GNUNET_GenericReturnValue GNUNET_DISK_file_copy(const char *src, const char *dst)
Copy a file.
Definition: disk.c:1126
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_remove(const char *filename)
Remove all files in a directory (rm -rf).
Definition: disk.c:1087
enum GNUNET_GenericReturnValue GNUNET_DISK_file_sync(const struct GNUNET_DISK_FileHandle *h)
Write file changes to disk.
Definition: disk.c:1427
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:1308
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:582
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:622
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:1617
struct GNUNET_DISK_FileHandle * GNUNET_DISK_get_handle_from_int_fd(int fno)
Get a handle from a native integer FD.
Definition: disk.c:1330
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:1534
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:701
enum GNUNET_GenericReturnValue GNUNET_DISK_file_unmap(struct GNUNET_DISK_MapHandle *h)
Unmap a file.
Definition: disk.c:1411
struct GNUNET_DISK_PipeHandle * GNUNET_DISK_pipe(enum GNUNET_DISK_PipeFlags pf)
Creates an interprocess channel.
Definition: disk.c:1444
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_create(const char *dir)
Implementation of "mkdir -p".
Definition: disk.c:496
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:664
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:814
@ 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:1361
void * addr
Address where the map is in memory.
Definition: disk.c:1365
size_t len
Number of bytes mapped.
Definition: disk.c:1370
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:959
void * cls
Definition: disk.c:960
int nres
Number of files that actually matched the glob pattern.
Definition: disk.c:965
const char * glob
Definition: disk.c:958