#!/usr/bin/perl -I../p # Copyright (c) 1998-1999 Sampo Kellomaki , All Rights Reserved. # This software may not be used or distributed for free or under any other # terms than those detailed in file COPYING. There is ABSOLUTELY NO WARRANTY. # Slurp and barf files with flock. These are supposed to be reasonably # efficient, too. Stdio is bypassed, for example. package filex; use integer; $trace = 0; sub slurp { my ($t,$nowarn) = @_; if (open(T, "<$t")) { flock T, 1; # Shared sysseek(T, 0, 0); sysread T, $t, -s(T); flock T, 8; close T; return $t; } else { my ($p,$f,$l)=caller; warn "$$: Cant read `$t' ($! at $f line $l)\n" unless $nowarn; return undef; } } sub barf { my ($t, $d) = @_; my ($p,$f,$l)=caller; umask 002; ($t) = $t =~ /^([^|;:&]+)$/; # untaint warn "$$: Barfing $t at $f line $l\n" if $trace; if (open(T, ">$t")) { flock T, 2; # Exclusive sysseek(T, 0, 0); syswrite T, $d, length($d); # Bypass stdio for efficiency flock T, 8; close T or do { warn "$$: Cant write `$t' ($! at $f line $l)\n"; return undef; }; return length($d) } else { warn "$$: Cant write `$t' ($! at $f line $l)\n"; return undef; } } ### This is really a multitasking synchronization primitive, useful ### for maintaining unique numbers. sub inc { my ($t,$inc) = @_; if (open(T, "+<$t")) { flock T, 2; # Exclusive seek(T, 0, 0); $t = ; chomp $t; seek(T, 0, 0); if ($inc eq 'a') { print T ++$t; } else { print T $t + $inc; } truncate T, tell T; flock T, 8; close T; return $t; } else { my ($p,$f,$l)=caller; warn "$$: Cant update `$t' ($! at $f line $l)"; return ''; } } ### Safely add a line to log sub append { my ($t,$line) = @_; if (open(T, ">>$t")) { flock T, 2; # Exclusive seek(T, 0, 2); # Go to absolute end of file (someone could have # written to the file while we were waiting for # flock) print T $line; flock T, 8; close T; return 1; } else { my ($p,$f,$l)=caller; warn "$$: Cant append `$t' ($! at $f line $l)"; return 0; } } 1; # EOF