+# Based on nmh's lkopen_fcntl
+# Return 0 for success, errno on failure.
+sub lkopen_fcntl {
+ my $file = shift;
+ my $access = shift;
+ my $mode = shift;
+ my $errno = 0;
+
+ # The assumption here is that if you open the file for writing, you
+ # need an exclusive lock.
+
+ my $tries = LOCK_TRIES;
+ for (;;) {
+ sysopen(my $fh, $file, $access, $mode) or die("sysopen($file): $!");
+
+ my $flk = File::FcntlLock->new;
+ $flk->l_start(0);
+ $flk->l_len(0);
+ $flk->l_type(($access & O_ACCMODE) == O_RDONLY ? F_RDLCK : F_WRLCK);
+ $flk->l_whence(SEEK_SET);
+
+ # Really should only retry on EAGAIN and EINTR...
+ if ($flk->lock($fh, F_SETLK)) {
+ return $fh, undef;
+ }
+
+ $errno = $flk->lock_errno;
+ close($fh) or die("close($file): $!");
+
+ if (--$tries == 0) {
+ last;
+ }
+ sleep(1);
+ }
+
+ return undef, $errno;
+}
+