]> git.ipfire.org Git - thirdparty/public-inbox.git/commitdiff
finalize DragonFlyBSD support
authorEric Wong <e@80x24.org>
Fri, 6 Oct 2023 09:46:04 +0000 (09:46 +0000)
committerEric Wong <e@80x24.org>
Fri, 6 Oct 2023 21:06:54 +0000 (21:06 +0000)
require_bsd and require_mods(':fcntl_lock') are now
supported in TestCommon to make it easier to maintain
than a big list of regexps.

getsockopt for SO_ACCEPTFILTER seems to always succeed,
even if the retrieved struct is all zeroes.

12 files changed:
install/os.perl
lib/PublicInbox/Daemon.pm
lib/PublicInbox/IPC.pm
lib/PublicInbox/MboxLock.pm
lib/PublicInbox/POP3D.pm
lib/PublicInbox/TestCommon.pm
t/ds-kqxs.t
t/kqnotify.t
t/pop3d-limit.t
t/pop3d.t
t/search.t
xt/pop3d-mpop.t

index 4fcbcbe49127b0f462809131e280044b15a6b07d..bf5c55c244d1b104a374304f031224809e79496c 100644 (file)
@@ -40,7 +40,7 @@ EOM
                last if $ID ne '' && $VERSION_ID ne '';
        }
        $ID = 'linux' if $ID eq ''; # cf. os-release(5)
-} elsif ($^O =~ m!\A(?:free|net|open)bsd\z!) { # TODO: net? dragonfly?
+} elsif ($^O =~ m!\A(?:free|net|open)bsd\z! || $^O eq 'dragonfly') {
        $ID = $^O;
        require POSIX;
        (undef, undef, $release, $version) = POSIX::uname();
@@ -50,7 +50,8 @@ EOM
        die "$^O unsupported";
 }
 $VERSION_ID //= 0; # numeric? could be 'sid', actually...
