+sub dir_glob_regex {
+ my ($dir, $regex) = @_;
+
+ my $dh = IO::Dir->new ($dir);
+ return wantarray ? () : undef if !$dh;
+
+ while (defined(my $tmp = $dh->read)) {
+ if (my @res = $tmp =~ m/^($regex)$/) {
+ $dh->close;
+ return wantarray ? @res : $tmp;
+ }
+ }
+ $dh->close;
+
+ return wantarray ? () : undef;
+}
+
+sub dir_glob_foreach {
+ my ($dir, $regex, $func) = @_;
+
+ my $dh = IO::Dir->new ($dir);
+ if (defined $dh) {
+ while (defined(my $tmp = $dh->read)) {
+ if (my @res = $tmp =~ m/^($regex)$/) {
+ &$func (@res);
+ }
+ }
+ }
+}
+
+sub assert_if_modified {
+ my ($digest1, $digest2) = @_;
+
+ if ($digest1 && $digest2 && ($digest1 ne $digest2)) {
+ die "detected modified configuration - file changed by other user? Try again.\n";
+ }
+}
+
+# Digest for short strings
+# like FNV32a, but we only return 31 bits (positive numbers)
+sub fnv31a {
+ my ($string) = @_;
+
+ my $hval = 0x811c9dc5;
+
+ foreach my $c (unpack('C*', $string)) {
+ $hval ^= $c;
+ $hval += (
+ (($hval << 1) ) +
+ (($hval << 4) ) +
+ (($hval << 7) ) +
+ (($hval << 8) ) +
+ (($hval << 24) ) );
+ $hval = $hval & 0xffffffff;
+ }
+ return $hval & 0x7fffffff;
+}
+
+sub fnv31a_hex { return sprintf("%X", fnv31a(@_)); }
+