File Coverage

lib/Rex/Interface/Fs/Sudo.pm
Criterion Covered Total %
statement 23 147 15.6
branch 0 30 0.0
condition 0 6 0.0
subroutine 8 29 27.5
pod 0 14 0.0
total 31 226 13.7


line stmt bran cond sub pod time code
1             #
2             # (c) Jan Gehring
3             #
4              
5             package Rex::Interface::Fs::Sudo;
6              
7 1     1   21 use v5.12.5;
  1         9  
8 1     1   12 use warnings;
  1         2  
  1         52  
9              
10             our $VERSION = '1.14.3'; # VERSION
11              
12             require Rex::Commands;
13 1     1   7 use Rex::Interface::Fs::Base;
  1         2  
  1         14  
14 1     1   36 use Rex::Helper::Path;
  1         9  
  1         68  
15 1     1   7 use Rex::Helper::Encode;
  1         2  
  1         70  
16 1     1   8 use JSON::MaybeXS;
  1         2  
  1         102  
17 1     1   7 use base qw(Rex::Interface::Fs::Base);
  1         6  
  1         70  
18 1     1   6 use Data::Dumper;
  1         2  
  1         1839  
19              
20             sub new {
21 0     0 0   my $that = shift;
22 0   0       my $proto = ref($that) || $that;
23 0           my $self = $proto->SUPER::new(@_);
24              
25 0           bless( $self, $proto );
26              
27 0           return $self;
28             }
29              
30             sub ls {
31 0     0 0   my ( $self, $path ) = @_;
32              
33 0           my @ret;
34              
35 0           my @out = split(
36             /\n/,
37             $self->_exec(
38             "ls -a1 $path", undef, { env => { QUOTING_STYLE => "literal" } }
39             )
40             );
41              
42             # failed open directory, return undef
43 0 0         if ( $? != 0 ) { return; }
  0            
44              
45 0           @ret = grep { !m/^\.\.?$/ } @out;
  0            
46              
47             # return directory content
48 0           return @ret;
49             }
50              
51             sub upload {
52 0     0 0   my ( $self, $source, $target ) = @_;
53              
54 0           my $rnd_file = get_tmp_file;
55              
56 0 0         if ( my $ssh = Rex::is_ssh() ) {
57 0 0         if ( ref $ssh eq "Net::OpenSSH" ) {
58 0           $ssh->sftp->put( $source, $rnd_file );
59             }
60             else {
61 0           $ssh->scp_put( $source, $rnd_file );
62             }
63 0           $self->_exec("mv $rnd_file '$target'");
64             }
65             else {
66 0           $self->cp( $source, $target );
67             }
68              
69             }
70              
71             sub download {
72 0     0 0   my ( $self, $source, $target ) = @_;
73              
74 0           my $rnd_file = get_tmp_file;
75              
76 0 0         if ( my $ssh = Rex::is_ssh() ) {
77 0           $self->_exec("cp '$source' $rnd_file");
78 0           $self->chmod( 444, $rnd_file );
79 0 0         if ( ref $ssh eq "Net::OpenSSH" ) {
80 0           $ssh->sftp->get( $rnd_file, $target );
81             }
82             else {
83 0           $ssh->scp_get( $rnd_file, $target );
84             }
85             Rex::get_current_connection_object()->run_sudo_unmodified(
86             sub {
87 0     0     $self->unlink($rnd_file);
88             }
89 0           );
90             }
91             else {
92 0           $self->cp( $source, $target );
93             }
94              
95             }
96              
97             sub is_dir {
98 0     0 0   my ( $self, $path ) = @_;
99              
100 0           ($path) = $self->_normalize_path($path);
101              
102 0           $self->_exec("test -d $path");
103 0           my $ret = $?;
104              
105 0 0         $ret == 0 ? return 1 : return undef;
106             }
107              
108             sub is_file {
109 0     0 0   my ( $self, $file ) = @_;
110              
111 0           ($file) = $self->_normalize_path($file);
112              
113 0           $self->_exec("test -e $file");
114 0           my $is_file = $?;
115              
116 0           $self->_exec("test -d $file");
117 0           my $is_dir = $?;
118              
119 0 0 0       ( $is_file == 0 && $is_dir != 0 ) ? return 1 : return undef;
120             }
121              
122             sub unlink {
123 0     0 0   my ( $self, @files ) = @_;
124 0           (@files) = $self->_normalize_path(@files);
125              
126 0           $self->_exec( "rm " . join( " ", @files ) );
127 0 0         if ( $? == 0 ) { return 1; }
  0            
128             }
129              
130             sub mkdir {
131 0     0 0   my ( $self, $dir ) = @_;
132 0           ($dir) = $self->_normalize_path($dir);
133 0           $self->_exec("mkdir $dir >/dev/null 2>&1");
134 0 0         if ( $? == 0 ) { return 1; }
  0            
135             }
136              
137             sub stat {
138 0     0 0   my ( $self, $file ) = @_;
139              
140 0           my $script = q|
141             unlink $0;
142              
143             if(my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size,
144             $atime, $mtime, $ctime, $blksize, $blocks) = stat($ARGV[0])) {
145              
146             my %ret;
147              
148             $ret{'mode'} = sprintf("%04o", $mode & 07777);
149             $ret{'size'} = $size;
150             $ret{'uid'} = $uid;
151             $ret{'gid'} = $gid;
152             $ret{'atime'} = $atime;
153             $ret{'mtime'} = $mtime;
154              
155             print to_json(\%ret);
156             }
157              
158             |;
159              
160 0           $script .= func_to_json();
161              
162 0           my $rnd_file = $self->_write_to_rnd_file($script);
163 0           ($file) = $self->_normalize_path($file);
164 0           my $out = $self->_exec("perl $rnd_file $file");
165              
166             Rex::get_current_connection_object()->run_sudo_unmodified(
167             sub {
168 0     0     $self->unlink($rnd_file);
169             }
170 0           );
171              
172 0 0         if ( !$out ) {
173 0           return undef;
174             }
175              
176 0           my $tmp = decode_json($out);
177              
178 0           return %{$tmp};
  0            
