+sub lockfile ($$) {
+ my ($fh, $fn, $flockmode) = @_;
+ for (;;) {
+ close $fh;
+ open $fh, '+>', $fn or fail "open/create $fn for lock: $!";
+ if (!flock $fh, $lockmode) {
+ if ($lockmode & LOCK_NB and $! == EWOULDBLOCK) {
+ return 0; # ok then
+ }
+ fail "lock $fn".
+ (($flockmode & ~LOCK_NB) == LOCK_SH ? " (shared)" : "").
+ ": $!";
+ }
+ stat $fh or fail "stat opened $fn: $!";
+ my $fh_ino = ((stat _)[1]);
+ if (!stat $fn) {
+ $! == ENOENT or fail "stat $fn: $!";
+ next;
+ }
+ my $fn_ino = ((stat _)[1]);
+ return 1 if $fn_ino == $fh_ino;
+ # oh dear
+ }
+}
+