File Coverage

blib/lib/Csistck/Test/FileBase.pm
Criterion Covered Total %
statement 77 122 63.1
branch 13 42 30.9
condition 2 12 16.6
subroutine 24 31 77.4
pod 0 19 0.0
total 116 226 51.3


line stmt bran cond sub pod time code
1             package Csistck::Test::FileBase;
2              
3 17     17   326 use 5.010;
  17         55  
  17         727  
4 17     17   91 use strict;
  17         31  
  17         529  
5 17     17   88 use warnings;
  17         31  
  17         447  
6              
7 17     17   120 use base 'Csistck::Test';
  17         27  
  17         1480  
8 17     17   92 use Csistck::Oper qw/debug/;
  17         35  
  17         1109  
9 17     17   18658 use Csistck::Util qw/backup_file hash_file hash_string/;
  17         78  
  17         1275  
10              
11 17     17   116 use Digest::MD5;
  17         98  
  17         775  
12 17     17   97 use File::Basename;
  17         30  
  17         9525  
13 17     17   266 use File::Copy;
  17         137  
  17         1320  
14 17     17   97 use FindBin;
  17         32  
  17         8296  
15 17     17   20457 use File::stat;
  17         215348  
  17         135  
16 17     17   20302 use Sys::Hostname::Long qw//;
  17         81083  
  17         27100  
17              
18 0     0 0 0 sub desc { sprintf("File check on %s", shift->{target}); }
19 47     47 0 661 sub dest { shift->{target}; }
20 14     14 0 80 sub src { shift->{src}; }
21 42     42 0 101 sub mode { shift->{mode}; }
22 14     14 0 56 sub uid { shift->{uid}; }
23 14     14 0 54 sub gid { shift->{gid}; }
24              
25             sub check {
26 11     11 0 4359 my $self = shift;
27 11         19 my $ret = 1;
28              
29 11 50       50 die("Destination path not found")
30             if (! -e $self->dest);
31            
32             # If we defined a source file
33 11 50 33     47 if (defined($self->src) and $self->can('file_check')) {
34 0         0 $ret &= $self->file_check;
35             }
36 11         62 $ret &= $self->mode_process(\&mode_check);
37 11         62 $ret &= $self->uid_process(\&uid_check);
38 11         108 $ret &= $self->gid_process(\&gid_check);
39              
40 11 100       68 return (($ret == 1) ? $self->pass('File matches') :
41             $self->fail("File doesn't match"));
42             }
43              
44             sub repair {
45 3     3 0 7 my $self = shift;
46 3         8 my $ret = 1;
47              
48             # If we defined a source file
49 3 50 33     13 if (defined($self->src) and $self->can('file_repair')) {
50 0 0       0 if (-e $self->dest) {
51 0 0       0 die("Destination ${\$self->dest} is not a file")
  0         0  
52             if (-d $self->dest);
53 0 0 0     0 die("Destination ${\$self->dest} exists is is not writable")
  0         0  
54             if (-f $self->dest and ! -w $self->dest);
55 0         0 backup_file($self->dest);
56             }
57            
58 0         0 $ret &= $self->file_repair;
59             }
60 3         15 $ret &= $self->mode_process(\&mode_repair);
61 3         18 $ret &= $self->uid_process(\&uid_repair);
62 3         15 $ret &= $self->gid_process(\&gid_repair);
63            
64 3 50       40 return (($ret == 1) ? $self->pass('File repaired') :
65             $self->fail('File not repaired'));
66             }
67              
68             # Diff for files
69             sub diff {
70 0     0 0 0 my $self = shift;
71            
72 0 0       0 die("Destination file does not exist: dest=<${\$self->dest}>")
  0         0  
73             unless (-f -e -r $self->dest);
74            
75             # If we defined a source file
76 0 0 0     0 if (defined($self->src) and $self->can('file_diff')) {
77 0         0 $self->file_diff();
78             }
79              
80             # TODO mode, uid, gid diff functions
81             }
82              
83             # Wrapper functions to perform sanity tests on arguments
84             # Return pass if arguments are missing, die if invalid
85             sub mode_process {
86 14     14 0 25 my ($self, $func) = @_;
87              
88 14 50       63 return 1 unless($self->mode);
89 14         37 my $mode = $self->mode;
90 14 50       66 die("Invalid file mode")
91             if ($mode !~ m/^[0-7]{3,4}$/);
92 14         37 $mode =~ s/^([0-7]{3})$/0$1/;
93 14         27 $self->{mode} = $mode;
94            
95 14         35 &{$func}($self->dest, $self->mode);
  14         40  
96             }
97              
98             sub uid_process {
99 14     14 0 30 my ($self, $func) = @_;
100              
101 14 50       53 return 1 unless ($self->uid);
102 0 0       0 die("Invalid user id")
103             if ($self->uid !~ m/^[0-9]+$/);
104            
105 0         0 &{$func}($self->dest, $self->uid);
  0         0  
106             }
107              
108             sub gid_process {
109 14     14 0 29 my ($self, $func) = @_;
110              
111 14 50       55 return 1 unless ($self->gid);
112 0 0       0 die("Invalid group id")
113             if ($self->gid !~ m/^[0-9]+$/);
114              
115 0         0 &{$func}($self->dest, $self->gid);
  0         0  
116             }
117              
118             # Mode operations
119             sub mode_check {
120 11     11 0 34 my ($file, $mode) = @_;
121 11         47 my $fh = stat($file);
122 11 50       1855 if ($fh) {
123 11         256 my $curmode = sprintf "%04o", $fh->mode & 07777;
124 11         140 debug("File mode: file=<$file> mode=<$curmode>");
125 11 100       110 return 1 if ($curmode eq $mode);
126             }
127             }
128              
129             sub mode_repair {
130 3     3 0 8 my ($file, $mode) = @_;
131 3         22 debug("Chmod file: file=<$file> mode=<$mode>");
132 3         160 chmod(oct($mode), $file);
133             }
134              
135             # UID operations
136             sub uid_check {
137 0     0 0   my ($file, $uid) = @_;
138 0           my $fh = stat($file);
139 0           my $curuid = undef;
140 0 0         if ($fh) {
141 0           my $curuid = $fh->uid;
142 0           debug("File owner: file=<$file> uid=<$uid>");
143             }
144 0           return ($curuid == $uid);
145             }
146              
147             sub uid_repair {
148 0     0 0   my ($file, $uid) = @_;
149 0           debug("Chown file: file=<$file> uid=<$uid>");
150 0           chown($uid, -1, $file);
151             }
152              
153             # GID operations
154             sub gid_check {
155 0     0 0   my ($file, $gid) = @_;
156 0           my $fh = stat($file);
157 0           my $curgid = undef;
158 0 0         if ($fh) {
159 0           $curgid = $fh->gid;
160 0           debug("File group: file=<$file> gid=<$gid>");
161             }
162 0           return ($curgid == $gid);
163             }
164              
165             sub gid_repair {
166 0     0 0   my ($file, $gid) = @_;
167 0           debug("Chown file: file=<$file> gid=<$gid>");
168 0           chown(-1, $gid, $file);
169             }
170              
171             # Compare hashes between two files
172             sub file_compare {
173 0     0 0   my @files = @_;
174 0 0         return 0 unless (scalar @files == 2);
175            
176             # Get hashes and return compare
177 0           my ($hasha, $hashb) = map hash_file($_), @files;
178 0           debug(sprintf "File compare result: ", $hasha, $hashb);
179 0           return ($hasha eq $hashb);
180             }
181              
182             1;