GNUnet 0.24.1-15-gab6ed22f1
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#include "disk.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
108static int
110{
111 int mode;
112
113 mode = 0;
115 mode |= S_IRUSR;
117 mode |= S_IWUSR;
119 mode |= S_IXUSR;
121 mode |= S_IRGRP;
123 mode |= S_IWGRP;
125 mode |= S_IXGRP;
127 mode |= S_IROTH;
129 mode |= S_IWOTH;
131 mode |= S_IXOTH;
132
133 return mode;
134}
135
136
146get_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 != lstat64 (fn, &buf))
155 {
157 return GNUNET_SYSERR;
158 }
159#else
160 struct stat buf;
161
162 if (0 != lstat (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 {
178 if (GNUNET_SYSERR ==
181 gfsd))
182 return GNUNET_SYSERR;
183 }
184 return GNUNET_OK;
185}
186
187
190{
191 return ((! h) || (h->fd == -1)) ? GNUNET_YES : GNUNET_NO;
192}
193
194
197 off_t *size)
198{
199 struct stat sbuf;
200
201 if (0 != fstat (fh->fd, &sbuf))
202 return GNUNET_SYSERR;
203 *size = sbuf.st_size;
204 return GNUNET_OK;
205}
206
207
208off_t
210 off_t offset,
211 enum GNUNET_DISK_Seek whence)
212{
213 static int t[] = { SEEK_SET, SEEK_CUR, SEEK_END };
214
215 if (h == NULL)
216 {
217 errno = EINVAL;
218 return GNUNET_SYSERR;
219 }
220 return lseek (h->fd, offset, t[whence]);
221}
222
223
226 uint64_t *size,
227 int include_symbolic_links,
228 int single_file_mode)
229{
230 struct GetFileSizeData gfsd;
232
233 GNUNET_assert (size != NULL);
234 gfsd.total = 0;
235 gfsd.include_sym_links = include_symbolic_links;
237 ret = get_size_rec (&gfsd, filename);
238 *size = gfsd.total;
239 return ret;
240}
241
242
245 uint64_t *dev,
246 uint64_t *ino)
247{
248#if HAVE_STAT
249 {
250 struct stat sbuf;
251
252 if (0 != stat (filename, &sbuf))
253 {
254 return GNUNET_SYSERR;
255 }
256 *ino = (uint64_t) sbuf.st_ino;
257 }
258#else
259 *ino = 0;
260#endif
261#if HAVE_STATVFS
262 {
263 struct statvfs fbuf;
264
265 if (0 != statvfs (filename, &fbuf))
266 {
267 return GNUNET_SYSERR;
268 }
269 *dev = (uint64_t) fbuf.f_fsid;
270 }
271#elif HAVE_STATFS
272 {
273 struct statfs fbuf;
274
275 if (0 != statfs (filename, &fbuf))
276 {
277 return GNUNET_SYSERR;
278 }
279 *dev =
280 ((uint64_t) fbuf.f_fsid.val[0]) << 32 || ((uint64_t) fbuf.f_fsid.val[1]);
281 }
282#else
283 *dev = 0;
284#endif
285 return GNUNET_OK;
286}
287
288
295static char *
296mktemp_name (const char *t)
297{
298 const char *tmpdir;
299 char *tmpl;
300 char *fn;
301
302 if ((t[0] != '/') && (t[0] != '\\'))
303 {
304 /* FIXME: This uses system codepage on W32, not UTF-8 */
305 tmpdir = getenv ("TMPDIR");
306 if (NULL == tmpdir)
307 tmpdir = getenv ("TMP");
308 if (NULL == tmpdir)
309 tmpdir = getenv ("TEMP");
310 if (NULL == tmpdir)
311 tmpdir = "/tmp";
312 GNUNET_asprintf (&tmpl, "%s/%s%s", tmpdir, t, "XXXXXX");
313 }
314 else
315 {
316 GNUNET_asprintf (&tmpl, "%s%s", t, "XXXXXX");
317 }
318 fn = tmpl;
319 return fn;
320}
321
322
323void
325 int require_uid_match,
326 int require_gid_match)
327{
328 mode_t mode;
329
330 if (GNUNET_YES == require_uid_match)
331 mode = S_IRUSR | S_IWUSR | S_IXUSR;
332 else if (GNUNET_YES == require_gid_match)
333 mode = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP;
334 else
335 mode = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH
336 | S_IWOTH | S_IXOTH;
337 if (0 != chmod (fn, mode))
339}
340
341
342char *
344{
345 char *fn;
346 mode_t omask;
347
348 omask = umask (S_IWGRP | S_IWOTH | S_IRGRP | S_IROTH);
349 fn = mktemp_name (t);
350 if (fn != mkdtemp (fn))
351 {
353 GNUNET_free (fn);
354 umask (omask);
355 return NULL;
356 }
357 umask (omask);
358 return fn;
359}
360
361
362char *
363GNUNET_DISK_file_backup (const char *fil)
364{
365 size_t slen;
366 char *target;
367 unsigned int num;
368
369 slen = strlen (fil) + 20;
370 target = GNUNET_malloc (slen);
371 num = 0;
372
373#if HAVE_RENAMEAT2
374 {
375 int fd;
376
377 do
378 {
379 GNUNET_snprintf (target,
380 slen,
381 "%s.%u~",
382 fil,
383 num++);
384 fd = open (target,
385 O_CREAT | O_EXCL,
387 } while (-1 == fd);
388 if (0 != renameat2 (AT_FDCWD,
389 fil,
390 AT_FDCWD,
391 target,
392 RENAME_EXCHANGE))
393 {
395 "renameat2",
396 fil);
397 GNUNET_break (0 ==
398 close (fd));
399 return NULL;
400 }
401 GNUNET_break (0 ==
402 close (fd));
403 }
404#else
405 do
406 {
407 GNUNET_snprintf (target, slen, "%s.%u~", fil, num++);
408 }
409 while (0 == access (target, F_OK));
410 if (0 != rename (fil, target))
411 {
413 return NULL;
414 }
415#endif
416 return target;
417}
418
419
420char *
422{
423 int fd;
424 char *fn;
425 mode_t omask;
426
427 omask = umask (S_IWGRP | S_IWOTH | S_IRGRP | S_IROTH);
428 fn = mktemp_name (t);
429 if (-1 == (fd = mkstemp (fn)))
430 {
432 GNUNET_free (fn);
433 umask (omask);
434 return NULL;
435 }
436 umask (omask);
437 if (0 != close (fd))
439 return fn;
440}
441
442
444GNUNET_DISK_directory_test (const char *fil, int is_readable)
445{
446 struct stat filestat;
447 int ret;
448
449 ret = stat (fil, &filestat);
450 if (ret != 0)
451 {
452 if (errno != ENOENT)
454 return GNUNET_SYSERR;
455 }
456 if (! S_ISDIR (filestat.st_mode))
457 {
459 "A file already exits with the same name %s\n",
460 fil);
461 return GNUNET_NO;
462 }
463 if (GNUNET_YES == is_readable)
464 ret = access (fil, R_OK | X_OK);
465 else
466 ret = access (fil, X_OK);
467 if (ret < 0)
468 {
470 return GNUNET_NO;
471 }
472 return GNUNET_YES;
473}
474
475
484file_test_internal (const char *fil, int amode)
485{
486 struct stat filestat;
487 int ret;
488 char *rdir;
489
491 if (rdir == NULL)
492 return GNUNET_SYSERR;
493
494 ret = stat (rdir, &filestat);
495 if (0 != ret)
496 {
497 if (errno != ENOENT)
498 {
500 GNUNET_free (rdir);
501 return GNUNET_SYSERR;
502 }
503 GNUNET_free (rdir);
504 return GNUNET_NO;
505 }
506 if (! S_ISREG (filestat.st_mode))
507 {
508 GNUNET_free (rdir);
509 return GNUNET_NO;
510 }
511 if (access (rdir, amode) < 0)
512 {
514 GNUNET_free (rdir);
515 return GNUNET_SYSERR;
516 }
517 GNUNET_free (rdir);
518 return GNUNET_YES;
519}
520
521
523GNUNET_DISK_file_test (const char *fil)
524{
525 return file_test_internal (fil, F_OK);
526}
527
528
531{
532 return file_test_internal (fil, R_OK);
533}
534
535
538{
539 char *rdir;
540 unsigned int len;
541 unsigned int pos;
542 unsigned int pos2;
543 int ret = GNUNET_OK;
544
546 if (rdir == NULL)
547 {
548 GNUNET_break (0);
549 return GNUNET_SYSERR;
550 }
551
552 len = strlen (rdir);
553
554 pos = 1; /* skip heading '/' */
555
556 /* Check which low level directories already exist */
557 pos2 = len;
558 rdir[len] = DIR_SEPARATOR;
559 while (pos <= pos2)
560 {
561 if (DIR_SEPARATOR == rdir[pos2])
562 {
563 rdir[pos2] = '\0';
565 if (GNUNET_NO == ret)
566 {
568 "Creating directory `%s' failed\n",
569 rdir);
570 GNUNET_free (rdir);
571 return GNUNET_SYSERR;
572 }
573 rdir[pos2] = DIR_SEPARATOR;
574 if (GNUNET_YES == ret)
575 {
576 pos2++;
577 break;
578 }
579 }
580 pos2--;
581 }
582 rdir[len] = '\0';
583 if (pos < pos2)
584 pos = pos2;
585 /* Start creating directories */
586 while (pos <= len)
587 {
588 if ((rdir[pos] == DIR_SEPARATOR) || (pos == len))
589 {
590 rdir[pos] = '\0';
592 if (GNUNET_NO == ret)
593 {
595 "Creating directory `%s' failed\n",
596 rdir);
597 GNUNET_free (rdir);
598 return GNUNET_SYSERR;
599 }
600 if (GNUNET_SYSERR == ret)
601 {
602 ret = mkdir (rdir,
603 S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH
604 | S_IXOTH); /* 755 */
605
606 if ((ret != 0) && (errno != EEXIST))
607 {
609 GNUNET_free (rdir);
610 return GNUNET_SYSERR;
611 }
612 }
613 rdir[pos] = DIR_SEPARATOR;
614 }
615 pos++;
616 }
617 GNUNET_free (rdir);
618 return GNUNET_OK;
619}
620
621
624{
625 char *rdir;
626 size_t len;
627 int eno;
629
631 if (NULL == rdir)
632 {
633 errno = EINVAL;
634 return GNUNET_SYSERR;
635 }
636 if (0 == access (rdir, W_OK))
637 {
638 GNUNET_free (rdir);
639 return GNUNET_OK;
640 }
641 len = strlen (rdir);
642 while ((len > 0) && (rdir[len] != DIR_SEPARATOR))
643 len--;
644 rdir[len] = '\0';
645 /* The empty path is invalid and in this case refers to / */
646 if (0 == len)
647 {
648 GNUNET_free (rdir);
649 rdir = GNUNET_strdup ("/");
650 }
652 if ( (GNUNET_OK == res) &&
653 (0 != access (rdir, W_OK)) )
654 res = GNUNET_NO;
655 eno = errno;
656 GNUNET_free (rdir);
657 errno = eno;
658 return res;
659}
660
661
662ssize_t
664 void *result,
665 size_t len)
666{
667 if (NULL == h)
668 {
669 errno = EINVAL;
670 return GNUNET_SYSERR;
671 }
672 return read (h->fd, result, len);
673}
674
675
676ssize_t
677GNUNET_DISK_fn_read (const char *fn,
678 void *result,
679 size_t len)
680{
681 struct GNUNET_DISK_FileHandle *fh;
682 ssize_t ret;
683 int eno;
684
685 fh = GNUNET_DISK_file_open (fn,
688 if (NULL == fh)
689 return GNUNET_SYSERR;
690 ret = GNUNET_DISK_file_read (fh, result, len);
691 eno = errno;
694 errno = eno;
695 return ret;
696}
697
698
699ssize_t
701 const void *buffer,
702 size_t n)
703{
704 if (NULL == h)
705 {
706 errno = EINVAL;
707 return GNUNET_SYSERR;
708 }
709 return write (h->fd,
710 buffer,
711 n);
712}
713
714
715ssize_t
717 const void *buffer,
718 size_t n)
719{
720 int flags;
721 ssize_t ret;
722
723 if (NULL == h)
724 {
725 errno = EINVAL;
726 return GNUNET_SYSERR;
727 }
728 /* set to blocking, write, then set back */
729 flags = fcntl (h->fd, F_GETFL);
730 if (0 != (flags & O_NONBLOCK))
731 (void) fcntl (h->fd, F_SETFL, flags - O_NONBLOCK);
732 ret = write (h->fd, buffer, n);
733 if (0 == (flags & O_NONBLOCK))
734 (void) fcntl (h->fd, F_SETFL, flags);
735 return ret;
736}
737
738
740GNUNET_DISK_fn_write (const char *fn,
741 const void *buf,
742 size_t buf_size,
744{
745 char *tmpl;
746 int fd;
747
748 if (GNUNET_OK !=
750 {
752 "mkstemp",
753 fn);
754 return GNUNET_SYSERR;
755 }
756 {
757 char *dname;
758
759 dname = GNUNET_strdup (fn);
760 GNUNET_asprintf (&tmpl,
761 "%s/XXXXXX",
762 dirname (dname));
763 GNUNET_free (dname);
764 }
765 fd = mkstemp (tmpl);
766 if (-1 == fd)
767 {
769 "mkstemp",
770 tmpl);
771 GNUNET_free (tmpl);
772 return GNUNET_SYSERR;
773 }
774
775 if (0 != fchmod (fd,
777 {
779 "chmod",
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 if (buf_size !=
790 write (fd,
791 buf,
792 buf_size))
793 {
795 "write",
796 tmpl);
797 GNUNET_assert (0 == close (fd));
798 if (0 != unlink (tmpl))
800 "unlink",
801 tmpl);
802 GNUNET_free (tmpl);
803 return GNUNET_SYSERR;
804 }
805 GNUNET_assert (0 == close (fd));
806
807 if (0 != link (tmpl,
808 fn))
809 {
810 if (0 != unlink (tmpl))
812 "unlink",
813 tmpl);
814 GNUNET_free (tmpl);
815 return GNUNET_NO;
816 }
817 if (0 != unlink (tmpl))
819 "unlink",
820 tmpl);
821 GNUNET_free (tmpl);
822 return GNUNET_OK;
823
824
825}
826
827
828int
831 void *callback_cls)
832{
833 DIR *dinfo;
834 struct dirent *finfo;
835 int count = 0;
837 char *name;
838 char *dname;
839 unsigned int name_len;
840 unsigned int n_size;
841
842 GNUNET_assert (NULL != dir_name);
844 if (NULL == dname)
845 return GNUNET_SYSERR;
846 while ( (strlen (dname) > 0) &&
847 (dname[strlen (dname) - 1] == DIR_SEPARATOR) )
848 dname[strlen (dname) - 1] = '\0';
849 dinfo = opendir (dname);
850 if (NULL == dinfo)
851 {
853 "opendir",
854 dname);
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 {
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,
884 ? ""
886 finfo->d_name);
887 ret = callback (callback_cls,
888 name);
889 if (GNUNET_OK != ret)
890 {
891 closedir (dinfo);
893 GNUNET_free (dname);
894 if (GNUNET_NO == ret)
895 return count;
896 return GNUNET_SYSERR;
897 }
898 }
899 count++;
900 }
901 closedir (dinfo);
903 GNUNET_free (dname);
904 return count;
905}
906
907
917static bool
918glob_match (const char *pattern, const char *str)
919{
920 /* Position in the input string */
921 const char *str_pos = str;
922 /* Position in the pattern */
923 const char *pat_pos = pattern;
924 /* Backtrack position in string */
925 const char *str_bt = NULL;
926 /* Backtrack position in pattern */
927 const char *pat_bt = NULL;
928
929 for (;;)
930 {
931 if (*pat_pos == '*')
932 {
933 str_bt = str_pos;
934 pat_bt = pat_pos++;
935 }
936 else if (*pat_pos == *str_pos)
937 {
938 if ('\0' == *pat_pos)
939 return true;
940 str_pos++;
941 pat_pos++;
942 }
943 else
944 {
945 if (NULL == str_bt)
946 return false;
947 /* Backtrack to match one more
948 character as part of the asterisk. */
949 str_pos = str_bt + 1;
950 if ('\0' == *str_pos)
951 return false;
952 pat_pos = pat_bt;
953 }
954 }
955}
956
957
959{
960 const char *glob;
962 void *cls;
963
967 int nres;
968};
969
980glob_cb (void *cls,
981 const char *filename)
982{
983 struct GlobClosure *gc = cls;
984 const char *fn;
985
986 fn = strrchr (filename, DIR_SEPARATOR);
987 fn = (NULL == fn) ? filename : (fn + 1);
988
990 "checking glob '%s' against '%s'\n",
991 gc->glob,
992 fn);
993
994 if (glob_match (gc->glob, fn))
995 {
996 enum GNUNET_GenericReturnValue cbret;
997
999 "found glob match '%s'\n",
1000 filename);
1001 gc->nres++;
1002 cbret = gc->cb (gc->cls, filename);
1003 if (GNUNET_OK != cbret)
1004 return cbret;
1005 }
1006 return GNUNET_OK;
1007}
1008
1009
1010int
1011GNUNET_DISK_glob (const char *glob_pattern,
1012 GNUNET_FileNameCallback callback,
1013 void *callback_cls)
1014{
1015 char *mypat = GNUNET_strdup (glob_pattern);
1016 char *sep;
1017 int ret;
1018
1019 if ( (NULL != strrchr (glob_pattern, '+')) ||
1020 (NULL != strrchr (glob_pattern, '[')) ||
1021 (NULL != strrchr (glob_pattern, '~')) )
1022 {
1024 "unsupported glob pattern: '%s'\n",
1025 glob_pattern);
1026 GNUNET_free (mypat);
1027 return -1;
1028 }
1029
1030 sep = strrchr (mypat, DIR_SEPARATOR);
1031 if (NULL == sep)
1032 {
1033 GNUNET_free (mypat);
1034 return -1;
1035 }
1036
1037 *sep = '\0';
1038
1039 if (NULL != strchr (mypat, '*'))
1040 {
1041 GNUNET_free (mypat);
1042 GNUNET_break (0);
1044 "glob pattern may only contain '*' in the final path component\n");
1045 return -1;
1046 }
1047
1048 {
1049 struct GlobClosure gc = {
1050 .glob = sep + 1,
1051 .cb = callback,
1052 .cls = callback_cls,
1053 .nres = 0,
1054 };
1056 "scanning directory '%s' for glob matches on '%s'\n",
1057 mypat,
1058 gc.glob);
1060 glob_cb,
1061 &gc
1062 );
1063 GNUNET_free (mypat);
1064 return (ret < 0) ? ret : gc.nres;
1065 }
1066}
1067
1068
1077static enum GNUNET_GenericReturnValue
1078remove_helper (void *unused,
1079 const char *fn)
1080{
1081 (void) unused;
1082 (void) GNUNET_DISK_directory_remove (fn);
1083 return GNUNET_OK;
1084}
1085
1086
1089{
1090 struct stat istat;
1091
1092 if (NULL == filename)
1093 {
1094 GNUNET_break (0);
1095 return GNUNET_SYSERR;
1096 }
1097 if (0 != lstat (filename, &istat))
1098 return GNUNET_NO; /* file may not exist... */
1099 (void) chmod (filename,
1100 S_IWUSR | S_IRUSR | S_IXUSR);
1101 if (0 == unlink (filename))
1102 return GNUNET_OK;
1103 if ( (errno != EISDIR) &&
1104 /* EISDIR is not sufficient in all cases, e.g.
1105 * sticky /tmp directory may result in EPERM on BSD.
1106 * So we also explicitly check "isDirectory" */
1107 (GNUNET_YES !=
1109 GNUNET_YES)) )
1110 {
1112 "rmdir",
1113 filename);
1114 return GNUNET_SYSERR;
1115 }
1116 if (GNUNET_SYSERR ==
1119 NULL))
1120 return GNUNET_SYSERR;
1121 if (0 != rmdir (filename))
1122 {
1124 "rmdir",
1125 filename);
1126 return GNUNET_SYSERR;
1127 }
1128 return GNUNET_OK;
1129}
1130
1131
1133GNUNET_DISK_file_copy (const char *src,
1134 const char *dst)
1135{
1136 char *buf;
1137 uint64_t pos;
1138 uint64_t size;
1139 size_t len;
1140 ssize_t sret;
1141 struct GNUNET_DISK_FileHandle *in;
1142 struct GNUNET_DISK_FileHandle *out;
1143
1145 {
1147 return GNUNET_SYSERR;
1148 }
1149 pos = 0;
1150 in =
1152 if (! in)
1153 {
1155 return GNUNET_SYSERR;
1156 }
1157 out =
1165 if (! out)
1166 {
1169 return GNUNET_SYSERR;
1170 }
1172 while (pos < size)
1173 {
1174 len = COPY_BLK_SIZE;
1175 if (len > size - pos)
1176 len = size - pos;
1177 sret = GNUNET_DISK_file_read (in, buf, len);
1178 if ((sret < 0) || (len != (size_t) sret))
1179 goto FAIL;
1180 sret = GNUNET_DISK_file_write (out, buf, len);
1181 if ((sret < 0) || (len != (size_t) sret))
1182 goto FAIL;
1183 pos += len;
1184 }
1185 GNUNET_free (buf);
1190 return GNUNET_OK;
1191FAIL:
1192 GNUNET_free (buf);
1197 return GNUNET_SYSERR;
1198}
1199
1200
1201void
1203{
1204 char *idx;
1205 char c;
1206
1207 for (idx = fn; *idx; idx++)
1208 {
1209 c = *idx;
1210
1211 if ((c == '/') || (c == '\\') || (c == ':') || (c == '*') || (c == '?') ||
1212 (c ==
1213 '"')
1214 ||
1215 (c == '<') || (c == '>') || (c == '|') )
1216 {
1217 *idx = '_';
1218 }
1219 }
1220}
1221
1222
1225 const char *user)
1226{
1227 struct passwd *pws;
1228
1229 pws = getpwnam (user);
1230 if (NULL == pws)
1231 {
1233 _ ("Cannot obtain information about user `%s': %s\n"),
1234 user,
1235 strerror (errno));
1236 return GNUNET_SYSERR;
1237 }
1238 if (0 != chown (filename, pws->pw_uid, pws->pw_gid))
1239 {
1241 return GNUNET_SYSERR;
1242 }
1243 return GNUNET_OK;
1244}
1245
1246
1249 enum GNUNET_DISK_OpenFlags flags,
1251{
1252 char *expfn;
1254
1255 int oflags;
1256 int mode;
1257 int fd;
1258
1259 expfn = GNUNET_STRINGS_filename_expand (fn);
1260 if (NULL == expfn)
1261 return NULL;
1262
1263 mode = 0;
1265 oflags = O_RDWR; /* note: O_RDWR is NOT always O_RDONLY | O_WRONLY */
1266 else if (flags & GNUNET_DISK_OPEN_READ)
1267 oflags = O_RDONLY;
1268 else if (flags & GNUNET_DISK_OPEN_WRITE)
1269 oflags = O_WRONLY;
1270 else
1271 {
1272 GNUNET_break (0);
1273 GNUNET_free (expfn);
1274 return NULL;
1275 }
1277 oflags |= (O_CREAT | O_EXCL);
1278 if (flags & GNUNET_DISK_OPEN_TRUNCATE)
1279 oflags |= O_TRUNC;
1280 if (flags & GNUNET_DISK_OPEN_APPEND)
1281 oflags |= O_APPEND;
1282 if (GNUNET_NO == GNUNET_DISK_file_test (fn))
1283 {
1284 if (flags & GNUNET_DISK_OPEN_CREATE)
1285 {
1287 oflags |= O_CREAT;
1288 mode = translate_unix_perms (perm);
1289 }
1290 }
1291
1292 // Setting O_CLOEXEC after pipe() may introduce
1293 // race conditions: https://bugs.gnunet.org/view.php?id=9311
1294 // This is no problem if the platform supports pipe2
1295 fd = open (expfn,
1296 oflags
1297#if O_CLOEXEC
1298 | O_CLOEXEC
1299#endif
1300 | O_LARGEFILE,
1301 mode);
1302 if (fd == -1)
1303 {
1304 if (0 == (flags & GNUNET_DISK_OPEN_FAILIFEXISTS))
1306 else
1308 GNUNET_free (expfn);
1309 return NULL;
1310 }
1311
1313
1314 ret->fd = fd;
1315
1316 GNUNET_free (expfn);
1317 return ret;
1318}
1319
1320
1323{
1325
1326 if (NULL == h)
1327 {
1328 errno = EINVAL;
1329 return GNUNET_SYSERR;
1330 }
1331
1332 ret = GNUNET_OK;
1333 if (0 != close (h->fd))
1334 {
1337 }
1338 GNUNET_free (h);
1339 return ret;
1340}
1341
1342
1345{
1346 struct GNUNET_DISK_FileHandle *fh;
1347
1348 if ((((off_t) -1) == lseek (fno, 0, SEEK_CUR)) && (EBADF == errno))
1349 return NULL; /* invalid FD */
1350
1351 fh = GNUNET_new (struct GNUNET_DISK_FileHandle);
1352
1353 fh->fd = fno;
1354
1355 return fh;
1356}
1357
1358
1361{
1362 int fno;
1363
1364 fno = fileno (fd);
1365 if (-1 == fno)
1366 return NULL;
1368}
1369
1370
1375{
1379 void *addr;
1380
1384 size_t len;
1385};
1386
1387
1388#ifndef MAP_FAILED
1389#define MAP_FAILED ((void *) -1)
1390#endif
1391
1392
1393void *
1395 struct GNUNET_DISK_MapHandle **m,
1396 enum GNUNET_DISK_MapType access,
1397 size_t len)
1398{
1399 int prot;
1400
1401 if (NULL == h)
1402 {
1403 errno = EINVAL;
1404 return NULL;
1405 }
1406 prot = 0;
1407 if (access & GNUNET_DISK_MAP_TYPE_READ)
1408 prot = PROT_READ;
1409 if (access & GNUNET_DISK_MAP_TYPE_WRITE)
1410 prot |= PROT_WRITE;
1412 (*m)->addr = mmap (NULL, len, prot, MAP_SHARED, h->fd, 0);
1413 GNUNET_assert (NULL != (*m)->addr);
1414 if (MAP_FAILED == (*m)->addr)
1415 {
1416 GNUNET_free (*m);
1417 return NULL;
1418 }
1419 (*m)->len = len;
1420 return (*m)->addr;
1421}
1422
1423
1426{
1428
1429 if (NULL == h)
1430 {
1431 errno = EINVAL;
1432 return GNUNET_SYSERR;
1433 }
1434 ret = munmap (h->addr, h->len) != -1 ? GNUNET_OK : GNUNET_SYSERR;
1435 GNUNET_free (h);
1436 return ret;
1437}
1438
1439
1442{
1443 if (h == NULL)
1444 {
1445 errno = EINVAL;
1446 return GNUNET_SYSERR;
1447 }
1448
1449#if ! defined(__linux__) || ! defined(GNU)
1450 return fsync (h->fd) == -1 ? GNUNET_SYSERR : GNUNET_OK;
1451#else
1452 return fdatasync (h->fd) == -1 ? GNUNET_SYSERR : GNUNET_OK;
1453#endif
1454}
1455
1456
1459{
1460 int fd[2];
1461
1462#if HAVE_PIPE2 && O_CLOEXEC
1463 if (-1 == pipe2 (fd, O_CLOEXEC))
1464#else
1465 if (-1 == pipe (fd))
1466#endif
1467 {
1468 int eno = errno;
1469
1471 errno = eno;
1472 return NULL;
1473 }
1474 return GNUNET_DISK_pipe_from_fd (pf, fd);
1475}
1476
1477
1480 int fd[2])
1481{
1482 struct GNUNET_DISK_PipeHandle *p;
1483 int ret = 0;
1484 int flags;
1485 int eno = 0; /* make gcc happy */
1486
1488 if (fd[0] >= 0)
1489 {
1490 p->fd[0] = GNUNET_new (struct GNUNET_DISK_FileHandle);
1491 p->fd[0]->fd = fd[0];
1492 if (0 == (GNUNET_DISK_PF_BLOCKING_READ & pf))
1493 {
1494 flags = fcntl (fd[0], F_GETFL);
1495 flags |= O_NONBLOCK;
1496 if (0 > fcntl (fd[0], F_SETFL, flags))
1497 {
1498 ret = -1;
1499 eno = errno;
1500 }
1501 }
1502 flags = fcntl (fd[0], F_GETFD);
1503 flags |= FD_CLOEXEC;
1504 if (0 > fcntl (fd[0], F_SETFD, flags))
1505 {
1506 ret = -1;
1507 eno = errno;
1508 }
1509 }
1510
1511 if (fd[1] >= 0)
1512 {
1513 p->fd[1] = GNUNET_new (struct GNUNET_DISK_FileHandle);
1514 p->fd[1]->fd = fd[1];
1515 if (0 == (GNUNET_DISK_PF_BLOCKING_WRITE & pf))
1516 {
1517 flags = fcntl (fd[1], F_GETFL);
1518 flags |= O_NONBLOCK;
1519 if (0 > fcntl (fd[1], F_SETFL, flags))
1520 {
1521 ret = -1;
1522 eno = errno;
1523 }
1524 }
1525 flags = fcntl (fd[1], F_GETFD);
1526 flags |= FD_CLOEXEC;
1527 if (0 > fcntl (fd[1], F_SETFD, flags))
1528 {
1529 ret = -1;
1530 eno = errno;
1531 }
1532 }
1533 if (ret == -1)
1534 {
1535 errno = eno;
1537 if (p->fd[0]->fd >= 0)
1538 GNUNET_break (0 == close (p->fd[0]->fd));
1539 if (p->fd[1]->fd >= 0)
1540 GNUNET_break (0 == close (p->fd[1]->fd));
1541 GNUNET_free (p->fd[0]);
1542 GNUNET_free (p->fd[1]);
1543 GNUNET_free (p);
1544 errno = eno;
1545 return NULL;
1546 }
1547 return p;
1548}
1549
1550
1554{
1556
1558 {
1559 if (p->fd[0])
1560 {
1561 ret = GNUNET_DISK_file_close (p->fd[0]);
1562 p->fd[0] = NULL;
1563 }
1564 }
1565 else if (end == GNUNET_DISK_PIPE_END_WRITE)
1566 {
1567 if (p->fd[1])
1568 {
1569 ret = GNUNET_DISK_file_close (p->fd[1]);
1570 p->fd[1] = NULL;
1571 }
1572 }
1573 return ret;
1574}
1575
1576
1580{
1581 struct GNUNET_DISK_FileHandle *ret = NULL;
1582
1584 {
1585 if (p->fd[0])
1586 {
1587 ret = p->fd[0];
1588 p->fd[0] = NULL;
1589 }
1590 }
1591 else if (end == GNUNET_DISK_PIPE_END_WRITE)
1592 {
1593 if (p->fd[1])
1594 {
1595 ret = p->fd[1];
1596 p->fd[1] = NULL;
1597 }
1598 }
1599
1600 return ret;
1601}
1602
1603
1606{
1608 enum GNUNET_GenericReturnValue read_end_close;
1609 enum GNUNET_GenericReturnValue write_end_close;
1610 int read_end_close_errno;
1611 int write_end_close_errno;
1612
1614 read_end_close_errno = errno;
1616 write_end_close_errno = errno;
1617 GNUNET_free (p);
1618
1619 if (GNUNET_OK != read_end_close)
1620 {
1621 errno = read_end_close_errno;
1622 ret = read_end_close;
1623 }
1624 else if (GNUNET_OK != write_end_close)
1625 {
1626 errno = write_end_close_errno;
1627 ret = write_end_close;
1628 }
1629
1630 return ret;
1631}
1632
1633
1634const struct GNUNET_DISK_FileHandle *
1636 enum GNUNET_DISK_PipeEnd n)
1637{
1638 switch (n)
1639 {
1642 return p->fd[n];
1643
1644 default:
1645 GNUNET_break (0);
1646 return NULL;
1647 }
1648}
1649
1650
1653 int *dst)
1654{
1655 if (NULL == fh)
1656 return GNUNET_SYSERR;
1657 *dst = fh->fd;
1658 return GNUNET_OK;
1659}
1660
1661
1669static enum GNUNET_GenericReturnValue
1670purge_cfg_dir (void *cls,
1671 const struct GNUNET_CONFIGURATION_Handle *cfg)
1672{
1673 const char *option = cls;
1674 char *tmpname;
1675
1676 if (GNUNET_OK !=
1678 "PATHS",
1679 option,
1680 &tmpname))
1681 {
1683 "PATHS",
1684 option);
1685 return GNUNET_NO;
1686 }
1687 if (GNUNET_SYSERR ==
1689 {
1691 "remove",
1692 tmpname);
1693 GNUNET_free (tmpname);
1694 return GNUNET_OK;
1695 }
1696 GNUNET_free (tmpname);
1697 return GNUNET_OK;
1698}
1699
1700
1701void
1703 const char *cfg_filename,
1704 const char *option)
1705{
1710 (void *) option));
1711}
1712
1713
1714/* 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 enum GNUNET_GenericReturnValue glob_cb(void *cls, const char *filename)
Function called with a filename.
Definition: disk.c:980
#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:484
#define S_ISLNK(m)
Definition: disk.c:61
#define MAP_FAILED
Definition: disk.c:1389
static bool glob_match(const char *pattern, const char *str)
Check for a simple wildcard match.
Definition: disk.c:918
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:1670
#define LOG(kind,...)
Definition: disk.c:31
static char * mktemp_name(const char *t)
Create the name for a temporary file or directory from a template.
Definition: disk.c:296
#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:1078
enum GNUNET_GenericReturnValue GNUNET_DISK_internal_file_handle_(const struct GNUNET_DISK_FileHandle *fh, int *dst)
Retrieve OS file handle.
Definition: disk.c:1652
Internal DISK related helper functions.
char * getenv()
static struct GNUNET_ARM_MonitorHandle * m
Monitor connection with ARM.
Definition: gnunet-arm.c:103
static struct GNUNET_ARM_Handle * h
Connection with ARM.
Definition: gnunet-arm.c:98
static int ret
Final status code.
Definition: gnunet-arm.c:93
static struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
Definition: gnunet-arm.c:108
static char * dir
Set to the directory where runtime files are stored.
Definition: gnunet-arm.c:88
static int end
Set if we are to shutdown all services (including ARM).
Definition: gnunet-arm.c:33
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
static char * name
Name (label) of the records to list.
static char * res
Currently read line or NULL on EOF.
static int result
Global testing status.
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 @44 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 struct GNUNET_OS_ProjectData *pd, 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.
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:1635
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:1248
void GNUNET_DISK_filename_canonicalize(char *fn)
Removes special characters as ':' from a filename.
Definition: disk.c:1202
int GNUNET_DISK_glob(const char *glob_pattern, GNUNET_FileNameCallback callback, void *callback_cls)
Find all files matching a glob pattern.
Definition: disk.c:1011
enum GNUNET_GenericReturnValue GNUNET_DISK_file_change_owner(const char *filename, const char *user)
Change owner of a file.
Definition: disk.c:1224
char * GNUNET_DISK_mktemp(const char *t)
Create an (empty) temporary file on disk.
Definition: disk.c:421
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:523
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:244
char * 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:363
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:324
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:1578
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:1479
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:700
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:209
struct GNUNET_DISK_PipeHandle * GNUNET_DISK_pipe(enum GNUNET_DISK_PipeFlags pf)
Creates an interprocess channel.
Definition: disk.c:1458
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:530
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:225
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:1605
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:740
char * GNUNET_DISK_mkdtemp(const char *t)
Create an (empty) temporary directory on disk.
Definition: disk.c:343
enum GNUNET_GenericReturnValue GNUNET_DISK_file_copy(const char *src, const char *dst)
Copy a file.
Definition: disk.c:1133
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_remove(const char *filename)
Remove all files in a directory (rm -rf).
Definition: disk.c:1088
enum GNUNET_GenericReturnValue GNUNET_DISK_file_sync(const struct GNUNET_DISK_FileHandle *h)
Write file changes to disk.
Definition: disk.c:1441
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:189
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_test(const char *fil, int is_readable)
Test if fil is a directory and listable.
Definition: disk.c:444
enum GNUNET_GenericReturnValue GNUNET_DISK_file_close(struct GNUNET_DISK_FileHandle *h)
Close an open file.
Definition: disk.c:1322
void GNUNET_DISK_purge_cfg_dir(const struct GNUNET_OS_ProjectData *pd, const char *cfg_filename, const char *option)
Remove the directory given under option in section [PATHS] in configuration under cfg_filename.
Definition: disk.c:1702
struct GNUNET_DISK_FileHandle * GNUNET_DISK_get_handle_from_native(FILE *fd)
Get a handle from a native FD.
Definition: disk.c:1360
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_create_for_file(const char *filename)
Create the directory structure for storing a file.
Definition: disk.c:623
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:1394
struct GNUNET_DISK_FileHandle * GNUNET_DISK_get_handle_from_int_fd(int fno)
Get a handle from a native integer FD.
Definition: disk.c:1344
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:663
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:196
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:1552
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:716
enum GNUNET_GenericReturnValue GNUNET_DISK_file_unmap(struct GNUNET_DISK_MapHandle *h)
Unmap a file.
Definition: disk.c:1425
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_create(const char *dir)
Implementation of "mkdir -p".
Definition: disk.c:537
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:677
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:829
@ 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:504
static unsigned int size
Size of the "table".
Definition: peer.c:68
#define DIR_SEPARATOR
Definition: platform.h:166
#define O_LARGEFILE
Definition: platform.h:213
#define DIR_SEPARATOR_STR
Definition: platform.h:167
#define _(String)
GNU gettext support macro.
Definition: platform.h:179
Handle used to access files (and pipes).
int fd
File handle on Unix-like systems.
Handle for a memory-mapping operation.
Definition: disk.c:1375
void * addr
Address where the map is in memory.
Definition: disk.c:1379
size_t len
Number of bytes mapped.
Definition: disk.c:1384
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
Project-specific data used to help the OS subsystem find installation paths.
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:961
void * cls
Definition: disk.c:962
int nres
Number of files that actually matched the glob pattern.
Definition: disk.c:967
const char * glob
Definition: disk.c:960