in reply to fcntl failure after eval

This ain't right.

pack('sslli', F_WRLCK, SEEK_SET, 0, 0); 12345 1 2 3 4

So I gotta wonder if the string is at all right.

Replies are listed 'Best First'.
Re^2: fcntl failure after eval
by ikegami (Patriarch) on Aug 11, 2011 at 22:26 UTC

    Ok, omitting the last input appears to be acceptable.

    $ perl -wE'say length pack "sslli", 0, 0, 0, 0;' 16 $ perl -wE'say length pack "sslli", 0, 0, 0, 0, 0;' 16

    However, that's far shorter than expected, at least on the 64-bit system I used.

    $ cat a.c #include <fcntl.h> #include <stddef.h> #include <stdio.h> int main() { struct flock lock; printf("flock: %lu\n", sizeof(lock)); printf("flock.l_type: %lu @ %2lu\n", sizeof(lock.l_type ), offse +tof(struct flock, l_type )); printf("flock.l_whence: %lu @ %2lu\n", sizeof(lock.l_whence), offse +tof(struct flock, l_whence)); printf("flock.l_start: %lu @ %2lu\n", sizeof(lock.l_start ), offse +tof(struct flock, l_start )); printf("flock.l_len: %lu @ %2lu\n", sizeof(lock.l_len ), offse +tof(struct flock, l_len )); printf("flock.l_pid: %lu @ %2lu\n", sizeof(lock.l_pid ), offse +tof(struct flock, l_pid )); return 0; } $ gcc -Wall a.c -o a && a flock: 32 flock.l_type: 2 @ 0 flock.l_whence: 2 @ 2 flock.l_start: 8 @ 8 flock.l_len: 8 @ 16 flock.l_pid: 4 @ 24

    On that system, one would need

    $ perl -wE'say length pack "s s x4 q q L x4", 0, 0, 0, 0, 0;' 32

      This does look like the right answer.

      There are 3 different cases to consider:

      1. a 32 bit system with large file support (-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64)
      2. a 32 bit system without large file support
      3. a 64 bit system

      ikegami's c program for each of the three:

      1. 32 bit system with LFS:
        $ gcc -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -Wall a.c -o a && a
        flock:          24
        flock.l_type:   2 @  0
        flock.l_whence: 2 @  2
        flock.l_start:  8 @  4
        flock.l_len:    8 @ 12
        flock.l_pid:    4 @ 20
        
      2. 32 bit system without LFS:
        $ gcc  -Wall a.c -o a && a
        flock:          16
        flock.l_type:   2 @  0
        flock.l_whence: 2 @  2
        flock.l_start:  4 @  4
        flock.l_len:    4 @  8
        flock.l_pid:    4 @ 12
        
      3. 64 bit system:
        $ gcc  -Wall a.c -o a && a
        flock:          32
        flock.l_type:   2 @  0
        flock.l_whence: 2 @  2
        flock.l_start:  8 @  8
        flock.l_len:    8 @ 16
        flock.l_pid:    4 @ 24
        

      The test perls:

      1. stock perl-5.10.0, running on a 32 bit system with large file support
      2. debian perl-5.10.0, running on a 32 bit system with large file support
      3. debian perl-5.10.1, running on a 64 bit system

      Changing the op's code to:

      • my $flags = pack('sslli', F_WRLCK, SEEK_SET, 5, 0);
        • perl 1: length of flags: 16 bits, expected length: 24 bits
          fcntl64(3, F_SETLK64, {type=F_WRLCK, whence=SEEK_SET, start=5, len=0}, 0x9d827d0) = 0
          => this probably works by accident
          
        • perl 2: length of flags: 16 bits, expected length: 24 bits (running as a normal user)
          fcntl64(3, F_SETLK64, {type=F_WRLCK, whence=SEEK_SET, start=5, len=0}, 0x819b4a8) = 0
          => this probably works by accident
          
        • perl 2: length of flags: 16 bits, expected length: 24 bits (running as root)
          fcntl64(3, F_SETLK64, {type=F_WRLCK, whence=SEEK_SET, start=5, len=2314885392840523776}, 0x81ed670) = 0
          => the length parameter does not contain the expected value
        • perl 3: length of flags: 16 bits, expected length: 32 bits
          fcntl(3, F_SETLK, {type=F_WRLCK, whence=SEEK_SET, start=0, len=0}) = 0
          => not correct, start is 0 but 'expected' value is 5
          
      • my $flags = pack('sslllli', F_WRLCK, SEEK_SET, 5, 0, 2, 0, 0);
        • perl 1: length of flags: 24 bits, expected length: 24 bits
          fcntl64(3, F_SETLK64, {type=F_WRLCK, whence=SEEK_SET, start=5, len=2}, 0x970c7d0) = 0
          
        • perl 2: length of flags: 24 bits, expected length: 24 bits (running as a normal user and as root)
          fcntl64(3, F_SETLK64, {type=F_WRLCK, whence=SEEK_SET, start=5, len=2}, 0x819b4a8) = 0
          
        • perl 3: length of flags: 24 bits, expected length: 32 bits
          fcntl(3, F_SETLK, {type=F_WRLCK, whence=SEEK_SET, start=8589934592, len=0}) = 0
          
      • my $flags = pack("s s x4 q q L x4", F_WRLCK, SEEK_SET, 5, 2, 0);
        • perl 3: length of flags: 32 bits, expected length: 32 bits
          fcntl(3, F_SETLK, {type=F_WRLCK, whence=SEEK_SET, start=5, len=2}) = 0
          

      What this all means is that the value you need for $flags depends highly on the system it is running.. Which makes me wonder wheter or not there is a better way to accomplish what the op wants..

        pack('sslllli',

        Aside from the fact that it's very weird that you're mixing specific width specifiers (like "l") with loose width specifiers (like "i"), "ll" is not right. Won't handle negative offsets.

        Which makes me wonder wheter or not there is a better way to accomplish what the op wants..

        Use C to create the structure.