179             }
180              
181             sub is_readable {
182 0     0 0   my ( $self, $file ) = @_;
183              
184 0           ($file) = $self->_normalize_path($file);
185 0           $self->_exec("test -r $file");
186              
187 0 0         if ( $? == 0 ) { return 1; }
  0            
188             }
189              
190             sub is_writable {
191 0     0 0   my ( $self, $file ) = @_;
192              
193 0           ($file) = $self->_normalize_path($file);
194 0           $self->_exec("test -w $file");
195              
196 0 0         if ( $? == 0 ) { return 1; }
  0            
197             }
198              
199             sub readlink {
200 0     0 0   my ( $self, $file ) = @_;
201 0           my $script = q|unlink $0; print readlink($ARGV[0]) . "\n"; |;
202 0           ($file) = $self->_normalize_path($file);
203              
204 0           my $rnd_file = $self->_write_to_rnd_file($script);
205 0           my $out = $self->_exec("perl $rnd_file $file");
206 0           my $ret = $?;
207 0           chomp $out;
208             Rex::get_current_connection_object()->run_sudo_unmodified(
209             sub {
210 0     0     $self->unlink($rnd_file);
211             }
212 0           );
213 0           $? = $ret;
214              
215 0           return $out;
216             }
217              
218             sub rename {
219 0     0 0   my ( $self, $old, $new ) = @_;
220 0           ($old) = $self->_normalize_path($old);
221 0           ($new) = $self->_normalize_path($new);
222              
223 0           $self->_exec("mv $old $new");
224              
225 0 0         if ( $? == 0 ) { return 1; }
  0            
226             }
227              
228             sub glob {
229 0     0 0   my ( $self, $glob ) = @_;
230              
231 0           my $script = q|
232             unlink $0;
233             print to_json([ glob("| . $glob . q|") ]);
234             |;
235              
236 0           $script .= func_to_json();
237              
238 0           my $rnd_file = $self->_write_to_rnd_file($script);
239 0           my $content = $self->_exec("perl $rnd_file");
240 0           my $ret = $?;
241             Rex::get_current_connection_object()->run_sudo_unmodified(
242             sub {
243 0     0     $self->unlink($rnd_file);
244             }
245 0           );
246 0           $? = $ret;
247              
248 0           my $tmp = decode_json($content);
249              
250 0           return @{$tmp};
  0            
251             }
252              
253             sub _get_file_writer {
254 0     0     my ($self) = @_;
255              
256 0           my $fh;
257 0 0         if ( my $o = Rex::is_ssh() ) {
258 0 0         if ( ref $o eq "Net::OpenSSH" ) {
259 0           $fh = Rex::Interface::File->create("OpenSSH");
260             }
261             else {
262 0           $fh = Rex::Interface::File->create("SSH");
263             }
264             }
265             else {
266 0           $fh = Rex::Interface::File->create("Local");
267             }
268              
269 0           return $fh;
270             }
271              
272             sub _write_to_rnd_file {
273 0     0     my ( $self, $content ) = @_;
274 0           my $fh = $self->_get_file_writer();
275 0           my $rnd_file = get_tmp_file;
276              
277 0           $fh->open( ">", $rnd_file );
278 0           $fh->write($content);
279 0           $fh->close;
280              
281 0           return $rnd_file;
282             }
283              
284             sub _exec {
285 0     0     my ( $self, $cmd, $path, $option ) = @_;
286 0           my $exec = Rex::Interface::Exec->create("Sudo");
287 0           return $exec->exec( $cmd, $path, $option );
288             }
289              
290             1;