aboutsummaryrefslogtreecommitdiff
path: root/src/util/disk.c
diff options
context:
space:
mode:
authorFlorian Dold <florian@dold.me>2021-07-28 14:31:38 +0200
committerFlorian Dold <florian@dold.me>2021-07-28 15:27:39 +0200
commit7615d46b09275383bd244a0ef1d94b3a77559b88 (patch)
treef6452173470ae80b186a4ee6da24d1d88d5033f2 /src/util/disk.c
parent391794a460140192b3466765ebc63797cea44000 (diff)
downloadgnunet-7615d46b09275383bd244a0ef1d94b3a77559b88.tar.gz
gnunet-7615d46b09275383bd244a0ef1d94b3a77559b88.zip
implement config inline globbing
Diffstat (limited to 'src/util/disk.c')
-rw-r--r--src/util/disk.c139
1 files changed, 138 insertions, 1 deletions
diff --git a/src/util/disk.c b/src/util/disk.c
index 3bafe311d..1b909f13e 100644
--- a/src/util/disk.c
+++ b/src/util/disk.c
@@ -882,6 +882,143 @@ GNUNET_DISK_directory_scan (const char *dir_name,
882 return count; 882 return count;
883} 883}
884 884
885/**
886 * Check for a simple wildcard match.
887 * Only asterisks are allowed.
888 * Asterisks match everything, including slashes.
889 *
890 * @param pattern pattern with wildcards
891 * @param str string to match against
892 * @returns true on match, false otherwise
893 */
894static bool
895glob_match (const char *pattern, const char *str)
896{
897 /* Position in the input string */
898 const char *str_pos = str;
899 /* Position in the pattern */
900 const char *pat_pos = pattern;
901 /* Backtrack position in string */
902 const char *str_bt = NULL;
903 /* Backtrack position in pattern */
904 const char *pat_bt = NULL;
905
906 for (;;)
907 {
908 if (*pat_pos == '*')
909 {
910 str_bt = str_pos;
911 pat_bt = pat_pos++;
912 }
913 else if (*pat_pos == *str_pos)
914 {
915 if ('\0' == *pat_pos)
916 return true;
917 str_pos++;
918 pat_pos++;
919 }
920 else
921 {
922 if (NULL == str_bt)
923 return false;
924 /* Backtrack to match one more
925 character as part of the asterisk. */
926 str_pos = str_bt + 1;
927 if ('\0' == *str_pos)
928 return false;
929 pat_pos = pat_bt;
930 }
931 }
932}
933
934struct GlobClosure
935{
936 const char *glob;
937 GNUNET_FileNameCallback cb;
938 void *cls;
939};
940
941/**
942 * Function called with a filename.
943 *
944 * @param cls closure
945 * @param filename complete filename (absolute path)
946 * @return #GNUNET_OK to continue to iterate,
947 * #GNUNET_NO to stop iteration with no error,
948 * #GNUNET_SYSERR to abort iteration with error!
949 */
950static enum GNUNET_GenericReturnValue
951glob_cb (void *cls,
952 const char *filename)
953{
954 struct GlobClosure *gc = cls;
955 const char *fn;
956
957 fn = strrchr (filename, DIR_SEPARATOR);
958 fn = (NULL == fn) ? filename : (fn + 1);
959
960 LOG (GNUNET_ERROR_TYPE_DEBUG,
961 "checking glob '%s' against '%s'\n",
962 gc->glob,
963 fn);
964
965 if (glob_match (gc->glob, fn))
966 {
967 LOG (GNUNET_ERROR_TYPE_DEBUG,
968 "found glob match '%s'\n",
969 filename);
970 gc->cb (gc->cls, filename);
971 }
972 return GNUNET_OK;
973}
974
975
976int
977GNUNET_DISK_glob (const char *glob_pattern,
978 GNUNET_FileNameCallback callback,
979 void *callback_cls)
980{
981 char *mypat = GNUNET_strdup (glob_pattern);
982 char *sep;
983 int ret;
984
985 sep = strrchr (mypat, DIR_SEPARATOR);
986 if (NULL == sep)
987 {
988 GNUNET_free (mypat);
989 return -1;
990 }
991
992 *sep = '\0';
993
994 if (NULL != strchr (mypat, '*'))
995 {
996 GNUNET_free (mypat);
997 GNUNET_break (0);
998 LOG (GNUNET_ERROR_TYPE_ERROR,
999 "glob pattern may only contain '*' in the final path component\n");
1000 return -1;
1001 }
1002
1003 {
1004 struct GlobClosure gc = {
1005 .glob = sep + 1,
1006 .cb = callback,
1007 .cls = callback_cls,
1008 };
1009 LOG (GNUNET_ERROR_TYPE_DEBUG,
1010 "scanning directory '%s' for glob matches on '%s'\n",
1011 mypat,
1012 gc.glob);
1013 ret = GNUNET_DISK_directory_scan (mypat,
1014 glob_cb,
1015 &gc
1016 );
1017 }
1018 GNUNET_free (mypat);
1019 return ret;
1020}
1021
885 1022
886/** 1023/**
887 * Function that removes the given directory by calling 1024 * Function that removes the given directory by calling
@@ -997,7 +1134,7 @@ GNUNET_DISK_file_copy (const char *src,
997 GNUNET_DISK_file_close (in); 1134 GNUNET_DISK_file_close (in);
998 GNUNET_DISK_file_close (out); 1135 GNUNET_DISK_file_close (out);
999 return GNUNET_OK; 1136 return GNUNET_OK;
1000FAIL: 1137 FAIL:
1001 GNUNET_free (buf); 1138 GNUNET_free (buf);
1002 GNUNET_DISK_file_close (in); 1139 GNUNET_DISK_file_close (in);
1003 GNUNET_DISK_file_close (out); 1140 GNUNET_DISK_file_close (out);