Says Ras:
Does anybody know how to lock a specific area in a file?
You need to use the fcntl() function
and pass a struct flock structure as
the third argument; you can construct this
struct using Perl's pack function.
Here's an example program:
#!/usr/bin/perl
# System V record locking demonstration
# Author: Mark Jason Dominus 20010503
# This program is in the public domain
use Fcntl qw(F_GETLK F_SETLK F_WRLCK F_RDLCK F_UNLCK );
my %type = map {&$_ => $_} qw(F_WRLCK F_RDLCK F_UNLCK);
my @whence = ('from beginning', 'from current position', 'from end');
# this is correct for my I386 linux box, but will be different
# depending on your OS and hardwre
$struct_flock = "s s l l L";
$file = $0;
open F, "+< $file" or die "Couldn't open file $file: $!; aborting";
do_lock(0, 10, F_WRLCK);
if (fork()) { # parent
wait;
} else {
do_lock(9, 20, F_WRLCK);
}
exit;
# see make_lock for an explanation of the arguments
sub do_lock {
my $lock_s = make_lock(@_);
if (fcntl(F, F_SETLK, $lock_s)) {
print "Got lock.\n";
} else {
print "Lock failed: $!\n\t", lock_struct_to_string($lock_s), "\n";
}
}
sub lock_struct_to_string {
my $s = shift;
my @d = unpack $struct_flock, $s;
my $type = $type{$d[0]} || '(unknown)';
my $whence = $whence[$d[1]];
my ($start, $len, $pid) = @d[2,3,4];
my $end = $start + $len - 1;
"$start-$end [type: $type; whence: $whence; pid: $pid]";
}
# arguments: lock $length bytes of the file, starting at position $pos
+ition
# $type should be F_WRLCK for a write lock, F_RDLCK for a read lock
# F_UNLCK releases the lock
sub make_lock {
my ($position, $length, $type) = @_;
$type = F_WRLCK unless defined $type;
return pack $struct_flock, $type, 0, $position, $length, $$;
}
This locks bytes 0-9 of a file and prints
a success message. Then it forks a
child process; the parent waits while the child tries to
lock bytes 9-28. The child fails to get the lock
(because byte 9 is locked by the parent) and prints a
diagnostic message. If you change the code
so that the child tries to lock a non-overlapping
region of the file, then the lock succeeds.
Note that this is the only time I have ever used the
fcntl-style region locking, so I have probably
not used the best practice here, whatever it is. All
I can vouch for is that the example does seem to work.
Hope this helps.
--
Mark Dominus
Perl Paraphernalia
|