1#
2# (c) Jan Gehring <jan.gehring@gmail.com>
3#
4# vim: set ts=2 sw=2 tw=0:
5# vim: set expandtab:
6
7package Rex::Interface::Fs::Base;
8
9use 5.010001;
10use strict;
11use warnings;
12
13our $VERSION = '1.13.4'; # VERSION
14
15use English qw(-no_match_vars);
16use Rex::Interface::Exec;
17use Rex::Helper::File::Spec;
18
19sub new {
20  my $that  = shift;
21  my $proto = ref($that) || $that;
22  my $self  = {@_};
23
24  bless( $self, $proto );
25
26  return $self;
27}
28
29sub ls          { die("Must be implemented by Interface Class"); }
30sub unlink      { die("Must be implemented by Interface Class"); }
31sub mkdir       { die("Must be implemented by Interface Class"); }
32sub glob        { die("Must be implemented by Interface Class"); }
33sub rename      { die("Must be implemented by Interface Class"); }
34sub stat        { die("Must be implemented by Interface Class"); }
35sub readlink    { die("Must be implemented by Interface Class"); }
36sub is_file     { die("Must be implemented by Interface Class"); }
37sub is_dir      { die("Must be implemented by Interface Class"); }
38sub is_readable { die("Must be implemented by Interface Class"); }
39sub is_writable { die("Must be implemented by Interface Class"); }
40sub upload      { die("Must be implemented by Interface Class"); }
41sub download    { die("Must be implemented by Interface Class"); }
42
43sub is_symlink {
44  my ( $self, $path ) = @_;
45  ($path) = $self->_normalize_path($path);
46
47  $self->_exec("/bin/sh -c '[ -L \"$path\" ]'");
48  my $ret = $?;
49
50  if ( $ret == 0 ) { return 1; }
51}
52
53sub ln {
54  my ( $self, $from, $to ) = @_;
55
56  Rex::Logger::debug("Symlinking files: $to -> $from");
57  ($from) = $self->_normalize_path($from);
58  ($to)   = $self->_normalize_path($to);
59
60  my $exec = Rex::Interface::Exec->create;
61  $exec->exec("ln -snf $from $to");
62
63  if ( $? == 0 ) { return 1; }
64
65  die "Error creating symlink. ($from -> $to)" if ( Rex::Config->get_autodie );
66}
67
68sub rmdir {
69  my ( $self, @dirs ) = @_;
70
71  @dirs = $self->_normalize_path(@dirs);
72
73  Rex::Logger::debug( "Removing directories: " . join( ", ", @dirs ) );
74  my $exec = Rex::Interface::Exec->create;
75  $exec->exec( "/bin/rm -rf " . join( " ", @dirs ) );
76
77  if ( $? == 0 ) { return 1; }
78
79  die( "Error removing directory: " . join( ", ", @dirs ) )
80    if ( Rex::Config->get_autodie );
81}
82
83sub chown {
84  my ( $self, $user, $file, @opts ) = @_;
85  my $options = {@opts};
86  ($file) = $self->_normalize_path($file);
87
88  my $recursive = "";
89  if ( exists $options->{"recursive"} && $options->{"recursive"} == 1 ) {
90    $recursive = " -R ";
91  }
92
93  my $exec = Rex::Interface::Exec->create;
94
95  if ( $exec->can_run( ['chown'] ) ) {
96    $exec->exec("chown $recursive $user $file");
97
98    if ( $? == 0 ) { return 1; }
99
100    die("Error running chown $recursive $user $file")
101      if ( Rex::Config->get_autodie );
102  }
103  else {
104    Rex::Logger::debug("Can't find `chown`.");
105    return 1; # fake success for windows
106  }
107}
108
109sub chgrp {
110  my ( $self, $group, $file, @opts ) = @_;
111  my $options = {@opts};
112  ($file) = $self->_normalize_path($file);
113
114  my $recursive = "";
115  if ( exists $options->{"recursive"} && $options->{"recursive"} == 1 ) {
116    $recursive = " -R ";
117  }
118
119  my $exec = Rex::Interface::Exec->create;
120
121  if ( $exec->can_run( ['chgrp'] ) ) {
122    $exec->exec("chgrp $recursive $group $file");
123
124    if ( $? == 0 ) { return 1; }
125
126    die("Error running chgrp $recursive $group $file")
127      if ( Rex::Config->get_autodie );
128  }
129  else {
130    Rex::Logger::debug("Can't find `chgrp`.");
131    return 1; # fake success for windows
132  }
133}
134
135sub chmod {
136  my ( $self, $mode, $file, @opts ) = @_;
137  my $options = {@opts};
138  ($file) = $self->_normalize_path($file);
139
140  my $recursive = "";
141  if ( exists $options->{"recursive"} && $options->{"recursive"} == 1 ) {
142    $recursive = " -R ";
143  }
144
145  my $exec = Rex::Interface::Exec->create;
146
147  if ( $exec->can_run( ['chmod'] ) ) {
148    $exec->exec("chmod $recursive $mode $file");
149
150    if ( $? == 0 ) { return 1; }
151
152    die("Error running chmod $recursive $mode $file")
153      if ( Rex::Config->get_autodie );
154  }
155  else {
156    Rex::Logger::debug("Can't find `chmod`.");
157    return 1; # fake success for windows
158  }
159}
160
161sub cp {
162  my ( $self, $source, $dest ) = @_;
163  ($source) = $self->_normalize_path($source);
164  ($dest)   = $self->_normalize_path($dest);
165
166  my $exec = Rex::Interface::Exec->create;
167
168  if ( $OSNAME =~ m/^MSWin/msx ) {
169    $exec->exec("copy /v /y $source $dest");
170  }
171  else {
172    $exec->exec("cp -R $source $dest");
173  }
174
175  if ( $? == 0 ) { return 1; }
176
177  die("Error copying $source -> $dest") if ( Rex::Config->get_autodie );
178}
179
180sub _normalize_path {
181  my ( $self, @dirs ) = @_;
182
183  my @ret;
184  for my $d (@dirs) {
185    my @t;
186    if (Rex::is_ssh) {
187      @t = Rex::Helper::File::Spec->splitdir($d);
188    }
189    else {
190      @t = Rex::Helper::File::Spec->splitdir($d);
191    }
192    push( @ret,
193      Rex::Helper::File::Spec->catfile( map { $self->_quotepath($_) } @t ) );
194  }
195
196  #  for (@dirs) {
197  #    s/ /\\ /g;
198  #  }
199
200  return @ret;
201}
202
203sub _quotepath {
204  my ( $self, $p ) = @_;
205  $p =~ s/([\@\$\% ])/\\$1/g;
206
207  return $p;
208}
209
210sub _exec {
211  my ( $self, $cmd ) = @_;
212  my $exec = Rex::Interface::Exec->create;
213  return $exec->exec($cmd);
214}
215
2161;
217