404

[ Avaa Bypassed ]




Upload:

Command:

botdev@18.116.61.213: ~ $
# -*- cperl -*-
#
# This program is free software; you can redistribute it and/or
# modify it under the same terms as Perl itself.
#
# Copyright (C) 2002-2014 Jens Thoms Toerring <jt@toerring.de>


# Package for file locking with fcntl(2) in which the binary layout of
# the C flock struct is determined via compiling and running a C program
# each time the package is loaded

package File::FcntlLock::Inline;

use 5.006001;
use strict;
use warnings;
use Fcntl;
use Config;
use File::Temp;
use File::Spec;
use base qw( File::FcntlLock::Core );


our $VERSION = File::FcntlLock::Core->VERSION;

our @EXPORT = @File::FcntlLock::Core::EXPORT;


my ( $packstr, @member_list );


###########################################################

BEGIN {
	# Create a C file in the preferred directory for temporary files for
	# probing the layout of the C 'flock struct'. Since __DATA__ can't
	# be used in a BEGIN block we've got to do with a HEREDOC.

	my $c_file = File::Temp->new( TEMPLATE => 'File-FcntlLock-XXXXXX',
								  SUFFIX   => '.c',
								  DIR      => File::Spec->tmpdir( ) );

	print $c_file <<EOF;
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <limits.h>


#define membersize( type, member ) ( sizeof( ( ( type * ) NULL )->member ) )
#define NUM_ELEMS( p ) ( sizeof p / sizeof *p )

typedef struct {
    const char * name;
    size_t       size;
    size_t       offset;
}  Params;


/*-------------------------------------------------*
 * Called from qsort() for sorting an array of Params structures
 * in ascending order of their 'offset' members
 *-------------------------------------------------*/

static int
comp( const void * a,
      const void * b )
{
    if ( a == b )
        return 0;
    return ( ( Params * ) a )->offset < ( ( Params * ) b )->offset ? -1 : 1;
}


/*-------------------------------------------------*
 *-------------------------------------------------*/

int
main( void )
{
    Params params[ ] = { { "l_type",
                           CHAR_BIT * membersize( struct flock, l_type ),
                           CHAR_BIT * offsetof( struct flock, l_type ) },
                         { "l_whence",
                           CHAR_BIT * membersize( struct flock, l_whence ),
                           CHAR_BIT * offsetof( struct flock, l_whence ) },
                         { "l_start",
                           CHAR_BIT * membersize( struct flock, l_start ),
                           CHAR_BIT * offsetof( struct flock, l_start ) },
                         { "l_len",
                           CHAR_BIT * membersize( struct flock, l_len ),
                           CHAR_BIT * offsetof( struct flock, l_len ) },
                         { "l_pid",
                           CHAR_BIT * membersize( struct flock, l_pid ),
                           CHAR_BIT * offsetof( struct flock, l_pid ) } };
    size_t size = CHAR_BIT * sizeof( struct flock );
    size_t i;
    size_t pos = 0;
    char packstr[ 128 ] = "";
    
    /* All sizes and offsets must be divisable by 8 and the sizes of the
       members must be either 8-, 16-, 32- or 64-bit values, otherwise
       there's no good way to pack them. */

    if ( size % 8 )
        exit( EXIT_FAILURE );

    size /= 8;

    for ( i = 0; i < NUM_ELEMS( params ); ++i )
    {
        if (    params[ i ].size   % 8
             || params[ i ].offset % 8
             || (    params[ i ].size   != 8
                  && params[ i ].size   != 16
                  && params[ i ].size   != 32
                  && params[ i ].size   != 64 ) )
            exit( EXIT_FAILURE );

        params[ i ].size   /= 8;
        params[ i ].offset /= 8;
    }

    /* Sort the array of structures for the members in ascending order of
       the offset */

    qsort( params, NUM_ELEMS( params ), sizeof *params, comp );

    /* Cobble together the template string to be passed to pack(), taking
       care of padding and also extra members we're not interested in. All
       the interesting members have signed integer types. */

    for ( i = 0; i < NUM_ELEMS( params ); ++i )
    {
		if ( pos != params[ i ].offset )
			sprintf( packstr + strlen( packstr ), "x%lu",
					 ( unsigned long )( params[ i ].offset - pos ) );
		pos = params[ i ].offset;

        switch ( params[ i ].size )
        {
            case 1 :
				strcat( packstr, "c" );
                break;

            case 2 :
				strcat( packstr, "s" );
                break;

            case 4 :
				strcat( packstr, "l" );
                break;

            case 8 :
#if defined NO_Q_FORMAT
                exit( EXIT_FAILURE );
#endif
				strcat( packstr, "q" );
                break;

            default :
                exit( EXIT_FAILURE );
        }

		pos += params[ i ].size;
    }

    if ( pos < size )
        sprintf( packstr + strlen( packstr ), "x%lu",
                 (unsigned long ) ( size - pos ) );

    printf( "%s\\n", packstr );
    for ( i = 0; i < NUM_ELEMS( params ); ++i )
		printf( "%s\\n", params[ i ].name );

    return 0;
}
EOF

	close $c_file;

	# Try to compile and link the file.

	my $exec_file = File::Temp->new( TEMPLATE => 'File=FcntlLock-XXXXXX',
									 DIR      => File::Spec->tmpdir( ) );
	close $exec_file;

    my $qflag = eval { pack 'q', 1 };
    $qflag = $@ ? '-DNO_Q_FORMAT' : '';

	die "Failed to run the C compiler '$Config{cc}'\n"
		if system "$Config{cc} $Config{ccflags} $qflag -o $exec_file $c_file";

	# Run the program and read it's output, it writes out the template string
	# we need for packing and unpacking the binary C struct flock required for
	# fcntl() and then the members of the structures in the sequence they are
	# defined in there.

	open my $pipe, '-|', $exec_file
		or die "Failed to run a compiled program: $!\n";

	chomp( $packstr = <$pipe> );
	while ( my $line = <$pipe> ) {
		chomp $line;
		push @member_list, $line;
	}

	# Make sure we got all information needed

    die   "Your Perl version does not support the 'q' format for pack() "
        . "and unpack()\n" unless defined $packstr;

	die "Failed to obtain all needed data about the C struct flock\n"
		unless @member_list == 5;
}


