GNUnet debian-0.24.3-1-ge21d59ae2
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_NO))
174 {
175 char linkdst[PATH_MAX];
176 ssize_t ret;
177 ret = readlink(fn, linkdst, PATH_MAX);
178 if (0 > ret)
179 {
181 return GNUNET_SYSERR;
182 }
183 linkdst[ret] = '\0';
184 return get_size_rec(gfsd, linkdst);
185 }
186 if ((! S_ISLNK (buf.st_mode)) || (gfsd->include_sym_links == GNUNET_YES))
187 gfsd->total += buf.st_size;
188 if ((S_ISDIR (buf.st_mode)) && (0 == access (fn, X_OK)) &&
189 ((! S_ISLNK (buf.st_mode)) || (gfsd->include_sym_links == GNUNET_YES)))
190 {
191 if (GNUNET_SYSERR ==
194 gfsd))
195 return GNUNET_SYSERR;
196 }
197 return GNUNET_OK;
198}
199
200
203{
204 return ((! h) || (h->fd == -1)) ? GNUNET_YES : GNUNET_NO;
205}
206
207
210 off_t *size)
211{
212 struct stat sbuf;
213
214 if (0 != fstat (fh->fd, &sbuf))
215 return GNUNET_SYSERR;
216 *size = sbuf.st_size;
217 return GNUNET_OK;
218}
219
220
221off_t
223 off_t offset,
224 enum GNUNET_DISK_Seek whence)
225{
226 static int t[] = { SEEK_SET, SEEK_CUR, SEEK_END };
227
228 if (h == NULL)
229 {
230 errno = EINVAL;
231 return GNUNET_SYSERR;
232 }
233 return lseek (h->fd, offset, t[whence]);
234}
235
236
239 uint64_t *size,
240 int include_symbolic_links,
241 int single_file_mode)
242{
243 struct GetFileSizeData gfsd;
245
246 GNUNET_assert (size != NULL);
247 gfsd.total = 0;
248 gfsd.include_sym_links = include_symbolic_links;
250 ret = get_size_rec (&gfsd, filename);
251 *size = gfsd.total;
252 return ret;
253}
254
255
258 uint64_t *dev,
259 uint64_t *ino)
260{
261#if HAVE_STAT
262 {
263 struct stat sbuf;
264
265 if (0 != stat (filename, &sbuf))
266 {
267 return GNUNET_SYSERR;
268 }
269 *ino = (uint64_t) sbuf.st_ino;
270 }
271#else
272 *ino = 0;
273#endif
274#if HAVE_STATVFS
275 {
276 struct statvfs fbuf;
277
278 if (0 != statvfs (filename, &fbuf))
279 {
280 return GNUNET_SYSERR;
281 }
282 *dev = (uint64_t) fbuf.f_fsid;
283 }
284#elif HAVE_STATFS
285 {
286 struct statfs fbuf;
287
288 if (0 != statfs (filename, &fbuf))
289 {
290 return GNUNET_SYSERR;
291 }
292 *dev =
293 ((uint64_t) fbuf.f_fsid.val[0]) << 32 || ((uint64_t) fbuf.f_fsid.val[1]);
294 }
295#else
296 *dev = 0;
297#endif
298 return GNUNET_OK;
299}
300
301
308static char *
309mktemp_name (const char *t)
310{
311 const char *tmpdir;
312 char *tmpl;
313 char *fn;
314
315 if ((t[0] != '/') && (t[0] != '\\'))
316 {
317 /* FIXME: This uses system codepage on W32, not UTF-8 */
318 tmpdir = getenv ("TMPDIR");
319 if (NULL == tmpdir)
320 tmpdir = getenv ("TMP");
321 if (NULL == tmpdir)
322 tmpdir = getenv ("TEMP");
323 if (NULL == tmpdir)
324 tmpdir = "/tmp";
325 GNUNET_asprintf (&tmpl, "%s/%s%s", tmpdir, t, "XXXXXX");
326 }
327 else
328 {
329 GNUNET_asprintf (&tmpl, "%s%s", t, "XXXXXX");
330 }
331 fn = tmpl;
332 return fn;
333}
334
335
336void
338 int require_uid_match,
339 int require_gid_match)
340{
341 mode_t mode;
342
343 if (GNUNET_YES == require_uid_match)
344 mode = S_IRUSR | S_IWUSR | S_IXUSR;
345 else if (GNUNET_YES == require_gid_match)
346 mode = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP;
347 else
348 mode = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH
349 | S_IWOTH | S_IXOTH;
350 if (0 != chmod (fn, mode))
352}
353
354
355char *
357{
358 char *fn;
359 mode_t omask;
360
361 omask = umask (S_IWGRP | S_IWOTH | S_IRGRP | S_IROTH);
362 fn = mktemp_name (t);
363 if (fn != mkdtemp (fn))
364 {
366 GNUNET_free (fn);
367 umask (omask);
368 return NULL;
369 }
370 umask (omask);
371 return fn;
372}
373
374
375char *
376GNUNET_DISK_file_backup (const char *fil)
377{
378 size_t slen;
379 char *target;
380 unsigned int num;
381
382 slen = strlen (fil) + 20;
383 target = GNUNET_malloc (slen);
384 num = 0;
385
386#if HAVE_RENAMEAT2
387 {
388 int fd;
389
390 do
391 {
392 GNUNET_snprintf (target,
393 slen,
394 "%s.%u~",
395 fil,
396 num++);
397 fd = open (target,
398 O_CREAT | O_EXCL,
400 } while (-1 == fd);
401 if (0 != renameat2 (AT_FDCWD,
402 fil,
403 AT_FDCWD,
404 target,
405 RENAME_EXCHANGE))
406 {
408 "renameat2",
409 fil);
410 GNUNET_break (0 ==
411 close (fd));
412 return NULL;
413 }
414 GNUNET_break (0 ==
415 close (fd));
416 }
417#else
418 do
419 {
420 GNUNET_snprintf (target, slen, "%s.%u~", fil, num++);
421 }
422 while (0 == access (target, F_OK));
423 if (0 != rename (fil, target))
424 {
426 return NULL;
427 }
428#endif
429 return target;
430}
431
432
433char *
435{
436 int fd;
437 char *fn;
438 mode_t omask;
439
440 omask = umask (S_IWGRP | S_IWOTH | S_IRGRP | S_IROTH);
441 fn = mktemp_name (t);
442 if (-1 == (fd = mkstemp (fn)))
443 {
445 GNUNET_free (fn);
446 umask (omask);
447 return NULL;
448 }
449 umask (omask);
450 if (0 != close (fd))
452 return fn;
453}
454
455
457GNUNET_DISK_directory_test (const char *fil, int is_readable)
458{
459 struct stat filestat;
460 int ret;
461
462 ret = stat (fil, &filestat);
463 if (ret != 0)
464 {
465 if (errno != ENOENT)
467 return GNUNET_SYSERR;
468 }
469 if (! S_ISDIR (filestat.st_mode))
470 {
472 "A file already exits with the same name %s\n",
473 fil);
474 return GNUNET_NO;
475 }
476 if (GNUNET_YES == is_readable)
477 ret = access (fil, R_OK | X_OK);
478 else
479 ret = access (fil, X_OK);
480 if (ret < 0)
481 {
483 return GNUNET_NO;
484 }
485 return GNUNET_YES;
486}
487
488
497file_test_internal (const char *fil, int amode)
498{
499 struct stat filestat;
500 int ret;
501 char *rdir;
502
504 if (rdir == NULL)
505 return GNUNET_SYSERR;
506
507 ret = stat (rdir, &filestat);
508 if (0 != ret)
509 {
510 if (errno != ENOENT)
511 {
513 GNUNET_free (rdir);
514 return GNUNET_SYSERR;
515 }
516 GNUNET_free (rdir);
517 return GNUNET_NO;
518 }
519 if (! S_ISREG (filestat.st_mode))
520 {
521 GNUNET_free (rdir);
522 return GNUNET_NO;
523 }
524 if (access (rdir, amode) < 0)
525 {
527 GNUNET_free (rdir);
528 return GNUNET_SYSERR;
529 }
530 GNUNET_free (rdir);
531 return GNUNET_YES;
532}
533
534
536GNUNET_DISK_file_test (const char *fil)
537{
538 return file_test_internal (fil, F_OK);
539}
540
541
544{
545 return file_test_internal (fil, R_OK);
546}
547
548
551{
552 char *rdir;
553 unsigned int len;
554 unsigned int pos;
555 unsigned int pos2;
556 int ret = GNUNET_OK;
557
559 if (rdir == NULL)
560 {
561 GNUNET_break (0);
562 return GNUNET_SYSERR;
563 }
564
565 len = strlen (rdir);
566
567 pos = 1; /* skip heading '/' */
568
569 /* Check which low level directories already exist */
570 pos2 = len;
571 rdir[len] = DIR_SEPARATOR;
572 while (pos <= pos2)
573 {
574 if (DIR_SEPARATOR == rdir[pos2])
575 {
576 rdir[pos2] = '\0';
578 if (GNUNET_NO == ret)
579 {
581 "Creating directory `%s' failed\n",
582 rdir);
583 GNUNET_free (rdir);
584 return GNUNET_SYSERR;
585 }
586 rdir[pos2] = DIR_SEPARATOR;
587 if (GNUNET_YES == ret)
588 {
589 pos2++;
590 break;
591 }
592 }
593 pos2--;
594 }
595 rdir[len] = '\0';
596 if (pos < pos2)
597 pos = pos2;
598 /* Start creating directories */
599 while (pos <= len)
600 {
601 if ((rdir[pos] == DIR_SEPARATOR) || (pos == len))
602 {
603 rdir[pos] = '\0';
605 if (GNUNET_NO == ret)
606 {
608 "Creating directory `%s' failed\n",
609 rdir);
610 GNUNET_free (rdir);
611 return GNUNET_SYSERR;
612 }
613 if (GNUNET_SYSERR == ret)
614 {
615 ret = mkdir (rdir,
616 S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH
617 | S_IXOTH); /* 755 */
618
619 if ((ret != 0) && (errno != EEXIST))
620 {
622 GNUNET_free (rdir);
623 return GNUNET_SYSERR;
624 }
625 }
626 rdir[pos] = DIR_SEPARATOR;
627 }
628 pos++;
629 }
630 GNUNET_free (rdir);
631 return GNUNET_OK;
632}
633
634
637{
638 char *rdir;
639 size_t len;
640 int eno;
642
644 if (NULL == rdir)
645 {
646 errno = EINVAL;
647 return GNUNET_SYSERR;
648 }
649 if (0 == access (rdir, W_OK))
650 {
651 GNUNET_free (rdir);
652 return GNUNET_OK;
653 }
654 len = strlen (rdir);
655 while ((len > 0) && (rdir[len] != DIR_SEPARATOR))
656 len--;
657 rdir[len] = '\0';
658 /* The empty path is invalid and in this case refers to / */
659 if (0 == len)
660 {
661 GNUNET_free (rdir);
662 rdir = GNUNET_strdup ("/");
663 }
665 if ( (GNUNET_OK == res) &&
666 (0 != access (rdir, W_OK)) )
667 res = GNUNET_NO;
668 eno = errno;
669 GNUNET_free (rdir);
670 errno = eno;
671 return res;
672}
673
674
675ssize_t
677 void *result,
678 size_t len)
679{
680 if (NULL == h)
681 {
682 errno = EINVAL;
683 return GNUNET_SYSERR;
684 }
685 return read (h->fd, result, len);
686}
687
688
689ssize_t
690GNUNET_DISK_fn_read (const char *fn,
691 void *result,
692 size_t len)
693{
694 struct GNUNET_DISK_FileHandle *fh;
695 ssize_t ret;
696 int eno;
697
698 fh = GNUNET_DISK_file_open (fn,
701 if (NULL == fh)
702 return GNUNET_SYSERR;
703 ret = GNUNET_DISK_file_read (fh, result, len);
704 eno = errno;
707 errno = eno;
708 return ret;
709}
710
711
712ssize_t
714 const void *buffer,
715 size_t n)
716{
717 if (NULL == h)
718 {
719 errno = EINVAL;
720 return GNUNET_SYSERR;
721 }
722 return write (h->fd,
723 buffer,
724 n);
725}
726
727
728ssize_t
730 const void *buffer,
731 size_t n)
732{
733 int flags;
734 ssize_t ret;
735
736 if (NULL == h)
737 {
738 errno = EINVAL;
739 return GNUNET_SYSERR;
740 }
741 /* set to blocking, write, then set back */
742 flags = fcntl (h->fd, F_GETFL);
743 if (0 != (flags & O_NONBLOCK))
744 (void) fcntl (h->fd, F_SETFL, flags - O_NONBLOCK);
745 ret = write (h->fd, buffer, n);
746 if (0 == (flags & O_NONBLOCK))
747 (void) fcntl (h->fd, F_SETFL, flags);
748 return ret;
749}
750
751
753GNUNET_DISK_fn_write (const char *fn,
754 const void *buf,
755 size_t buf_size,
757{
758 char *tmpl;
759 int fd;
760
761 if (GNUNET_OK !=
763 {
765 "mkstemp",
766 fn);
767 return GNUNET_SYSERR;
768 }
769 {
770 char *dname;
771
772 dname = GNUNET_strdup (fn);
773 GNUNET_asprintf (&tmpl,
774 "%s/XXXXXX",
775 dirname (dname));
776 GNUNET_free (dname);
777 }
778 fd = mkstemp (tmpl);
779 if (-1 == fd)
780 {
782 "mkstemp",
783 tmpl);
784 GNUNET_free (tmpl);
785 return GNUNET_SYSERR;
786 }
787
788 if (0 != fchmod (fd,
790 {
792 "chmod",
793 tmpl);
794 GNUNET_assert (0 == close (fd));
795 if (0 != unlink (tmpl))
797 "unlink",
798 tmpl);
799 GNUNET_free (tmpl);
800 return GNUNET_SYSERR;
801 }
802 if (buf_size !=
803 write (fd,
804 buf,
805 buf_size))
806 {
808 "write",
809 tmpl);
810 GNUNET_assert (0 == close (fd));
811 if (0 != unlink (tmpl))
813 "unlink",
814 tmpl);
815 GNUNET_free (tmpl);
816 return GNUNET_SYSERR;
817 }
818 GNUNET_assert (0 == close (fd));
819
820 if (0 != link (tmpl,
821 fn))
822 {
823 if (0 != unlink (tmpl))
825 "unlink",
826 tmpl);
827 GNUNET_free (tmpl);
828 return GNUNET_NO;
829 }
830 if (0 != unlink (tmpl))
832 "unlink",
833 tmpl);
834 GNUNET_free (tmpl);
835 return GNUNET_OK;
836
837
838}
839
840
841int
844 void *callback_cls)
845{
846 DIR *dinfo;
847 struct dirent *finfo;
848 int count = 0;
850 char *name;
851 char *dname;
852 unsigned int name_len;
853 unsigned int n_size;
854
855 GNUNET_assert (NULL != dir_name);
857 if (NULL == dname)
858 return GNUNET_SYSERR;
859 while ( (strlen (dname) > 0) &&
860 (dname[strlen (dname) - 1] == DIR_SEPARATOR) )
861 dname[strlen (dname) - 1] = '\0';
862 dinfo = opendir (dname);
863 if (NULL == dinfo)
864 {
866 "opendir",
867 dname);
868 GNUNET_free (dname);
869 return GNUNET_SYSERR;
870 }
871 name_len = 256;
872 n_size = strlen (dname) + name_len + strlen (DIR_SEPARATOR_STR) + 1;
873 name = GNUNET_malloc (n_size);
874 while (NULL != (finfo = readdir (dinfo)))
875 {
876 if ((0 == strcmp (finfo->d_name, ".")) ||
877 (0 == strcmp (finfo->d_name, "..")))
878 continue;
879 if (NULL != callback)
880 {
881 if (name_len < strlen (finfo->d_name))
882 {
884 name_len = strlen (finfo->d_name);
885 n_size = strlen (dname) + name_len + strlen (DIR_SEPARATOR_STR) + 1;
886 name = GNUNET_malloc (n_size);
887 }
888 /* dname can end in "/" only if dname == "/";
889 * if dname does not end in "/", we need to add
890 * a "/" (otherwise, we must not!) */
892 n_size,
893 "%s%s%s",
894 dname,
895 (0 == strcmp (dname,
897 ? ""
899 finfo->d_name);
900 ret = callback (callback_cls,
901 name);
902 if (GNUNET_OK != ret)
903 {
904 closedir (dinfo);
906 GNUNET_free (dname);
907 if (GNUNET_NO == ret)
908 return count;
909 return GNUNET_SYSERR;
910 }
911 }
912 count++;
913 }
914 closedir (dinfo);
916 GNUNET_free (dname);
917 return count;
918}
919
920
930static bool
931glob_match (const char *pattern, const char *str)
932{
933 /* Position in the input string */
934 const char *str_pos = str;
935 /* Position in the pattern */
936 const char *pat_pos = pattern;
937 /* Backtrack position in string */
938 const char *str_bt = NULL;
939 /* Backtrack position in pattern */
940 const char *pat_bt = NULL;
941
942 for (;;)
943 {
944 if (*pat_pos == '*')
945 {
946 str_bt = str_pos;
947 pat_bt = pat_pos++;
948 }
949 else if (*pat_pos == *str_pos)
950 {
951 if ('\0' == *pat_pos)
952 return true;
953 str_pos++;
954 pat_pos++;
955 }
956 else
957 {
958 if (NULL == str_bt)
959 return false;
960 /* Backtrack to match one more
961 character as part of the asterisk. */
962 str_pos = str_bt + 1;
963 if ('\0' == *str_pos)
964 return false;
965 pat_pos = pat_bt;
966 }
967 }
968}
969
970
972{
973 const char *glob;
975 void *cls;
976
980 int nres;
981};
982
993glob_cb (void *cls,
994 const char *filename)
995{
996 struct GlobClosure *gc = cls;
997 const char *fn;
998
999 fn = strrchr (filename, DIR_SEPARATOR);
1000 fn = (NULL == fn) ? filename : (fn + 1);
1001
1003 "checking glob '%s' against '%s'\n",
1004 gc->glob,
1005 fn);
1006
1007 if (glob_match (gc->glob, fn))
1008 {
1009 enum GNUNET_GenericReturnValue cbret;
1010
1012 "found glob match '%s'\n",
1013 filename);
1014 gc->nres++;
1015 cbret = gc->cb (gc->cls, filename);
1016 if (GNUNET_OK != cbret)
1017 return cbret;
1018 }
1019 return GNUNET_OK;
1020}
1021
1022
1023int
1024GNUNET_DISK_glob (const char *glob_pattern,
1025 GNUNET_FileNameCallback callback,
1026 void *callback_cls)
1027{
1028 char *mypat = GNUNET_strdup (glob_pattern);
1029 char *sep;
1030 int ret;
1031
1032 if ( (NULL != strrchr (glob_pattern, '+')) ||
1033 (NULL != strrchr (glob_pattern, '[')) ||
1034 (NULL != strrchr (glob_pattern, '~')) )
1035 {
1037 "unsupported glob pattern: '%s'\n",
1038 glob_pattern);
1039 GNUNET_free (mypat);
1040 return -1;
1041 }
1042
1043 sep = strrchr (mypat, DIR_SEPARATOR);
1044 if (NULL == sep)
1045 {
1046 GNUNET_free (mypat);
1047 return -1;
1048 }
1049
1050 *sep = '\0';
1051
1052 if (NULL != strchr (mypat, '*'))
1053 {
1054 GNUNET_free (mypat);
1055 GNUNET_break (0);
1057 "glob pattern may only contain '*' in the final path component\n");
1058 return -1;
1059 }
1060
1061 {
1062 struct GlobClosure gc = {
1063 .glob = sep + 1,
1064 .cb = callback,
1065 .cls = callback_cls,
1066 .nres = 0,
1067 };
1069 "scanning directory '%s' for glob matches on '%s'\n",
1070 mypat,
1071 gc.glob);
1073 glob_cb,
1074 &gc
1075 );
1076 GNUNET_free (mypat);
1077 return (ret < 0) ? ret : gc.nres;
1078 }
1079}
1080
1081
1090static enum GNUNET_GenericReturnValue
1091remove_helper (void *unused,
1092 const char *fn)
1093{
1094 (void) unused;
1095 (void) GNUNET_DISK_directory_remove (fn);
1096 return GNUNET_OK;
1097}
1098
1099
1102{
1103 struct stat istat;
1104
1105 if (NULL == filename)
1106 {
1107 GNUNET_break (0);
1108 return GNUNET_SYSERR;
1109 }
1110 if (0 != lstat (filename, &istat))
1111 return GNUNET_NO; /* file may not exist... */
1112 (void) chmod (filename,
1113 S_IWUSR | S_IRUSR | S_IXUSR);
1114 if (0 == unlink (filename))
1115 return GNUNET_OK;
1116 if ( (errno != EISDIR) &&
1117 /* EISDIR is not sufficient in all cases, e.g.
1118 * sticky /tmp directory may result in EPERM on BSD.
1119 * So we also explicitly check "isDirectory" */
1120 (GNUNET_YES !=
1122 GNUNET_YES)) )
1123 {
1125 "rmdir",
1126 filename);
1127 return GNUNET_SYSERR;
1128 }
1129 if (GNUNET_SYSERR ==
1132 NULL))
1133 return GNUNET_SYSERR;
1134 if (0 != rmdir (filename))
1135 {
1137 "rmdir",
1138 filename);
1139 return GNUNET_SYSERR;
1140 }
1141 return GNUNET_OK;
1142}
1143
1144
1146GNUNET_DISK_file_copy (const char *src,
1147 const char *dst)
1148{
1149 char *buf;
1150 uint64_t pos;
1151 uint64_t size;
1152 size_t len;
1153 ssize_t sret;
1154 struct GNUNET_DISK_FileHandle *in;
1155 struct GNUNET_DISK_FileHandle *out;
1156
1158 {
1160 return GNUNET_SYSERR;
1161 }
1162 pos = 0;
1163 in =
1165 if (! in)
1166 {
1168 return GNUNET_SYSERR;
1169 }
1170 out =
1178 if (! out)
1179 {
1182 return GNUNET_SYSERR;
1183 }
1185 while (pos < size)
1186 {
1187 len = COPY_BLK_SIZE;
1188 if (len > size - pos)
1189 len = size - pos;
1190 sret = GNUNET_DISK_file_read (in, buf, len);
1191 if ((sret < 0) || (len != (size_t) sret))
1192 goto FAIL;
1193 sret = GNUNET_DISK_file_write (out, buf, len);
1194 if ((sret < 0) || (len != (size_t) sret))
1195 goto FAIL;
1196 pos += len;
1197 }
1198 GNUNET_free (buf);
1203 return GNUNET_OK;
1204FAIL:
1205 GNUNET_free (buf);
1210 return GNUNET_SYSERR;
1211}
1212
1213
1214void
1216{
1217 char *idx;
1218 char c;
1219
1220 for (idx = fn; *idx; idx++)
1221 {
1222 c = *idx;
1223
1224 if ((c == '/') || (c == '\\') || (c == ':') || (c == '*') || (c == '?') ||
1225 (c ==
1226 '"')
1227 ||
1228 (c == '<') || (c == '>') || (c == '|') )
1229 {
1230 *idx = '_';
1231 }
1232 }
1233}
1234
1235
1238 const char *user)
1239{
1240 struct passwd *pws;
1241
1242 pws = getpwnam (user);
1243 if (NULL == pws)
1244 {
1246 _ ("Cannot obtain information about user `%s': %s\n"),
1247 user,
1248 strerror (errno));
1249 return GNUNET_SYSERR;
1250 }
1251 if (0 != chown (filename, pws->pw_uid, pws->pw_gid))
1252 {
1254 return GNUNET_SYSERR;
1255 }
1256 return GNUNET_OK;
1257}
1258
1259
1262 enum GNUNET_DISK_OpenFlags flags,
1264{
1265 char *expfn;
1267
1268 int oflags;
1269 int mode;
1270 int fd;
1271
1272 expfn = GNUNET_STRINGS_filename_expand (fn);
1273 if (NULL == expfn)
1274 return NULL;
1275
1276 mode = 0;
1278 oflags = O_RDWR; /* note: O_RDWR is NOT always O_RDONLY | O_WRONLY */
1279 else if (flags & GNUNET_DISK_OPEN_READ)
1280 oflags = O_RDONLY;
1281 else if (flags & GNUNET_DISK_OPEN_WRITE)
1282 oflags = O_WRONLY;
1283 else
1284 {
1285 GNUNET_break (0);
1286 GNUNET_free (expfn);
1287 return NULL;
1288 }
1290 oflags |= (O_CREAT | O_EXCL);
1291 if (flags & GNUNET_DISK_OPEN_TRUNCATE)
1292 oflags |= O_TRUNC;
1293 if (flags & GNUNET_DISK_OPEN_APPEND)
1294 oflags |= O_APPEND;
1295 if (GNUNET_NO == GNUNET_DISK_file_test (fn))
1296 {
1297 if (flags & GNUNET_DISK_OPEN_CREATE)
1298 {
1300 oflags |= O_CREAT;
1301 mode = translate_unix_perms (perm);
1302 }
1303 }
1304
1305 // Setting O_CLOEXEC after pipe() may introduce
1306 // race conditions: https://bugs.gnunet.org/view.php?id=9311
1307 // This is no problem if the platform supports pipe2
1308 fd = open (expfn,
1309 oflags
1310#if O_CLOEXEC
1311 | O_CLOEXEC
1312#endif
1313 | O_LARGEFILE,
1314 mode);
1315 if (fd == -1)
1316 {
1317 if (0 == (flags & GNUNET_DISK_OPEN_FAILIFEXISTS))
1319 else
1321 GNUNET_free (expfn);
1322 return NULL;
1323 }
1324
1326
1327 ret->fd = fd;
1328
1329 GNUNET_free (expfn);
1330 return ret;
1331}
1332
1333
1336{
1338
1339 if (NULL == h)
1340 {
1341 errno = EINVAL;
1342 return GNUNET_SYSERR;
1343 }
1344
1345 ret = GNUNET_OK;
1346 if (0 != close (h->fd))
1347 {
1350 }
1351 GNUNET_free (h);
1352 return ret;
1353}
1354
1355
1358{
1359 struct GNUNET_DISK_FileHandle *fh;
1360
1361 if ((((off_t) -1) == lseek (fno, 0, SEEK_CUR)) && (EBADF == errno))
1362 return NULL; /* invalid FD */
1363
1364 fh = GNUNET_new (struct GNUNET_DISK_FileHandle);
1365
1366 fh->fd = fno;
1367
1368 return fh;
1369}
1370
1371
1374{
1375 int fno;
1376
1377 fno = fileno (fd);
1378 if (-1 == fno)
1379 return NULL;
1381}
1382
1383
1388{
1392 void *addr;
1393
1397 size_t len;
1398};
1399
1400
1401#ifndef MAP_FAILED
1402#define MAP_FAILED ((void *) -1)
1403#endif
1404
1405
1406void *
1408 struct GNUNET_DISK_MapHandle **m,
1409 enum GNUNET_DISK_MapType access,
1410 size_t len)
1411{
1412 int prot;
1413
1414 if (NULL == h)
1415 {
1416 errno = EINVAL;
1417 return NULL;
1418 }
1419 prot = 0;
1420 if (access & GNUNET_DISK_MAP_TYPE_READ)
1421 prot = PROT_READ;
1422 if (access & GNUNET_DISK_MAP_TYPE_WRITE)
1423 prot |= PROT_WRITE;
1425 (*m)->addr = mmap (NULL, len, prot, MAP_SHARED, h->fd, 0);
1426 GNUNET_assert (NULL != (*m)->addr);
1427 if (MAP_FAILED == (*m)->addr)
1428 {
1429 GNUNET_free (*m);
1430 return NULL;
1431 }
1432 (*m)->len = len;
1433 return (*m)->addr;
1434}
1435
1436
1439{
1441
1442 if (NULL == h)
1443 {
1444 errno = EINVAL;
1445 return GNUNET_SYSERR;
1446 }
1447 ret = munmap (h->addr, h->len) != -1 ? GNUNET_OK : GNUNET_SYSERR;
1448 GNUNET_free (h);
1449 return ret;
1450}
1451
1452
1455{
1456 if (h == NULL)
1457 {
1458 errno = EINVAL;
1459 return GNUNET_SYSERR;
1460 }
1461
1462#if ! defined(__linux__) || ! defined(GNU)
1463 return fsync (h->fd) == -1 ? GNUNET_SYSERR : GNUNET_OK;
1464#else
1465 return fdatasync (h->fd) == -1 ? GNUNET_SYSERR : GNUNET_OK;
1466#endif
1467}
1468
1469
1472{
1473 int fd[2];
1474
1475#if HAVE_PIPE2 && O_CLOEXEC
1476 if (-1 == pipe2 (fd, O_CLOEXEC))
1477#else
1478 if (-1 == pipe (fd))
1479#endif
1480 {
1481 int eno = errno;
1482
1484 errno = eno;
1485 return NULL;
1486 }
1487 return GNUNET_DISK_pipe_from_fd (pf, fd);
1488}
1489
1490
1493 int fd[2])
1494{
1495 struct GNUNET_DISK_PipeHandle *p;
1496 int ret = 0;
1497 int flags;
1498 int eno = 0; /* make gcc happy */
1499
1501 if (fd[0] >= 0)
1502 {
1503 p->fd[0] = GNUNET_new (struct GNUNET_DISK_FileHandle);
1504 p->fd[0]->fd = fd[0];
1505 if (0 == (GNUNET_DISK_PF_BLOCKING_READ & pf))
1506 {
1507 flags = fcntl (fd[0], F_GETFL);
1508 flags |= O_NONBLOCK;
1509 if (0 > fcntl (fd[0], F_SETFL, flags))
1510 {
1511 ret = -1;
1512 eno = errno;
1513 }
1514 }
1515 flags = fcntl (fd[0], F_GETFD);
1516 flags |= FD_CLOEXEC;
1517 if (0 > fcntl (fd[0], F_SETFD, flags))
1518 {
1519 ret = -1;
1520 eno = errno;
1521 }
1522 }
1523
1524 if (fd[1] >= 0)
1525 {
1526 p->fd[1] = GNUNET_new (struct GNUNET_DISK_FileHandle);
1527 p->fd[1]->fd = fd[1];
1528 if (0 == (GNUNET_DISK_PF_BLOCKING_WRITE & pf))
1529 {
1530 flags = fcntl (fd[1], F_GETFL);
1531 flags |= O_NONBLOCK;
1532 if (0 > fcntl (fd[1], F_SETFL, flags))
1533 {
1534 ret = -1;
1535 eno = errno;
1536 }
1537 }
1538 flags = fcntl (fd[1], F_GETFD);
1539 flags |= FD_CLOEXEC;
1540 if (0 > fcntl (fd[1], F_SETFD, flags))
1541 {
1542 ret = -1;
1543 eno = errno;
1544 }
1545 }
1546 if (ret == -1)
1547 {
1548 errno = eno;
1550 if (p->fd[0]->fd >= 0)
1551 GNUNET_break (0 == close (p->fd[0]->fd));
1552 if (p->fd[1]->fd >= 0)
1553 GNUNET_break (0 == close (p->fd[1]->fd));
1554 GNUNET_free (p->fd[0]);
1555 GNUNET_free (p->fd[1]);
1556 GNUNET_free (p);
1557 errno = eno;
1558 return NULL;
1559 }
1560 return p;
1561}
1562
1563
1567{
1569
1571 {
1572 if (p->fd[0])
1573 {
1574 ret = GNUNET_DISK_file_close (p->fd[0]);
1575 p->fd[0] = NULL;
1576 }
1577 }
1578 else if (end == GNUNET_DISK_PIPE_END_WRITE)
1579 {
1580 if (p->fd[1])
1581 {
1582 ret = GNUNET_DISK_file_close (p->fd[1]);
1583 p->fd[1] = NULL;
1584 }
1585 }
1586 return ret;
1587}
1588
1589
1593{
1594 struct GNUNET_DISK_FileHandle *ret = NULL;
1595
1597 {
1598 if (p->fd[0])
1599 {
1600 ret = p->fd[0];
1601 p->fd[0] = NULL;
1602 }
1603 }
1604 else if (end == GNUNET_DISK_PIPE_END_WRITE)
1605 {
1606 if (p->fd[1])
1607 {
1608 ret = p->fd[1];
1609 p->fd[1] = NULL;
1610 }
1611 }
1612
1613 return ret;
1614}
1615
1616
1619{
1621 enum GNUNET_GenericReturnValue read_end_close;
1622 enum GNUNET_GenericReturnValue write_end_close;
1623 int read_end_close_errno;
1624 int write_end_close_errno;
1625
1627 read_end_close_errno = errno;
1629 write_end_close_errno = errno;
1630 GNUNET_free (p);
1631
1632 if (GNUNET_OK != read_end_close)
1633 {
1634 errno = read_end_close_errno;
1635 ret = read_end_close;
1636 }
1637 else if (GNUNET_OK != write_end_close)
1638 {
1639 errno = write_end_close_errno;
1640 ret = write_end_close;
1641 }
1642
1643 return ret;
1644}
1645
1646
1647const struct GNUNET_DISK_FileHandle *
1649 enum GNUNET_DISK_PipeEnd n)
1650{
1651 switch (n)
1652 {
1655 return p->fd[n];
1656
1657 default:
1658 GNUNET_break (0);
1659 return NULL;
1660 }
1661}
1662
1663
1666 int *dst)
1667{
1668 if (NULL == fh)
1669 return GNUNET_SYSERR;
1670 *dst = fh->fd;
1671 return GNUNET_OK;
1672}
1673
1674
1682static enum GNUNET_GenericReturnValue
1683purge_cfg_dir (void *cls,
1684 const struct GNUNET_CONFIGURATION_Handle *cfg)
1685{
1686 const char *option = cls;
1687 char *tmpname;
1688
1689 if (GNUNET_OK !=
1691 "PATHS",
1692 option,
1693 &tmpname))
1694 {
1696 "PATHS",
1697 option);
1698 return GNUNET_NO;
1699 }
1700 if (GNUNET_SYSERR ==
1702 {
1704 "remove",
1705 tmpname);
1706 GNUNET_free (tmpname);
1707 return GNUNET_OK;
1708 }
1709 GNUNET_free (tmpname);
1710 return GNUNET_OK;
1711}
1712
1713
1714void
1716 const char *cfg_filename,
1717 const char *option)
1718{
1723 (void *) option));
1724}
1725
1726
1727/* 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:993
#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:497
#define S_ISLNK(m)
Definition: disk.c:61
#define MAP_FAILED
Definition: disk.c:1402
static bool glob_match(const char *pattern, const char *str)
Check for a simple wildcard match.
Definition: disk.c:931
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:1683
#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:309
#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:1091
enum GNUNET_GenericReturnValue GNUNET_DISK_internal_file_handle_(const struct GNUNET_DISK_FileHandle *fh, int *dst)
Retrieve OS file handle.
Definition: disk.c:1665
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:1648
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:1261
void GNUNET_DISK_filename_canonicalize(char *fn)
Removes special characters as ':' from a filename.
Definition: disk.c:1215
int GNUNET_DISK_glob(const char *glob_pattern, GNUNET_FileNameCallback callback, void *callback_cls)
Find all files matching a glob pattern.
Definition: disk.c:1024
enum GNUNET_GenericReturnValue GNUNET_DISK_file_change_owner(const char *filename, const char *user)
Change owner of a file.
Definition: disk.c:1237
char * GNUNET_DISK_mktemp(const char *t)
Create an (empty) temporary file on disk.
Definition: disk.c:434
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:536
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:257
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:376
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:337
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:1591
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:1492
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:713
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:222
struct GNUNET_DISK_PipeHandle * GNUNET_DISK_pipe(enum GNUNET_DISK_PipeFlags pf)
Creates an interprocess channel.
Definition: disk.c:1471
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:543
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:238
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:1618
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:753
char * GNUNET_DISK_mkdtemp(const char *t)
Create an (empty) temporary directory on disk.
Definition: disk.c:356
enum GNUNET_GenericReturnValue GNUNET_DISK_file_copy(const char *src, const char *dst)
Copy a file.
Definition: disk.c:1146
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_remove(const char *filename)
Remove all files in a directory (rm -rf).
Definition: disk.c:1101
enum GNUNET_GenericReturnValue GNUNET_DISK_file_sync(const struct GNUNET_DISK_FileHandle *h)
Write file changes to disk.
Definition: disk.c:1454
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:202
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_test(const char *fil, int is_readable)
Test if fil is a directory and listable.
Definition: disk.c:457
enum GNUNET_GenericReturnValue GNUNET_DISK_file_close(struct GNUNET_DISK_FileHandle *h)
Close an open file.
Definition: disk.c:1335
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:1715
struct GNUNET_DISK_FileHandle * GNUNET_DISK_get_handle_from_native(FILE *fd)
Get a handle from a native FD.
Definition: disk.c:1373
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_create_for_file(const char *filename)
Create the directory structure for storing a file.
Definition: disk.c:636
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:1407
struct GNUNET_DISK_FileHandle * GNUNET_DISK_get_handle_from_int_fd(int fno)
Get a handle from a native integer FD.
Definition: disk.c:1357
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:676
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:209
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:1565
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:729
enum GNUNET_GenericReturnValue GNUNET_DISK_file_unmap(struct GNUNET_DISK_MapHandle *h)
Unmap a file.
Definition: disk.c:1438
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_create(const char *dir)
Implementation of "mkdir -p".
Definition: disk.c:550
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:690
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:842
@ 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:506
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
#define PATH_MAX
Assumed maximum path length.
Definition: platform.h:242
Handle used to access files (and pipes).
int fd
File handle on Unix-like systems.
Handle for a memory-mapping operation.
Definition: disk.c:1388
void * addr
Address where the map is in memory.
Definition: disk.c:1392
size_t len
Number of bytes mapped.
Definition: disk.c:1397
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:974
void * cls
Definition: disk.c:975
int nres
Number of files that actually matched the glob pattern.
Definition: disk.c:980
const char * glob
Definition: disk.c:973