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 enum GNUNET_GenericReturnValue
146 get_size_rec (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 
187 {
188  return ((! h) || (h->fd == -1)) ? GNUNET_YES : GNUNET_NO;
189 }
190 
191 
194  off_t *size)
195 {
196  struct stat sbuf;
197 
198  if (0 != fstat (fh->fd, &sbuf))
199  return GNUNET_SYSERR;
200  *size = sbuf.st_size;
201  return GNUNET_OK;
202 }
203 
204 
205 off_t
207  off_t offset,
208  enum GNUNET_DISK_Seek whence)
209 {
210  static int t[] = { SEEK_SET, SEEK_CUR, SEEK_END };
211 
212  if (h == NULL)
213  {
214  errno = EINVAL;
215  return GNUNET_SYSERR;
216  }
217  return lseek (h->fd, offset, t[whence]);
218 }
219 
220 
222 GNUNET_DISK_file_size (const char *filename,
223  uint64_t *size,
224  int include_symbolic_links,
225  int single_file_mode)
226 {
227  struct GetFileSizeData gfsd;
229 
230  GNUNET_assert (size != NULL);
231  gfsd.total = 0;
232  gfsd.include_sym_links = include_symbolic_links;
234  ret = get_size_rec (&gfsd, filename);
235  *size = gfsd.total;
236  return ret;
237 }
238 
239 
242  uint64_t *dev,
243  uint64_t *ino)
244 {
245 #if HAVE_STAT
246  {
247  struct stat sbuf;
248 
249  if (0 != stat (filename, &sbuf))
250  {
251  return GNUNET_SYSERR;
252  }
253  *ino = (uint64_t) sbuf.st_ino;
254  }
255 #else
256  *ino = 0;
257 #endif
258 #if HAVE_STATVFS
259  {
260  struct statvfs fbuf;
261 
262  if (0 != statvfs (filename, &fbuf))
263  {
264  return GNUNET_SYSERR;
265  }
266  *dev = (uint64_t) fbuf.f_fsid;
267  }
268 #elif HAVE_STATFS
269  {
270  struct statfs fbuf;
271 
272  if (0 != statfs (filename, &fbuf))
273  {
274  return GNUNET_SYSERR;
275  }
276  *dev =
277  ((uint64_t) fbuf.f_fsid.val[0]) << 32 || ((uint64_t) fbuf.f_fsid.val[1]);
278  }
279 #else
280  *dev = 0;
281 #endif
282  return GNUNET_OK;
283 }
284 
285 
292 static char *
293 mktemp_name (const char *t)
294 {
295  const char *tmpdir;
296  char *tmpl;
297  char *fn;
298 
299  if ((t[0] != '/') && (t[0] != '\\'))
300  {
301  /* FIXME: This uses system codepage on W32, not UTF-8 */
302  tmpdir = getenv ("TMPDIR");
303  if (NULL == tmpdir)
304  tmpdir = getenv ("TMP");
305  if (NULL == tmpdir)
306  tmpdir = getenv ("TEMP");
307  if (NULL == tmpdir)
308  tmpdir = "/tmp";
309  GNUNET_asprintf (&tmpl, "%s/%s%s", tmpdir, t, "XXXXXX");
310  }
311  else
312  {
313  GNUNET_asprintf (&tmpl, "%s%s", t, "XXXXXX");
314  }
315  fn = tmpl;
316  return fn;
317 }
318 
319 
320 void
322  int require_uid_match,
323  int require_gid_match)
324 {
325  mode_t mode;
326 
327  if (GNUNET_YES == require_uid_match)
328  mode = S_IRUSR | S_IWUSR | S_IXUSR;
329  else if (GNUNET_YES == require_gid_match)
330  mode = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP;
331  else
332  mode = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH
333  | S_IWOTH | S_IXOTH;
334  if (0 != chmod (fn, mode))
336 }
337 
338 
339 char *
340 GNUNET_DISK_mkdtemp (const char *t)
341 {
342  char *fn;
343  mode_t omask;
344 
345  omask = umask (S_IWGRP | S_IWOTH | S_IRGRP | S_IROTH);
346  fn = mktemp_name (t);
347  if (fn != mkdtemp (fn))
348  {
350  GNUNET_free (fn);
351  umask (omask);
352  return NULL;
353  }
354  umask (omask);
355  return fn;
356 }
357 
358 
359 void
360 GNUNET_DISK_file_backup (const char *fil)
361 {
362  size_t slen;
363  char *target;
364  unsigned int num;
365 
366  slen = strlen (fil) + 20;
367  target = GNUNET_malloc (slen);
368  num = 0;
369  do
370  {
371  GNUNET_snprintf (target, slen, "%s.%u~", fil, num++);
372  }
373  while (0 == access (target, F_OK));
374  if (0 != rename (fil, target))
376  GNUNET_free (target);
377 }
378 
379 
380 char *
381 GNUNET_DISK_mktemp (const char *t)
382 {
383  int fd;
384  char *fn;
385  mode_t omask;
386 
387  omask = umask (S_IWGRP | S_IWOTH | S_IRGRP | S_IROTH);
388  fn = mktemp_name (t);
389  if (-1 == (fd = mkstemp (fn)))
390  {
392  GNUNET_free (fn);
393  umask (omask);
394  return NULL;
395  }
396  umask (omask);
397  if (0 != close (fd))
399  return fn;
400 }
401 
402 
404 GNUNET_DISK_directory_test (const char *fil, int is_readable)
405 {
406  struct stat filestat;
407  int ret;
408 
409  ret = stat (fil, &filestat);
410  if (ret != 0)
411  {
412  if (errno != ENOENT)
414  return GNUNET_SYSERR;
415  }
416  if (! S_ISDIR (filestat.st_mode))
417  {
419  "A file already exits with the same name %s\n",
420  fil);
421  return GNUNET_NO;
422  }
423  if (GNUNET_YES == is_readable)
424  ret = access (fil, R_OK | X_OK);
425  else
426  ret = access (fil, X_OK);
427  if (ret < 0)
428  {
430  return GNUNET_NO;
431  }
432  return GNUNET_YES;
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 
914 static bool
915 glob_match (const char *pattern, const char *str)
916 {
917  /* Position in the input string */
918  const char *str_pos = str;
919  /* Position in the pattern */
920  const char *pat_pos = pattern;
921  /* Backtrack position in string */
922  const char *str_bt = NULL;
923  /* Backtrack position in pattern */
924  const char *pat_bt = NULL;
925 
926  for (;;)
927  {
928  if (*pat_pos == '*')
929  {
930  str_bt = str_pos;
931  pat_bt = pat_pos++;
932  }
933  else if (*pat_pos == *str_pos)
934  {
935  if ('\0' == *pat_pos)
936  return true;
937  str_pos++;
938  pat_pos++;
939  }
940  else
941  {
942  if (NULL == str_bt)
943  return false;
944  /* Backtrack to match one more
945  character as part of the asterisk. */
946  str_pos = str_bt + 1;
947  if ('\0' == *str_pos)
948  return false;
949  pat_pos = pat_bt;
950  }
951  }
952 }
953 
955 {
956  const char *glob;
958  void *cls;
959 
963  int nres;
964 };
965 
975 static enum GNUNET_GenericReturnValue
976 glob_cb (void *cls,
977  const char *filename)
978 {
979  struct GlobClosure *gc = cls;
980  const char *fn;
981 
982  fn = strrchr (filename, DIR_SEPARATOR);
983  fn = (NULL == fn) ? filename : (fn + 1);
984 
986  "checking glob '%s' against '%s'\n",
987  gc->glob,
988  fn);
989 
990  if (glob_match (gc->glob, fn))
991  {
992  enum GNUNET_GenericReturnValue cbret;
993 
995  "found glob match '%s'\n",
996  filename);
997  gc->nres++;
998  cbret = gc->cb (gc->cls, filename);
999  if (GNUNET_OK != cbret)
1000  return cbret;
1001  }
1002  return GNUNET_OK;
1003 }
1004 
1005 
1006 int
1007 GNUNET_DISK_glob (const char *glob_pattern,
1008  GNUNET_FileNameCallback callback,
1009  void *callback_cls)
1010 {
1011  char *mypat = GNUNET_strdup (glob_pattern);
1012  char *sep;
1013  int ret;
1014 
1015  if ( (NULL != strrchr (glob_pattern, '+')) ||
1016  (NULL != strrchr (glob_pattern, '[')) ||
1017  (NULL != strrchr (glob_pattern, '+')) ||
1018  (NULL != strrchr (glob_pattern, '~')) )
1019  {
1021  "unsupported glob pattern: '%s'\n",
1022  glob_pattern);
1023  GNUNET_free (mypat);
1024  return -1;
1025  }
1026 
1027  sep = strrchr (mypat, DIR_SEPARATOR);
1028  if (NULL == sep)
1029  {
1030  GNUNET_free (mypat);
1031  return -1;
1032  }
1033 
1034  *sep = '\0';
1035 
1036  if (NULL != strchr (mypat, '*'))
1037  {
1038  GNUNET_free (mypat);
1039  GNUNET_break (0);
1041  "glob pattern may only contain '*' in the final path component\n");
1042  return -1;
1043  }
1044 
1045  {
1046  struct GlobClosure gc = {
1047  .glob = sep + 1,
1048  .cb = callback,
1049  .cls = callback_cls,
1050  .nres = 0,
1051  };
1053  "scanning directory '%s' for glob matches on '%s'\n",
1054  mypat,
1055  gc.glob);
1057  glob_cb,
1058  &gc
1059  );
1060  GNUNET_free (mypat);
1061  return (ret < 0) ? ret : gc.nres;
1062  }
1063 }
1064 
1065 
1074 static enum GNUNET_GenericReturnValue
1075 remove_helper (void *unused,
1076  const char *fn)
1077 {
1078  (void) unused;
1079  (void) GNUNET_DISK_directory_remove (fn);
1080  return GNUNET_OK;
1081 }
1082 
1083 
1086 {
1087  struct stat istat;
1088 
1089  if (NULL == filename)
1090  {
1091  GNUNET_break (0);
1092  return GNUNET_SYSERR;
1093  }
1094  if (0 != lstat (filename, &istat))
1095  return GNUNET_NO; /* file may not exist... */
1096  (void) chmod (filename,
1097  S_IWUSR | S_IRUSR | S_IXUSR);
1098  if (0 == unlink (filename))
1099  return GNUNET_OK;
1100  if ( (errno != EISDIR) &&
1101  /* EISDIR is not sufficient in all cases, e.g.
1102  * sticky /tmp directory may result in EPERM on BSD.
1103  * So we also explicitly check "isDirectory" */
1104  (GNUNET_YES !=
1106  GNUNET_YES)) )
1107  {
1109  return GNUNET_SYSERR;
1110  }
1111  if (GNUNET_SYSERR ==
1113  return GNUNET_SYSERR;
1114  if (0 != rmdir (filename))
1115  {
1117  return GNUNET_SYSERR;
1118  }
1119  return GNUNET_OK;
1120 }
1121 
1122 
1124 GNUNET_DISK_file_copy (const char *src,
1125  const char *dst)
1126 {
1127  char *buf;
1128  uint64_t pos;
1129  uint64_t size;
1130  size_t len;
1131  ssize_t sret;
1132  struct GNUNET_DISK_FileHandle *in;
1133  struct GNUNET_DISK_FileHandle *out;
1134 
1136  {
1138  return GNUNET_SYSERR;
1139  }
1140  pos = 0;
1141  in =
1143  if (! in)
1144  {
1146  return GNUNET_SYSERR;
1147  }
1148  out =
1149  GNUNET_DISK_file_open (dst,
1156  if (! out)
1157  {
1160  return GNUNET_SYSERR;
1161  }
1163  while (pos < size)
1164  {
1165  len = COPY_BLK_SIZE;
1166  if (len > size - pos)
1167  len = size - pos;
1168  sret = GNUNET_DISK_file_read (in, buf, len);
1169  if ((sret < 0) || (len != (size_t) sret))
1170  goto FAIL;
1171  sret = GNUNET_DISK_file_write (out, buf, len);
1172  if ((sret < 0) || (len != (size_t) sret))
1173  goto FAIL;
1174  pos += len;
1175  }
1176  GNUNET_free (buf);
1178  GNUNET_DISK_file_close (out);
1179  return GNUNET_OK;
1180  FAIL:
1181  GNUNET_free (buf);
1183  GNUNET_DISK_file_close (out);
1184  return GNUNET_SYSERR;
1185 }
1186 
1187 
1188 void
1190 {
1191  char *idx;
1192  char c;
1193 
1194  for (idx = fn; *idx; idx++)
1195  {
1196  c = *idx;
1197 
1198  if ((c == '/') || (c == '\\') || (c == ':') || (c == '*') || (c == '?') ||
1199  (c ==
1200  '"')
1201  ||
1202  (c == '<') || (c == '>') || (c == '|') )
1203  {
1204  *idx = '_';
1205  }
1206  }
1207 }
1208 
1209 
1212  const char *user)
1213 {
1214  struct passwd *pws;
1215 
1216  pws = getpwnam (user);
1217  if (NULL == pws)
1218  {
1220  _ ("Cannot obtain information about user `%s': %s\n"),
1221  user,
1222  strerror (errno));
1223  return GNUNET_SYSERR;
1224  }
1225  if (0 != chown (filename, pws->pw_uid, pws->pw_gid))
1226  {
1228  return GNUNET_SYSERR;
1229  }
1230  return GNUNET_OK;
1231 }
1232 
1233 
1234 struct GNUNET_DISK_FileHandle *
1235 GNUNET_DISK_file_open (const char *fn,
1236  enum GNUNET_DISK_OpenFlags flags,
1238 {
1239  char *expfn;
1240  struct GNUNET_DISK_FileHandle *ret;
1241 
1242  int oflags;
1243  int mode;
1244  int fd;
1245 
1246  expfn = GNUNET_STRINGS_filename_expand (fn);
1247  if (NULL == expfn)
1248  return NULL;
1249 
1250  mode = 0;
1252  oflags = O_RDWR; /* note: O_RDWR is NOT always O_RDONLY | O_WRONLY */
1253  else if (flags & GNUNET_DISK_OPEN_READ)
1254  oflags = O_RDONLY;
1255  else if (flags & GNUNET_DISK_OPEN_WRITE)
1256  oflags = O_WRONLY;
1257  else
1258  {
1259  GNUNET_break (0);
1260  GNUNET_free (expfn);
1261  return NULL;
1262  }
1263  if (flags & GNUNET_DISK_OPEN_FAILIFEXISTS)
1264  oflags |= (O_CREAT | O_EXCL);
1265  if (flags & GNUNET_DISK_OPEN_TRUNCATE)
1266  oflags |= O_TRUNC;
1267  if (flags & GNUNET_DISK_OPEN_APPEND)
1268  oflags |= O_APPEND;
1269  if (GNUNET_NO == GNUNET_DISK_file_test (fn))
1270  {
1271  if (flags & GNUNET_DISK_OPEN_CREATE)
1272  {
1274  oflags |= O_CREAT;
1275  mode = translate_unix_perms (perm);
1276  }
1277  }
1278 
1279  fd = open (expfn,
1280  oflags
1281 #if O_CLOEXEC
1282  | O_CLOEXEC
1283 #endif
1284  | O_LARGEFILE,
1285  mode);
1286  if (fd == -1)
1287  {
1288  if (0 == (flags & GNUNET_DISK_OPEN_FAILIFEXISTS))
1290  else
1291  LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_DEBUG, "open", expfn);
1292  GNUNET_free (expfn);
1293  return NULL;
1294  }
1295 
1297 
1298  ret->fd = fd;
1299 
1300  GNUNET_free (expfn);
1301  return ret;
1302 }
1303 
1304 
1307 {
1309 
1310  if (NULL == h)
1311  {
1312  errno = EINVAL;
1313  return GNUNET_SYSERR;
1314  }
1315 
1316  ret = GNUNET_OK;
1317  if (0 != close (h->fd))
1318  {
1320  ret = GNUNET_SYSERR;
1321  }
1322  GNUNET_free (h);
1323  return ret;
1324 }
1325 
1326 
1327 struct GNUNET_DISK_FileHandle *
1329 {
1330  struct GNUNET_DISK_FileHandle *fh;
1331 
1332  if ((((off_t) -1) == lseek (fno, 0, SEEK_CUR)) && (EBADF == errno))
1333  return NULL; /* invalid FD */
1334 
1336 
1337  fh->fd = fno;
1338 
1339  return fh;
1340 }
1341 
1342 
1343 struct GNUNET_DISK_FileHandle *
1345 {
1346  int fno;
1347 
1348  fno = fileno (fd);
1349  if (-1 == fno)
1350  return NULL;
1352 }
1353 
1354 
1359 {
1363  void *addr;
1364 
1368  size_t len;
1369 };
1370 
1371 
1372 #ifndef MAP_FAILED
1373 #define MAP_FAILED ((void *) -1)
1374 #endif
1375 
1376 
1377 void *
1379  struct GNUNET_DISK_MapHandle **m,
1380  enum GNUNET_DISK_MapType access,
1381  size_t len)
1382 {
1383  int prot;
1384 
1385  if (NULL == h)
1386  {
1387  errno = EINVAL;
1388  return NULL;
1389  }
1390  prot = 0;
1391  if (access & GNUNET_DISK_MAP_TYPE_READ)
1392  prot = PROT_READ;
1393  if (access & GNUNET_DISK_MAP_TYPE_WRITE)
1394  prot |= PROT_WRITE;
1395  *m = GNUNET_new (struct GNUNET_DISK_MapHandle);
1396  (*m)->addr = mmap (NULL, len, prot, MAP_SHARED, h->fd, 0);
1397  GNUNET_assert (NULL != (*m)->addr);
1398  if (MAP_FAILED == (*m)->addr)
1399  {
1400  GNUNET_free (*m);
1401  return NULL;
1402  }
1403  (*m)->len = len;
1404  return (*m)->addr;
1405 }
1406 
1407 
1410 {
1412 
1413  if (NULL == h)
1414  {
1415  errno = EINVAL;
1416  return GNUNET_SYSERR;
1417  }
1418  ret = munmap (h->addr, h->len) != -1 ? GNUNET_OK : GNUNET_SYSERR;
1419  GNUNET_free (h);
1420  return ret;
1421 }
1422 
1423 
1426 {
1427  if (h == NULL)
1428  {
1429  errno = EINVAL;
1430  return GNUNET_SYSERR;
1431  }
1432 
1433 #if ! defined(__linux__) || ! defined(GNU)
1434  return fsync (h->fd) == -1 ? GNUNET_SYSERR : GNUNET_OK;
1435 #else
1436  return fdatasync (h->fd) == -1 ? GNUNET_SYSERR : GNUNET_OK;
1437 #endif
1438 }
1439 
1440 
1441 struct GNUNET_DISK_PipeHandle *
1443 {
1444  int fd[2];
1445 
1446  if (-1 == pipe (fd))
1447  {
1448  int eno = errno;
1449 
1451  errno = eno;
1452  return NULL;
1453  }
1454  return GNUNET_DISK_pipe_from_fd (pf, fd);
1455 }
1456 
1457 
1458 struct GNUNET_DISK_PipeHandle *
1460  int fd[2])
1461 {
1462  struct GNUNET_DISK_PipeHandle *p;
1463  int ret = 0;
1464  int flags;
1465  int eno = 0; /* make gcc happy */
1466 
1467  p = GNUNET_new (struct GNUNET_DISK_PipeHandle);
1468  if (fd[0] >= 0)
1469  {
1470  p->fd[0] = GNUNET_new (struct GNUNET_DISK_FileHandle);
1471  p->fd[0]->fd = fd[0];
1472  if (0 == (GNUNET_DISK_PF_BLOCKING_READ & pf))
1473  {
1474  flags = fcntl (fd[0], F_GETFL);
1475  flags |= O_NONBLOCK;
1476  if (0 > fcntl (fd[0], F_SETFL, flags))
1477  {
1478  ret = -1;
1479  eno = errno;
1480  }
1481  }
1482  flags = fcntl (fd[0], F_GETFD);
1483  flags |= FD_CLOEXEC;
1484  if (0 > fcntl (fd[0], F_SETFD, flags))
1485  {
1486  ret = -1;
1487  eno = errno;
1488  }
1489  }
1490 
1491  if (fd[1] >= 0)
1492  {
1493  p->fd[1] = GNUNET_new (struct GNUNET_DISK_FileHandle);
1494  p->fd[1]->fd = fd[1];
1495  if (0 == (GNUNET_DISK_PF_BLOCKING_WRITE & pf))
1496  {
1497  flags = fcntl (fd[1], F_GETFL);
1498  flags |= O_NONBLOCK;
1499  if (0 > fcntl (fd[1], F_SETFL, flags))
1500  {
1501  ret = -1;
1502  eno = errno;
1503  }
1504  }
1505  flags = fcntl (fd[1], F_GETFD);
1506  flags |= FD_CLOEXEC;
1507  if (0 > fcntl (fd[1], F_SETFD, flags))
1508  {
1509  ret = -1;
1510  eno = errno;
1511  }
1512  }
1513  if (ret == -1)
1514  {
1515  errno = eno;
1517  if (p->fd[0]->fd >= 0)
1518  GNUNET_break (0 == close (p->fd[0]->fd));
1519  if (p->fd[1]->fd >= 0)
1520  GNUNET_break (0 == close (p->fd[1]->fd));
1521  GNUNET_free (p->fd[0]);
1522  GNUNET_free (p->fd[1]);
1523  GNUNET_free (p);
1524  errno = eno;
1525  return NULL;
1526  }
1527  return p;
1528 }
1529 
1530 
1533  enum GNUNET_DISK_PipeEnd end)
1534 {
1536 
1538  {
1539  if (p->fd[0])
1540  {
1541  ret = GNUNET_DISK_file_close (p->fd[0]);
1542  p->fd[0] = NULL;
1543  }
1544  }
1545  else if (end == GNUNET_DISK_PIPE_END_WRITE)
1546  {
1547  if (p->fd[1])
1548  {
1549  ret = GNUNET_DISK_file_close (p->fd[1]);
1550  p->fd[1] = NULL;
1551  }
1552  }
1553  return ret;
1554 }
1555 
1556 
1557 struct GNUNET_DISK_FileHandle *
1559  enum GNUNET_DISK_PipeEnd end)
1560 {
1561  struct GNUNET_DISK_FileHandle *ret = NULL;
1562 
1564  {
1565  if (p->fd[0])
1566  {
1567  ret = p->fd[0];
1568  p->fd[0] = NULL;
1569  }
1570  }
1571  else if (end == GNUNET_DISK_PIPE_END_WRITE)
1572  {
1573  if (p->fd[1])
1574  {
1575  ret = p->fd[1];
1576  p->fd[1] = NULL;
1577  }
1578  }
1579 
1580  return ret;
1581 }
1582 
1583 
1586 {
1587  int ret = GNUNET_OK;
1588 
1589  int read_end_close;
1590  int write_end_close;
1591  int read_end_close_errno;
1592  int write_end_close_errno;
1593 
1595  read_end_close_errno = errno;
1597  write_end_close_errno = errno;
1598  GNUNET_free (p);
1599 
1600  if (GNUNET_OK != read_end_close)
1601  {
1602  errno = read_end_close_errno;
1603  ret = read_end_close;
1604  }
1605  else if (GNUNET_OK != write_end_close)
1606  {
1607  errno = write_end_close_errno;
1608  ret = write_end_close;
1609  }
1610 
1611  return ret;
1612 }
1613 
1614 
1615 const struct GNUNET_DISK_FileHandle *
1617  enum GNUNET_DISK_PipeEnd n)
1618 {
1619  switch (n)
1620  {
1623  return p->fd[n];
1624 
1625  default:
1626  GNUNET_break (0);
1627  return NULL;
1628  }
1629 }
1630 
1631 
1634  void *dst,
1635  size_t dst_len)
1636 {
1637  if (NULL == fh)
1638  return GNUNET_SYSERR;
1639  if (dst_len < sizeof(int))
1640  return GNUNET_SYSERR;
1641  *((int *) dst) = fh->fd;
1642  return GNUNET_OK;
1643 }
1644 
1645 
1653 static enum GNUNET_GenericReturnValue
1654 purge_cfg_dir (void *cls,
1655  const struct GNUNET_CONFIGURATION_Handle *cfg)
1656 {
1657  const char *option = cls;
1658  char *tmpname;
1659 
1660  if (GNUNET_OK !=
1661  GNUNET_CONFIGURATION_get_value_filename (cfg, "PATHS", option, &tmpname))
1662  {
1664  return GNUNET_NO;
1665  }
1667  {
1669  GNUNET_free (tmpname);
1670  return GNUNET_OK;
1671  }
1672  GNUNET_free (tmpname);
1673  return GNUNET_OK;
1674 }
1675 
1676 
1677 void
1679  const char *option)
1680 {
1683  &purge_cfg_dir,
1684  (void *) option));
1685 }
1686 
1687 
1688 /* 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:146
#define COPY_BLK_SIZE
Block size for IO for copying files.
Definition: disk.c:42
static char * mktemp_name(const char *t)
Create the name for a temporary file or directory from a template.
Definition: disk.c:293
static enum GNUNET_GenericReturnValue glob_cb(void *cls, const char *filename)
Function called with a filename.
Definition: disk.c:976
#define LOG_STRERROR_FILE(kind, syscall, filename)
Definition: disk.c:36
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
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:61
#define MAP_FAILED
Definition: disk.c:1373
static bool glob_match(const char *pattern, const char *str)
Check for a simple wildcard match.
Definition: disk.c:915
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:1654
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:1633
#define LOG(kind,...)
Definition: disk.c:31
#define LOG_STRERROR(kind, syscall)
Definition: disk.c:33
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:1075
Internal DISK related helper functions.
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 struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-qr.c:59
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_SCHEDULER_Task * t
Main task.
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.
Definition: gnunet_common.h:92
@ GNUNET_OK
Definition: gnunet_common.h:95
@ GNUNET_YES
Definition: gnunet_common.h:97
@ GNUNET_NO
Definition: gnunet_common.h:94
@ GNUNET_SYSERR
Definition: gnunet_common.h:93
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:1235
void GNUNET_DISK_filename_canonicalize(char *fn)
Removes special characters as ':' from a filename.
Definition: disk.c:1189
int GNUNET_DISK_glob(const char *glob_pattern, GNUNET_FileNameCallback callback, void *callback_cls)
Find all files matching a glob pattern.
Definition: disk.c:1007
enum GNUNET_GenericReturnValue GNUNET_DISK_file_change_owner(const char *filename, const char *user)
Change owner of a file.
Definition: disk.c:1211
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:241
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:321
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:1558
char * GNUNET_DISK_mktemp(const char *t)
Create an (empty) temporary file on disk.
Definition: disk.c:381
struct GNUNET_DISK_FileHandle * GNUNET_DISK_get_handle_from_native(FILE *fd)
Get a handle from a native FD.
Definition: disk.c:1344
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:1678
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:206
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:222
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:1585
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:1378
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:1459
enum GNUNET_GenericReturnValue GNUNET_DISK_file_copy(const char *src, const char *dst)
Copy a file.
Definition: disk.c:1124
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_remove(const char *filename)
Remove all files in a directory (rm -rf).
Definition: disk.c:1085
enum GNUNET_GenericReturnValue GNUNET_DISK_file_sync(const struct GNUNET_DISK_FileHandle *h)
Write file changes to disk.
Definition: disk.c:1425
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:186
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_test(const char *fil, int is_readable)
Test if fil is a directory and listable.
Definition: disk.c:404
enum GNUNET_GenericReturnValue GNUNET_DISK_file_close(struct GNUNET_DISK_FileHandle *h)
Close an open file.
Definition: disk.c:1306
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:360
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:193
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:1616
struct GNUNET_DISK_FileHandle * GNUNET_DISK_get_handle_from_int_fd(int fno)
Get a handle from a native integer FD.
Definition: disk.c:1328
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:1532
char * GNUNET_DISK_mkdtemp(const char *t)
Create an (empty) temporary directory on disk.
Definition: disk.c:340
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:1409
struct GNUNET_DISK_PipeHandle * GNUNET_DISK_pipe(enum GNUNET_DISK_PipeFlags pf)
Creates an interprocess channel.
Definition: disk.c:1442
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.
#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:482
static unsigned int size
Size of the "table".
Definition: peer.c:67
#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:1359
void * addr
Address where the map is in memory.
Definition: disk.c:1363
size_t len
Number of bytes mapped.
Definition: disk.c:1368
Handle used to manage a pipe.
Definition: disk.c:69
struct GNUNET_DISK_FileHandle * fd[2]
File descriptors for the pipe.
Definition: disk.c:74
Closure for the recursion to determine the file size of a directory.
Definition: disk.c:83
uint64_t total
Set to the total file size.
Definition: disk.c:87
int include_sym_links
GNUNET_YES if symbolic links should be included.
Definition: disk.c:92
int single_file_mode
GNUNET_YES if mode is file-only (return total == -1 for directories).
Definition: disk.c:97
GNUNET_FileNameCallback cb
Definition: disk.c:957
void * cls
Definition: disk.c:958
int nres
Number of files that actually matched the glob pattern.
Definition: disk.c:963
const char * glob
Definition: disk.c:956