-my %MIN_VER = (freebsd => v11, openbsd => v7.3, netbsd => v9.3);
+my %MIN_VER = (freebsd => v11, openbsd => v7.3, netbsd => v9.3,
+       dragonfly => v6.4);
 
 if (defined(my $min_ver = $MIN_VER{$^O})) {
        my $vid = $VERSION_ID;
@@ -63,7 +64,7 @@ EOM
 }
 
 sub pkg_fmt () {
-       if ($ID eq 'freebsd') { 'pkg' }
+       if ($ID =~ /\A(?:freebsd|dragonfly)\z/) { 'pkg' }
        # *shrug*, as long as the (Net|Open)BSD names don't conflict w/ FreeBSD
        elsif ($ID eq 'netbsd') { 'pkgin' }
        elsif ($ID eq 'openbsd') { 'pkg_add' }
index a4c99ccac914740f7e7b1bbdb717e3cc83d3d4d6..520cef72916e3f63d10ffb7f2bf136022e271f06 100644 (file)
@@ -634,9 +634,9 @@ sub defer_accept ($$) {
                my $sec = unpack('i', $x);
                return if $sec > 0; # systemd users may set a higher value
                setsockopt($s, IPPROTO_TCP, $TCP_DEFER_ACCEPT, 1);
-       } elsif ($^O =~ /\A(?:freebsd|netbsd)\z/) {
+       } elsif ($^O =~ /\A(?:freebsd|netbsd|dragonfly)\z/) {
                my $x = getsockopt($s, SOL_SOCKET, $SO_ACCEPTFILTER);
-               return if defined $x; # don't change if set
+               return if ($x // "\0") =~ /[^\0]/s; # don't change if set
                my $accf_arg = pack('a16a240', $af_name, '');
                setsockopt($s, SOL_SOCKET, $SO_ACCEPTFILTER, $accf_arg);
        }
index 839281b2436001cb7d425e05464db28453c316f2..068c5623dfed6e6290d53136441b80b5340b4516 100644 (file)
@@ -437,6 +437,7 @@ sub DESTROY {
 my %NPROCESSORS_ONLN = (
        linux => 84,
        freebsd => 58,
+       dragonfly => 58,
        openbsd => 503,
        netbsd => 1002
 );
index 95aa986236019d6129a228892da10616d2151a85..9d7d4a32a13c45e64a237c953225b7c76ecaaaaa 100644 (file)
@@ -12,9 +12,13 @@ use PublicInbox::DS qw(now); # ugh...
 use autodie qw(chdir opendir unlink);
 
 our $TMPL = do {
-       if ($^O eq 'linux') { \'s @32' }
-       elsif ($^O =~ /bsd/) { \'@20 s @256' } # n.b. @32 may be enough...
-       else { eval { require File::FcntlLock; 1 } }
+       if ($^O eq 'linux') {
+               \'s @32'
+       } elsif ($^O =~ /bsd/ || $^O eq 'dragonfly') {
+               \'@20 s @256' # n.b. @32 may be enough...
+       } else {
+                eval { require File::FcntlLock; 1 }
+       }
 };
 
 # This order matches Debian policy on Linux systems.
index 2a9ccfdd27f856255c20ec2da7bdda89099cbdb4..38e982ee0cf34c10ab6891b653d7d8f28fbaaa00 100644 (file)
@@ -15,7 +15,7 @@ use File::Temp 0.19 (); # 0.19 for ->newdir
 use Fcntl qw(F_SETLK F_UNLCK F_WRLCK SEEK_SET);
 my ($FLOCK_TMPL, @FLOCK_ORDER);
 # are all BSDs the same "struct flock"? tested Free+Net+Open...
-if ($^O eq 'linux' || $^O =~ /bsd/) {
+if ($^O =~ /\A(?:linux|dragonfly)\z/ || $^O =~ /bsd/) {
        require Config;
        my $off_t;
        my $sz = $Config::Config{lseeksize};
@@ -28,7 +28,7 @@ if ($^O eq 'linux' || $^O =~ /bsd/) {
                if ($^O eq 'linux') {
                        $FLOCK_TMPL = "ss\@8$off_t$off_t\@32";
                        @FLOCK_ORDER = qw(l_type l_whence l_start l_len);
-               } elsif ($^O =~ /bsd/) { # @32 may be enough
+               } else { # *bsd including dragonfly
                        $FLOCK_TMPL = "${off_t}${off_t}lss\@256";
                        @FLOCK_ORDER = qw(l_start l_len l_pid l_type l_whence);
                }
index 32213fdec4c85c814efb1864866d98d33ac792bc..323152b44f057669c568b5064ce88cf178af54ef 100644 (file)
@@ -23,7 +23,7 @@ BEGIN {
        @EXPORT = qw(tmpdir tcp_server tcp_connect require_git require_mods
                run_script start_script key2sub xsys xsys_e xqx eml_load tick
                have_xapian_compact json_utf8 setup_public_inboxes create_inbox
-               create_coderepo no_scm_rights
+               create_coderepo require_bsd
                quit_waiter_pipe wait_for_eof
                tcp_host_port test_lei lei lei_ok $lei_out $lei_err $lei_opt
                test_httpd xbail require_cmd is_xdeeply tail_f
@@ -35,6 +35,15 @@ BEGIN {
        push @EXPORT, @methods;
 }
 
+sub require_bsd (;$) {
+       state $ok = ($^O =~ m!\A(?:free|net|open)bsd\z! ||
+                       $^O eq 'dragonfly');
+       return 1 if $ok;
+       return if defined(wantarray);
+       my $m = "$0 is BSD-only (\$^O=$^O)";
+       @_ ? skip($m) : plan(skip_all => $m);
+}
+
 sub xbail (@) { BAIL_OUT join(' ', map { ref() ? (explain($_)) : ($_) } @_) }
 
 sub eml_load ($) {
@@ -136,7 +145,8 @@ my %IPv6_VERSION = (
 sub need_accept_filter ($) {
        my ($af) = @_;
        return if $^O eq 'netbsd'; # since NetBSD 5.0
-       skip 'SO_ACCEPTFILTER is FreeBSD/NetBSD-only' if $^O ne 'freebsd';
+       $^O =~ /\A(?:freebsd|dragonfly)\z/ or
+               skip 'SO_ACCEPTFILTER is FreeBSD/NetBSD/Dragonfly-only so far';
        state $tried = {};
        ($tried->{$af} //= system("kldstat -m $af >/dev/null")) and
                skip "$af not loaded: kldload $af";
@@ -175,6 +185,11 @@ sub require_mods {
                                push @need, $msg;
                                next;
                        }
+               } elsif ($mod eq ':fcntl_lock') {
+                       next if $^O eq 'linux' || require_bsd;
+                       diag "untested platform: $^O, ".
+                               "requiring File::FcntlLock...";
+                       push @mods, 'File::FcntlLock';
                } elsif ($mod =~ /\A\+(accf_.*)\z/) {
                        need_accept_filter($1);
                        next
index 57acb53fc91c96b3a6b4afd6bbc9fbf87ac2b6bc..87f7199ddff280e8ca51422c1582ba0989b5812e 100644 (file)
@@ -6,8 +6,9 @@
 use v5.12;
 use Test::More;
 unless (eval { require IO::KQueue }) {
-       my $m = $^O !~ /bsd/ ? 'DSKQXS is only for *BSD systems'
-                               : "no IO::KQueue, skipping $0: $@";
+       my $m = ($^O =~ /bsd/ || $^O eq 'dragonfly') ?
+               "no IO::KQueue, skipping $0: $@" :
+               'DSKQXS is only for *BSD systems';
        plan skip_all => $m;
 }
 
index edecf2e118413b57cc6e172065c4d1c9e0dd57e7..cf32b63347c554890a0960546c6d036025db0e77 100644 (file)
@@ -7,7 +7,7 @@
 use v5.12;
 use PublicInbox::TestCommon;
 use autodie;
-plan skip_all => 'KQNotify is only for *BSD systems' if $^O !~ /bsd/;
+require_bsd;
 require_mods('IO::KQueue');
 use_ok 'PublicInbox::KQNotify';
 my ($tmpdir, $for_destroy) = tmpdir();
@@ -33,9 +33,35 @@ $hit = [ grep(m!/link$!, @read) ];
 is_deeply($hit, ["$tmpdir/new/link"], 'link(2) detected (via NOTE_WRITE)')
        or diag explain(\@read);
 
+{
+       my $d = "$tmpdir/new/ANOTHER";
+       mkdir $d;
+       $hit = [ map { $_->fullname } $kqn->read ];
+       is_xdeeply($hit, [ $d ], 'mkdir detected');
+       rmdir $d;
+       # TODO: should we always watch for directory removals?
+}
+
 $w->cancel;
 link("$tmpdir/new/tst", "$tmpdir/new/link2");
 $hit = [ map { $_->fullname } $kqn->read ];
 is_deeply($hit, [], 'link(2) not detected after cancel');
 
+# rearm:
+my $GONE = PublicInbox::KQNotify::NOTE_DELETE() |
+       PublicInbox::KQNotify::NOTE_REVOKE() |
+       PublicInbox::KQNotify::NOTE_ATTRIB() |
+       PublicInbox::KQNotify::NOTE_WRITE() |
+       PublicInbox::KQNotify::NOTE_RENAME();
+$w = $kqn->watch("$tmpdir/new", $mask|$GONE);
+my @unlink = sort glob("$tmpdir/new/*");
+unlink(@unlink);
+$hit = [ sort(map { $_->fullname } $kqn->read) ];
+is_xdeeply($hit, \@unlink, 'unlinked files match');
+
+# this is unreliable on Dragonfly tmpfs (fixed post-6.4)
+rmdir "$tmpdir/new";
+$hit = [ sort(map { $_->fullname } $kqn->read) ];
+is(scalar(@$hit), 1, 'detected self removal');
+
 done_testing;
index 00da477d6d80332b0406e9927ca101ca279efe21..79e320afec01c063b65d779038e95a13f4616292 100644 (file)
@@ -3,9 +3,7 @@
 # License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
 use v5.12;
 use PublicInbox::TestCommon;
-require_mods(qw(DBD::SQLite Net::POP3));
-$^O =~ /\A(?:linux|(?:free|net|open)bsd)\z/ or
-       require_mods(qw(File::FcntlLock));
+require_mods(qw(DBD::SQLite Net::POP3 :fcntl_lock));
 use autodie;
 my ($tmpdir, $for_destroy) = tmpdir();
 mkdir("$tmpdir/p3state");
index fce4a78803670a5c2d9b782b1633f6e2b4a05a24..ee19f2d765c1ce916b7f16797e08809fedbeb615 100644 (file)
--- a/t/pop3d.t
+++ b/t/pop3d.t
@@ -12,10 +12,8 @@ unless (-r $key && -r $cert) {
 }
 
 # Net::POP3 is part of the standard library, but distros may split it off...
-require_mods(qw(DBD::SQLite Net::POP3 IO::Socket::SSL));
-require_git('2.6'); # for v2
-$^O =~ /\A(?:linux|(?:free|net|open)bsd)\z/ or
-       require_mods(qw(File::FcntlLock));
+require_mods(qw(DBD::SQLite Net::POP3 IO::Socket::SSL :fcntl_lock));
+require_git(v2.6); # for v2
 use_ok 'IO::Socket::SSL';
 use_ok 'PublicInbox::TLS';
 my ($tmpdir, $for_destroy) = tmpdir();
index 636dc5cfe16a128fd6b829081cd0283821904a11..282ae5868d25c917f3d6974633557d0e66638e84 100644 (file)
@@ -440,7 +440,7 @@ my $dir_mask = 02770;
 # FreeBSD, OpenBSD and NetBSD do not allow non-root users to set S_ISGID,
 # so git doesn't set it, either (see DIR_HAS_BSD_GROUP_SEMANTICS in git.git)
 # Presumably all *BSDs behave the same way.
-if ($^O =~ /\A.+bsd\z/i) {
+if (require_bsd) {
        $all_mask = 0777;
        $dir_mask = 0770;
 }
index 9da1050c569c3e48645f997358a7eb7e53e820b0..ff8bb5dc9d0b6abd65fa5c32e9134a0ac2663b3e 100644 (file)
@@ -12,9 +12,8 @@ my $inboxdir = $ENV{GIANT_INBOX_DIR};
 plan skip_all => "bad characters in $inboxdir" if $inboxdir =~ m![^\w\.\-/]!;
 my $uuidgen = require_cmd('uuidgen');
 my $mpop = require_cmd('mpop');
-require_mods(qw(DBD::SQLite));
-require_git('2.6'); # for v2
-require_mods(qw(File::FcntlLock)) if $^O !~ /\A(?:linux|freebsd)\z/;
+require_mods(qw(DBD::SQLite :fcntl_lock));
+require_git(v2.6); # for v2
 
 my ($tmpdir, $for_destroy) = tmpdir();
 my $cfg = "$tmpdir/cfg";