File Coverage

blib/lib/FFI/C/Stat.pm
Criterion Covered Total %
statement 23 24 95.8
branch 5 6 83.3
condition 1 3 33.3
subroutine 7 7 100.0
pod 1 1 100.0
total 37 41 90.2


line stmt bran cond sub pod time code
1             package FFI::C::Stat;
2              
3 1     1   252927 use strict;
  1         10  
  1         32  
4 1     1   6 use warnings;
  1         1  
  1         30  
5 1     1   40 use 5.008004;
  1         5  
6 1     1   561 use Ref::Util qw( is_ref is_globref is_blessed_ref );
  1         1902  
  1         86  
7 1     1   8 use Carp ();
  1         3  
  1         34  
8 1     1   759 use FFI::Platypus 1.00;
  1         7888  
  1         623  
9              
10             # ABSTRACT: Object-oriented FFI interface to native stat and lstat
11             our $VERSION = '0.02'; # VERSION
12              
13              
14             my $ffi = FFI::Platypus->new( api => 1 );
15             $ffi->bundle; # for accessors / constructor / destructor
16              
17             $ffi->type('object(FFI::C::Stat)', 'stat');
18             if($^O eq 'MSWin32')
19             {
20             $ffi->type('uint' => $_) for qw( uid_t gid_t nlink_t blksize_t blkcnt_t );
21             }
22              
23             $ffi->mangler(sub { "stat__$_[0]" });
24              
25             $ffi->attach( '_stat' => ['string'] => 'opaque' );
26             $ffi->attach( '_fstat' => ['int', ] => 'opaque' );
27             $ffi->attach( '_lstat' => ['string'] => 'opaque' );
28              
29              
30             sub new
31             {
32 5     5 1 23681 my($class, $file, %options) = @_;
33              
34 5         14 my $ptr;
35 5 100 33     48 if(is_globref $file)
    50          
36 1         33 { $ptr = _fstat(fileno($file)) }
37             elsif(!is_ref($file) && defined $file)
38 4 100       164 { $ptr = $options{symlink} ? _lstat($file) : _stat($file) }
39             else
40 0         0 { Carp::croak("Tried to stat something whch is neither a glob reference nor a plain string") }
41              
42 5         66 bless \$ptr, $class;
43             }
44              
45              
46             $ffi->attach( clone => ['opaque'] => 'opaque' => sub {
47             my($xsub, $class, $other) = @_;
48              
49             my $ptr;
50             if(is_blessed_ref $other)
51             {
52             if($other->isa('FFI::C::Stat'))
53             {
54             $ptr = $xsub->($$other);
55             }
56             else
57             {
58             Carp::croak("Not a FFI::C::Struct instance");
59             }
60             }
61             elsif(!is_ref $other)
62             {
63             $ptr = $xsub->($other);
64             }
65             else
66             {
67             Carp::croak("Not an FFI::C::Struct structure or opaque pointer");
68             }
69              
70             bless \$ptr, $class;
71             });
72              
73             $ffi->attach( DESTROY => ['stat'] );
74              
75              
76             $ffi->attach( dev => ['stat'] => 'dev_t' );
77             $ffi->attach( ino => ['stat'] => 'ino_t' );
78             $ffi->attach( mode => ['stat'] => 'mode_t' );
79             $ffi->attach( nlink => ['stat'] => 'nlink_t' );
80             $ffi->attach( uid => ['stat'] => 'uid_t' );
81             $ffi->attach( gid => ['stat'] => 'gid_t' );
82             $ffi->attach( rdev => ['stat'] => 'dev_t' );
83             $ffi->attach( size => ['stat'] => 'off_t' );
84             $ffi->attach( atime => ['stat'] => 'time_t' );
85             $ffi->attach( mtime => ['stat'] => 'time_t' );
86             $ffi->attach( ctime => ['stat'] => 'time_t' );
87              
88             if($^O ne 'MSWin32')
89             {
90             $ffi->attach( blksize => ['stat'] => 'blksize_t' );
91             $ffi->attach( blocks => ['stat'] => 'blkcnt_t' );
92             }
93             else
94             {
95             *blksize = sub { '' };
96             *blocks = sub { '' };
97             }
98              
99             1;
100              
101             __END__