/usr/local/CPAN/zxid/filex.pm
#!/usr/bin/perl -I../p
# Copyright (c) 1998-1999 Sampo Kellomaki <sampo@iki.fi>, 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 = <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