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