in reply to Check if file is locked without locking it

fcntl has an F_GETLK flag which will tell if the file would have been locked without actually locking it (although it isn't documented it does appear in the code, you could check the fcntl(2) man page for information on how it works in C), but if you are checking something that can't deal with a split second lock, and it only uses flock, you may just be out of luck.


We're not surrounded, we're in a target-rich environment!
  • Comment on Re: Check if file is locked without locking it

Replies are listed 'Best First'.
Re: Re: Check if file is locked without locking it
by perlplexer (Hermit) on Apr 10, 2003 at 22:34 UTC
    Thanks for the pointer, jasonk++.
    I guess I'd eventually stumble upon this but you saved me a lot of time. :)

    In case someone needs this in the future, the following works for <2GB files on HPUX 11
    use Fcntl; use POSIX qw(:unistd_h); ... # $fh -- open file handle # $lock is the structure that will be passed to fcntl(). # Note that values in the structure must be valid even # though they are not required for F_GETLK. If you just # zero-out everything fcntl() will return "Invalid argument" my $lock = pack 'sslli', F_UNLCK, SEEK_SET, 0, 0, 0; # Second parameter - 5, represents F_GETLK. I couldn't use # F_GETLK directly because it is mapped to 8 (F_GETLK64) and # I couldn't get the definition for flock64 (the equivalent # of "flock" for large files). The reason F_GETLK64 is # mapped to F_GETLK is because perl was compiled with # USE_LARGE_FILES. if (fcntl($fh, 5, $lock)){ my $lpid = (unpack 'sslli', $lock)[-1]; if ($lpid){ print "File is locked by PID: $lpid\n"; }else{ print "File is not locked\n"; } }else{ print STDERR "fcntl() failed: $!\n"; } ...
    What I still don't know, and would be grateful if someone could point me in the right direction, is where flock64 is defined and what it looks like.
    "/usr/include/sys/fcntl.h" includes "/usr/include/sys/_flock_body.h", which defines flock64 as:
    short l_type; short l_whence; long long l_start; long long l_len; unsigned int l_pid;
    which should make the structure be 24 bytes long.
    So, I packed it as 'sslllli' and got a nice "possible memory overflow" message after calling fcntl()... :/
    To figure out what was going wrong I wrote a small C program, defined "_APP32_64BIT_OFF_T" to enable large file support, and did a sizeof() on the structure. Turns out it's 32 bytes long. Memory dumps showed that the structure looks something like this:
    short l_type; /* 2 bytes */ short l_whence; /* 2 bytes*/ long four_byte_foo; /* what's this? */ long long l_start; /* 8 bytes */ long long l_len; /* 8 bytes */ unsigned int l_pid; /* 4 bytes */ long four_byte_bar; /* what is this? */
    So, I'm not sure where those extra 8 bytes come from. They look suspiciously like padding, to make sure everything's on a 64-bit boundary, but I'm not entirely sure...

    As a side note, direct usage of fcntl() makes your program unportable even among UNIX systems. Linux, SunOS, BSD -- they all have different flock structures and Windows doesn't even support fcntl().

    --perlplexer