File Coverage

blib/lib/Filesys/POSIX/ReducedPrivileges/Directory.pm
Criterion Covered Total %
statement 43 54 79.6
branch 8 16 50.0
condition 2 9 22.2
subroutine 11 14 78.5
pod 0 1 0.0
total 64 94 68.0


line stmt bran cond sub pod time code
1             package Filesys::POSIX::ReducedPrivileges::Directory;
2              
3             # Copyright (c) 2016, cPanel, Inc.
4             # All rights reserved.
5             # http://cpanel.net/
6             #
7             # This is free software; you can redistribute it and/or modify it under the same
8             # terms as Perl itself. See the LICENSE file for further details.
9              
10 1     1   3 use strict;
  1         1  
  1         20  
11 1     1   3 use warnings;
  1         1  
  1         16  
12              
13 1     1   314 use Filesys::POSIX::Real::Directory ();
  1         2  
  1         14  
14 1     1   5 use Carp ();
  1         2  
  1         11  
15 1     1   412 use Try::Tiny;
  1         991  
  1         296  
16              
17             our @ISA = qw(Filesys::POSIX::Real::Directory);
18             our $AUTOLOAD;
19              
20             sub new {
21 0     0 0 0 my ( $class, $path, $inode ) = @_;
22 0 0 0     0 unless ( defined $inode->{dev} && ref $inode->{dev} && $inode->{dev}->isa('Filesys::POSIX::ReducedPrivileges') ) {
      0        
23 0         0 Carp::confess("invalid filesystem device");
24             }
25              
26 0         0 return $class->SUPER::new( $path, $inode );
27             }
28              
29             sub _sync_member {
30 6     6   5 my ( $self, $name ) = @_;
31 6         17 $self->{inode}{dev}->enter_filesystem();
32             try {
33 6     6   128 my $subpath = "$self->{'path'}/$name";
34 6         80 my @st = lstat $subpath;
35              
36 6 100 66     27 if ( scalar @st == 0 && $!{'ENOENT'} ) {
37 1         17 delete $self->{'members'}->{$name};
38             }
39             else {
40              
41 5 50       9 Carp::confess($!) unless @st;
42              
43 5 50       7 if ( exists $self->{'members'}->{$name} ) {
44 0         0 $self->{'members'}->{$name}->update(@st);
45             }
46             else {
47             $self->{'members'}->{$name} = Filesys::POSIX::ReducedPrivileges::Inode->from_disk(
48             $subpath,
49             'st_info' => \@st,
50             'dev' => $self->{'inode'}->{'dev'},
51 5         18 'parent' => $self->{'inode'}
52             );
53             }
54             }
55             }
56             catch {
57 0     0   0 $self->{inode}{dev}->exit_filesystem();
58 0         0 die $_;
59 6         36 };
60 6         68 $self->{inode}{dev}->exit_filesystem();
61 6         9 return;
62             }
63              
64             # Wrap all of the normal Inode methods with privilege dropping and restoring.
65             BEGIN {
66 1     1   2 foreach my $method (qw(_sync_all rename_member delete open rewind read close)) {
67 7         7 my $super_method = "SUPER::$method";
68 1     1   4 no strict 'refs';
  1         1  
  1         149  
69 7         44 *{ __PACKAGE__ . "::$method" } = sub {
70 1     1   7 my ( $self, @args ) = @_;
71 1         3 $self->{inode}{dev}->enter_filesystem();
72 1         2 my $context = wantarray();
73 1         1 my @result;
74             try {
75 1 50   1   22 if ($context) {
    50          
76 0         0 @result = $self->$super_method(@args);
77             }
78             elsif ( defined $context ) {
79 0         0 @result = ( scalar $self->$super_method(@args) );
80             }
81             else {
82 1         7 $self->$super_method(@args);
83             }
84             }
85             catch {
86 0     0   0 $self->{inode}{dev}->exit_filesystem();
87 0         0 die $_;
88 1         7 };
89 1         13 $self->{inode}{dev}->exit_filesystem();
90 1 50       5 return $context ? @result : defined $context ? $result[0] : ();
    50          
91 7         22 };
92             }
93             }
94              
95             1;