File Coverage

blib/lib/DateTimeX/Lite/TimeZone/Local/Unix.pm
Criterion Covered Total %
statement 14 105 13.3
branch 0 50 0.0
condition 0 36 0.0
subroutine 6 15 40.0
pod 2 7 28.5
total 22 213 10.3


line stmt bran cond sub pod time code
1             package DateTimeX::Lite::TimeZone::Local::Unix;
2              
3 1     1   1388 use strict;
  1         2  
  1         50  
4 1     1   6 use warnings;
  1         3  
  1         35  
5              
6 1     1   6 use base 'DateTimeX::Lite::TimeZone::Local';
  1         3  
  1         1494  
7              
8              
9             sub Methods
10             {
11 539     539 1 2131 return qw( FromEnv
12             FromEtcLocaltime
13             FromEtcTimezone
14             FromEtcTIMEZONE
15             FromEtcSysconfigClock
16             FromEtcDefaultInit
17             );
18             }
19              
20 543     543 1 1426 sub EnvVars { return 'TZ' }
21              
22             sub FromEtcLocaltime
23             {
24 0     0 0 0 my $class = shift;
25              
26 0         0 my $lt_file = '/etc/localtime';
27              
28 0 0 0     0 return unless -r $lt_file && -s _;
29              
30 0         0 my $real_name;
31 0 0       0 if ( -l $lt_file )
32             {
33             # The _Readlink sub exists so the test suite can mock it.
34 0         0 $real_name = $class->_Readlink( $lt_file );
35             }
36              
37 0   0     0 $real_name ||= $class->_FindMatchingZoneinfoFile( $lt_file );
38              
39 0 0       0 if ( defined $real_name )
40             {
41 0         0 my ( $vol, $dirs, $file ) = File::Spec->splitpath( $real_name );
42              
43 0 0       0 my @parts =
44 0         0 grep { defined && length } File::Spec->splitdir( $dirs ), $file;
45              
46 0         0 foreach my $x ( reverse 0..$#parts )
47             {
48 0 0       0 my $name =
49             ( $x < $#parts ?
50             join '/', @parts[$x..$#parts] :
51             $parts[$x]
52             );
53              
54 0         0 my $tz;
55             {
56 0         0 local $@;
  0         0  
57 0         0 $tz = eval { DateTimeX::Lite::TimeZone->load( name => $name ) };
  0         0  
58             }
59              
60 0 0       0 return $tz if $tz;
61             }
62             }
63             }
64              
65             sub _Readlink
66             {
67 1     1   42585 my $link = $_[1];
68              
69 1         14 require Cwd;
70             # Using abs_path will resolve multiple levels of link indirection,
71             # whereas readlink just follows the link to the next target.
72 1         276 return Cwd::abs_path($link);
73             }
74              
75             # for systems where /etc/localtime is a copy of a zoneinfo file
76             sub _FindMatchingZoneinfoFile
77             {
78 0     0     my $class = shift;
79 0           my $file_to_match = shift;
80              
81 0 0         return unless -d '/usr/share/zoneinfo';
82              
83 0           require File::Basename;
84 0           require File::Compare;
85 0           require File::Find;
86              
87 0           my $size = -s $file_to_match;
88              
89 0           my $real_name;
90 0           local $@;
91 0           local $_;
92             eval
93 0           {
94 0           local $SIG{__DIE__};
95             File::Find::find
96             ( { wanted =>
97             sub
98             {
99 0 0 0 0     if ( ! defined $real_name
      0        
      0        
      0        
      0        
100             && -f $_
101             && ! -l $_
102             && $size == -s _
103             # This fixes RT 24026 - apparently such a
104             # file exists on FreeBSD and it can cause a
105             # false positive
106             && File::Basename::basename($_) ne 'posixrules'
107             && File::Compare::compare( $_, $file_to_match ) == 0
108             )
109             {
110 0           $real_name = $_;
111              
112             # File::Find has no mechanism for bailing in the
113             # middle of a find.
114 0           die { found => 1 };
115             }
116             },
117 0           no_chdir => 1,
118             },
119             '/usr/share/zoneinfo',
120             );
121             };
122              
123 0 0         if ($@)
124             {
125 0 0 0       return $real_name if ref $@ && $@->{found};
126 0           die $@;
127             }
128             }
129              
130             sub FromEtcTimezone
131             {
132 0     0 0   my $class = shift;
133              
134 0           my $tz_file = '/etc/timezone';
135              
136 0 0 0       return unless -f $tz_file && -r _;
137              
138 0           local *TZ;
139 0 0         open TZ, "<$tz_file"
140             or die "Cannot read $tz_file: $!";
141 0           my $name = join '', ;
142 0           close TZ;
143              
144 0           $name =~ s/^\s+|\s+$//g;
145              
146 0 0         return unless $class->_IsValidName($name);
147              
148 0           local $@;
149 0           return eval { DateTimeX::Lite::TimeZone->load( name => $name ) };
  0            
150             }
151              
152             sub FromEtcTIMEZONE
153             {
154 0     0 0   my $class = shift;
155              
156 0           my $tz_file = '/etc/TIMEZONE';
157              
158 0 0 0       return unless -f $tz_file && -r _;
159              
160 0           local *TZ;
161 0 0         open TZ, "<$tz_file"
162             or die "Cannot read $tz_file: $!";
163              
164 0           my $name;
165 0           while ( defined( $name = ) )
166             {
167 0 0         if ( $name =~ /\A\s*TZ\s*=\s*(\S+)/ )
168             {
169 0           $name = $1;
170 0           last;
171             }
172             }
173              
174 0           close TZ;
175              
176 0 0         return unless $class->_IsValidName($name);
177              
178 0           local $@;
179 0           return eval { DateTimeX::Lite::TimeZone->load( name => $name ) };
  0            
180             }
181              
182             # RedHat uses this
183             sub FromEtcSysconfigClock
184             {
185 0     0 0   my $class = shift;
186              
187 0 0 0       return unless -r "/etc/sysconfig/clock" && -f _;
188              
189 0           my $name = $class->_ReadEtcSysconfigClock();
190              
191 0 0         return unless $class->_IsValidName($name);
192              
193 0           local $@;
194 0           return eval { DateTimeX::Lite::TimeZone->load( name => $name ) };
  0            
195             }
196              
197             # this is a sparate function so that it can be overridden in the test
198             # suite
199             sub _ReadEtcSysconfigClock
200             {
201 0     0     my $class = shift;
202              
203 0           local *CLOCK;
204 0 0         open CLOCK, '
205             or die "Cannot read /etc/sysconfig/clock: $!";
206              
207 0           local $_;
208 0           while ()
209             {
210 0 0         return $1 if /^(?:TIME)?ZONE="([^"]+)"/;
211             }
212             }
213              
214             sub FromEtcDefaultInit
215             {
216 0     0 0   my $class = shift;
217              
218 0 0 0       return unless -r "/etc/default/init" && -f _;
219              
220 0           my $name = $class->_ReadEtcDefaultInit();
221              
222 0 0         return unless $class->_IsValidName($name);
223              
224 0           local $@;
225 0           return eval { DateTimeX::Lite::TimeZone->load( name => $name ) };
  0            
226             }
227              
228             # this is a separate function so that it can be overridden in the test
229             # suite
230             sub _ReadEtcDefaultInit
231             {
232 0     0     my $class = shift;
233              
234 0           local *INIT;
235 0 0         open INIT, '
236             or die "Cannot read /etc/default/init: $!";
237              
238 0           local $_;
239 0           while ()
240             {
241 0 0         return $1 if /^TZ=(.+)/;
242             }
243             }
244              
245              
246             1;
247              
248             __END__