File Coverage

blib/lib/Filesys/POSIX/ReducedPrivileges/Inode.pm
Criterion Covered Total %
statement 52 69 75.3
branch 4 14 28.5
condition 4 12 33.3
subroutine 16 20 80.0
pod 0 2 0.0
total 76 117 64.9


line stmt bran cond sub pod time code
1             package Filesys::POSIX::ReducedPrivileges::Inode;
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         22  
11 1     1   3 use warnings;
  1         0  
  1         17  
12              
13 1     1   338 use Filesys::POSIX::ReducedPrivileges::Directory ();
  1         2  
  1         14  
14 1     1   341 use Filesys::POSIX::Real::Inode ();
  1         2  
  1         15  
15 1     1   4 use Filesys::POSIX::Mem::Inode ();
  1         1  
  1         11  
16 1     1   3 use Filesys::POSIX::Bits;
  1         1  
  1         257  
17 1     1   5 use Filesys::POSIX::Bits::System;
  1         1  
  1         17  
18 1     1   3 use Filesys::POSIX::Error qw(throw);
  1         1  
  1         29  
19 1     1   3 use Carp ();
  1         1  
  1         11  
20              
21 1     1   3 use Fcntl qw(:DEFAULT :mode);
  1         1  
  1         338  
22 1     1   4 use Try::Tiny;
  1         1  
  1         273  
23              
24             our @ISA = qw(Filesys::POSIX::Real::Inode);
25             our $AUTOLOAD;
26              
27             sub new {
28 7     7 0 12 my ( $class, $path, %opts ) = @_;
29 7 50 33     43 unless ( defined $opts{dev} && ref $opts{dev} && $opts{dev}->isa('Filesys::POSIX::ReducedPrivileges') ) {
      33        
30 0         0 Carp::confess("invalid filesystem device");
31             }
32              
33             # No need to enter the ReducedContext for new. No file operations are performed.
34             # Typically new() is called by from_disk() anyway
35 7         20 return $class->SUPER::new( $path, %opts );
36             }
37              
38             sub from_disk {
39 7     7 0 15 my ( $class, $path, %opts ) = @_;
40 7 50 33     54 unless ( defined $opts{dev} && ref $opts{dev} && $opts{dev}->isa('Filesys::POSIX::ReducedPrivileges') ) {
      33        
41 0         0 Carp::confess("invalid filesystem device");
42             }
43              
44 7         5 my $self;
45 7         16 $opts{dev}->enter_filesystem();
46             try {
47 7     7   155 $self = $class->SUPER::from_disk( $path, %opts );
48             }
49             catch {
50 0     0   0 $opts{dev}->exit_filesystem();
51 0         0 die $_;
52 7         38 };
53              
54 7         82 $opts{dev}->exit_filesystem();
55              
56             # Fix the class of the directory object
57 7 100       16 bless $self->{directory}, 'Filesys::POSIX::ReducedPrivileges::Directory' if ( ref $self->{directory} );
58              
59 7         19 return $self;
60             }
61              
62             # Wrap the normal Inode methods that do actual filesystem activity with privilege dropping and restoring.
63             BEGIN {
64 1     1   2 foreach my $method (qw(open chown chmod readlink symlink child)) {
65 6         6 my $super_method = "SUPER::$method";
66 1     1   4 no strict 'refs';
  1         1  
  1         142  
67 6         36 *{ __PACKAGE__ . "::$method" } = sub {
68 0     0   0 my ( $self, @args ) = @_;
69 0         0 $self->{dev}->enter_filesystem();
70 0         0 my $context = wantarray();
71 0         0 my @result;
72             try {
73 0 0   0   0 if ($context) {
    0          
74 0         0 @result = $self->$super_method(@args);
75             }
76             elsif ( defined $context ) {
77 0         0 @result = ( scalar $self->$super_method(@args) );
78             }
79             else {
80 0         0 $self->$super_method(@args);
81             }
82             }
83             catch {
84 0     0   0 $self->{dev}->exit_filesystem();
85 0         0 die $_;
86 0         0 };
87 0         0 $self->{dev}->exit_filesystem();
88 0 0       0 return $context ? @result : defined $context ? $result[0] : ();
    0          
89 6         20 };
90             }
91             }
92              
93             1;