]> git.ipfire.org Git - thirdparty/public-inbox.git/commitdiff
pop3d: support fcntl locks on OpenBSD i386
authorEric Wong <e@80x24.org>
Thu, 1 Feb 2024 20:59:48 +0000 (20:59 +0000)
committerEric Wong <e@80x24.org>
Tue, 6 Feb 2024 00:39:57 +0000 (00:39 +0000)
The packaged Perl on OpenBSD i386 supports 64-bit file offsets
but not 64-bit integer support for 'q' and 'Q' with `pack'.
Since servers aren't likely to require lock files larger than
2 GB (we'd need an inbox with >2 billion messages), we can
workaround the Perl build limitation with explicit padding.

File::FcntlLock isn't packaged for OpenBSD <= 7.4 (but should be
in future releases), but I can test i386 OpenBSD on an extremely
slow VM.

Big endian support can be done, too, but I have no idea if
there's 32-bit BE users around nowadays...

MANIFEST
lib/PublicInbox/POP3D.pm
t/pop3d_lock.t [new file with mode: 0644]

index 2223cfb4ec490572a3d5780f9304d55e2a1ae884..4c974338a12fc28625d3d5528b4a6b29e499043f 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -575,6 +575,7 @@ t/plack-qp.eml
 t/plack.t
 t/pop3d-limit.t
 t/pop3d.t
+t/pop3d_lock.t
 t/precheck.t
 t/psgi_attach.eml
 t/psgi_attach.t
index 38e982ee0cf34c10ab6891b653d7d8f28fbaaa00..bd44043452b7f6ca8696fb5661d4d49777866292 100644 (file)
@@ -18,18 +18,32 @@ my ($FLOCK_TMPL, @FLOCK_ORDER);
 if ($^O =~ /\A(?:linux|dragonfly)\z/ || $^O =~ /bsd/) {
        require Config;
        my $off_t;
+       my @LE_pad = ('', '');
        my $sz = $Config::Config{lseeksize};
-
-       if ($sz == 8 && eval('length(pack("q", 1)) == 8')) { $off_t = 'q' }
-       elsif ($sz == 4) { $off_t = 'l' }
-       else { warn "sizeof(off_t)=$sz requires File::FcntlLock\n" }
-
+       if ($sz == 8) {
+               if (eval('length(pack("q", 1)) == 8')) {
+                       $off_t = 'q';
+               } elsif ($Config::Config{byteorder} == 1234) { # OpenBSD i386
+                       $off_t = 'l';
+                       @LE_pad = ('@8', '@16');
+               } else { # I have no 32-bit BE machine to test on...
+                       warn <<EOM;
+Perl built with 64-bit file support but not 64-bit int (pack("q")) support.
+byteorder=$Config::Config{byteorder}
+EOM
+               }
+       } elsif ($sz == 4) {
+               $off_t = 'l';
+       } else {
+               warn "sizeof(off_t)=$sz requires File::FcntlLock\n"
+       }
        if (defined($off_t)) {
                if ($^O eq 'linux') {
-                       $FLOCK_TMPL = "ss\@8$off_t$off_t\@32";
+                       $FLOCK_TMPL = 'ss@8'.$off_t.$LE_pad[0].$off_t.'@32';
                        @FLOCK_ORDER = qw(l_type l_whence l_start l_len);
                } else { # *bsd including dragonfly
-                       $FLOCK_TMPL = "${off_t}${off_t}lss\@256";
+                       $FLOCK_TMPL = $off_t.$LE_pad[0].$off_t.$LE_pad[1].
+                                       'lss@256';
                        @FLOCK_ORDER = qw(l_start l_len l_pid l_type l_whence);
                }
        }
diff --git a/t/pop3d_lock.t b/t/pop3d_lock.t
new file mode 100644 (file)
index 0000000..fb305f9
--- /dev/null
@@ -0,0 +1,16 @@
+# Copyright (C) all contributors <meta@public-inbox.org>
+# 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 :fcntl_lock));
+use autodie;
+my $tmpdir = tmpdir;
+require_ok 'PublicInbox::POP3D';
+my $pop3d = bless {}, 'PublicInbox::POP3D';
+open $pop3d->{txn_fh}, '+>>', "$tmpdir/txn.lock";
+use Fcntl qw(F_SETLK F_UNLCK F_WRLCK);
+
+ok $pop3d->_setlk(l_type => F_WRLCK, l_start => 9, l_len => 1),
+       'locked file (check with ktrace/strace)';
+
+done_testing;