###########################################################
# Function for doing the actual fcntl() call: assembles the binary
# structure that must be passed to fcntl() from the File::FcntlLock
# object we get passed, calls it and then modifies the File::FcntlLock
# with the data from the flock structure

sub lock {
    my ( $self, $fh, $action ) = @_;

    my $buf = $self->pack_flock( );
    my $ret = fcntl( $fh, $action, $buf );

    if ( $ret  ) {
		$self->unpack_flock( $buf );
        $self->{ errno } = $self->{ error } = undef;
    } else {
        $self->get_error( $self->{ errno } = $! + 0 );
    }

    return $ret;
}


###########################################################
# Method for packing the data from the 'flock_struct' into a
# binary blob to be passed to fcntl().

sub pack_flock {
    my $self = shift;
	my @args;
	push @args, $self->{ $_ } for @member_list;
    return pack $packstr, @args;
}


###########################################################
# Method for unpacking the binary blob received from a call of
# fcntl() into the 'flock_struct'.

sub unpack_flock {
	my ( $self, $data ) = @_;
	my @res = unpack $packstr, $data;
	$self->{ $_ } = shift @res for @member_list;
}


=cut


1;


# Local variables:
# tab-width: 4
# indent-tabs-mode: nil
# End:

Filemanager

Name Type Size Permission Actions
Core.pm File 3.29 KB 0644
Errors.pm File 4.03 KB 0644
Inline.pm File 7.32 KB 0644
Inline.pod File 10.47 KB 0644
Pure.pm File 2.21 KB 0644
Pure.pod File 10.47 KB 0644
XS.pm File 494 B 0644
XS.pod File 10.47 KB 0644