line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package File::Stamped; |
2
|
7
|
|
|
7
|
|
595011
|
use strict; |
|
7
|
|
|
|
|
77
|
|
|
7
|
|
|
|
|
177
|
|
3
|
7
|
|
|
7
|
|
32
|
use warnings; |
|
7
|
|
|
|
|
14
|
|
|
7
|
|
|
|
|
190
|
|
4
|
7
|
|
|
7
|
|
151
|
use 5.008001; |
|
7
|
|
|
|
|
22
|
|
5
|
|
|
|
|
|
|
our $VERSION = '0.09'; |
6
|
7
|
|
|
7
|
|
32
|
use Carp (); |
|
7
|
|
|
|
|
11
|
|
|
7
|
|
|
|
|
93
|
|
7
|
7
|
|
|
7
|
|
3180
|
use POSIX (); |
|
7
|
|
|
|
|
38791
|
|
|
7
|
|
|
|
|
227
|
|
8
|
7
|
|
|
7
|
|
424
|
use SelectSaver (); |
|
7
|
|
|
|
|
1232
|
|
|
7
|
|
|
|
|
89
|
|
9
|
7
|
|
|
7
|
|
30
|
use File::Path (); |
|
7
|
|
|
|
|
11
|
|
|
7
|
|
|
|
|
73
|
|
10
|
7
|
|
|
7
|
|
27
|
use File::Basename (); |
|
7
|
|
|
|
|
14
|
|
|
7
|
|
|
|
|
6143
|
|
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
sub new { |
13
|
6
|
|
|
6
|
1
|
4346
|
my $class = shift; |
14
|
6
|
50
|
|
|
|
41
|
my %args = @_==1?%{$_[0]}:@_; |
|
0
|
|
|
|
|
0
|
|
15
|
6
|
50
|
66
|
|
|
45
|
if (exists($args{pattern}) && exists($args{callback})) { |
16
|
0
|
|
|
|
|
0
|
Carp::croak "Both 'pattern' and 'callback' cannot be specified."; |
17
|
|
|
|
|
|
|
} |
18
|
6
|
50
|
66
|
|
|
28
|
unless (exists($args{pattern}) || exists($args{callback})) { |
19
|
0
|
|
|
|
|
0
|
Carp::croak "You need to specify 'pattern' or 'callback'."; |
20
|
|
|
|
|
|
|
} |
21
|
6
|
50
|
66
|
|
|
46
|
if (defined $args{symlink} && ! -l $args{symlink} && -e _) { |
|
|
|
66
|
|
|
|
|
22
|
0
|
|
|
|
|
0
|
Carp::croak "File '$args{symlink}' already exists (not a symlink)"; |
23
|
|
|
|
|
|
|
} |
24
|
6
|
|
66
|
|
|
50
|
my $callback = delete($args{callback}) || _make_callback_from_pattern(delete($args{pattern})); |
25
|
6
|
|
|
|
|
15
|
my $self = bless \do { local *FH }, $class; |
|
6
|
|
|
|
|
32
|
|
26
|
6
|
|
|
|
|
98
|
tie *$self, $class, $self; |
27
|
6
|
|
|
|
|
59
|
%args = ( |
28
|
|
|
|
|
|
|
autoflush => 1, |
29
|
|
|
|
|
|
|
close_after_write => 1, |
30
|
|
|
|
|
|
|
iomode => '>>:utf8', |
31
|
|
|
|
|
|
|
rotationtime => 1, |
32
|
|
|
|
|
|
|
callback => $callback, |
33
|
|
|
|
|
|
|
auto_make_dir => 0, |
34
|
|
|
|
|
|
|
%args, |
35
|
|
|
|
|
|
|
); |
36
|
6
|
|
|
|
|
28
|
for my $k (keys %args) { |
37
|
37
|
|
|
|
|
76
|
*$self->{$k} = $args{$k}; |
38
|
|
|
|
|
|
|
} |
39
|
6
|
|
|
|
|
21
|
return $self; |
40
|
|
|
|
|
|
|
} |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
sub TIEHANDLE { |
43
|
|
|
|
|
|
|
( |
44
|
6
|
50
|
33
|
6
|
|
80
|
( defined( $_[1] ) && UNIVERSAL::isa( $_[1], __PACKAGE__ ) ) |
45
|
|
|
|
|
|
|
? $_[1] |
46
|
|
|
|
|
|
|
: shift->new(@_) |
47
|
|
|
|
|
|
|
); |
48
|
|
|
|
|
|
|
} |
49
|
|
|
|
|
|
|
|
50
|
4
|
|
|
4
|
|
80
|
sub PRINT { shift->print(@_) } |
51
|
|
|
|
|
|
|
|
52
|
3
|
|
|
3
|
|
31
|
sub WRITE { shift->syswrite(@_) } |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
sub _gen_filename { |
55
|
14
|
|
|
14
|
|
3000636
|
my $self = shift; |
56
|
14
|
|
|
|
|
54
|
return *$self->{callback}->(*$self); |
57
|
|
|
|
|
|
|
} |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
sub _make_callback_from_pattern { |
60
|
5
|
|
|
5
|
|
13
|
my ($pattern) = shift; |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
return sub { |
63
|
12
|
|
|
12
|
|
22
|
my $self = shift; |
64
|
12
|
|
|
|
|
21
|
my $time = time(); |
65
|
12
|
50
|
|
|
|
36
|
if ( $time > 1 ) { |
66
|
12
|
|
|
|
|
30
|
$time = $time - $time % $self->{rotationtime}; |
67
|
|
|
|
|
|
|
} |
68
|
12
|
|
|
|
|
733
|
return POSIX::strftime($pattern, localtime($time)); |
69
|
5
|
|
|
|
|
48
|
}; |
70
|
|
|
|
|
|
|
} |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
sub _gen_symlink { |
73
|
12
|
|
|
12
|
|
24
|
my ($self, $fname) = @_; |
74
|
|
|
|
|
|
|
|
75
|
12
|
100
|
|
|
|
58
|
if (defined(my $symlink = *$self->{symlink})) { |
76
|
2
|
100
|
|
|
|
22
|
if (-l $symlink) { |
77
|
1
|
|
|
|
|
10
|
my $link = readlink $symlink; |
78
|
1
|
50
|
33
|
|
|
8
|
if (defined $link && $link ne $fname) { |
79
|
0
|
|
|
|
|
0
|
unlink $symlink; |
80
|
|
|
|
|
|
|
} |
81
|
|
|
|
|
|
|
} |
82
|
2
|
|
|
|
|
32
|
symlink $fname, $symlink; |
83
|
|
|
|
|
|
|
} |
84
|
|
|
|
|
|
|
} |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
sub _output { |
87
|
12
|
|
|
12
|
|
26
|
my ($self, $callback) = @_; |
88
|
|
|
|
|
|
|
|
89
|
12
|
|
|
|
|
26
|
my $fname = $self->_gen_filename(); |
90
|
12
|
100
|
|
|
|
223
|
if (*$self->{auto_make_dir}) { |
91
|
2
|
|
|
|
|
263
|
File::Path::make_path(File::Basename::dirname($fname)); |
92
|
|
|
|
|
|
|
} |
93
|
12
|
|
|
|
|
18
|
my $fh; |
94
|
12
|
50
|
|
|
|
38
|
if (*$self->{fh}) { |
95
|
0
|
0
|
0
|
|
|
0
|
if ($fname eq *$self->{fname} && *$self->{pid}==$$) { |
96
|
0
|
|
|
|
|
0
|
$fh = delete *$self->{fh}; |
97
|
|
|
|
|
|
|
} else { |
98
|
0
|
|
|
|
|
0
|
my $fh = delete *$self->{fh}; |
99
|
0
|
0
|
|
|
|
0
|
close $fh if $fh; |
100
|
|
|
|
|
|
|
} |
101
|
|
|
|
|
|
|
} |
102
|
|
|
|
|
|
|
|
103
|
12
|
|
|
|
|
30
|
$fh = $callback->($fh, $fname); |
104
|
|
|
|
|
|
|
|
105
|
12
|
50
|
|
|
|
54
|
if (*$self->{close_after_write}) { |
106
|
12
|
|
|
|
|
164
|
close $fh; |
107
|
|
|
|
|
|
|
} else { |
108
|
0
|
|
|
|
|
0
|
*$self->{fh} = $fh; |
109
|
0
|
|
|
|
|
0
|
*$self->{fname} = $fname; |
110
|
0
|
|
|
|
|
0
|
*$self->{pid} = $$; |
111
|
|
|
|
|
|
|
} |
112
|
|
|
|
|
|
|
} |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
sub print { |
115
|
8
|
|
|
8
|
1
|
29
|
my $self = shift; |
116
|
|
|
|
|
|
|
|
117
|
8
|
|
|
|
|
21
|
my @msg = @_; |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
$self->_output(sub { |
120
|
8
|
|
|
8
|
|
19
|
my ($fh, $fname) = @_; |
121
|
8
|
50
|
|
|
|
21
|
unless ($fh) { |
122
|
8
|
50
|
|
|
|
597
|
open $fh, *$self->{iomode}, $fname or die "Cannot open file($fname): $!"; |
123
|
8
|
50
|
|
|
|
59
|
if (*$self->{autoflush}) { |
124
|
8
|
|
|
|
|
59
|
my $saver = SelectSaver->new($fh); |
125
|
8
|
|
|
|
|
212
|
$|=1; |
126
|
|
|
|
|
|
|
} |
127
|
8
|
|
|
|
|
70
|
$self->_gen_symlink($fname); |
128
|
|
|
|
|
|
|
} |
129
|
8
|
50
|
|
|
|
26
|
print {$fh} @msg |
|
8
|
|
|
|
|
308
|
|
130
|
|
|
|
|
|
|
or die "Cannot write to $fname: $!"; |
131
|
|
|
|
|
|
|
|
132
|
8
|
|
|
|
|
30
|
$fh; |
133
|
8
|
|
|
|
|
42
|
}); |
134
|
|
|
|
|
|
|
} |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
sub syswrite { |
137
|
4
|
|
|
4
|
1
|
10
|
my $self = shift; |
138
|
|
|
|
|
|
|
|
139
|
4
|
|
|
|
|
16
|
my ($buf, @args) = @_; |
140
|
|
|
|
|
|
|
|
141
|
4
|
|
|
|
|
10
|
local *$self->{iomode} = '>>:raw'; # perl-5.30 syswrite compatibility |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
$self->_output(sub { |
144
|
4
|
|
|
4
|
|
10
|
my ($fh, $fname) = @_; |
145
|
4
|
50
|
|
|
|
6
|
unless ($fh) { |
146
|
4
|
50
|
|
|
|
146
|
open $fh, *$self->{iomode}, $fname or die "Cannot open file($fname): $!"; |
147
|
4
|
|
|
|
|
18
|
$self->_gen_symlink($fname); |
148
|
|
|
|
|
|
|
} |
149
|
4
|
50
|
|
|
|
79
|
my $res = @args == 0 ? CORE::syswrite($fh, $buf) |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
150
|
|
|
|
|
|
|
: @args == 1 ? CORE::syswrite($fh, $buf, $args[0]) |
151
|
|
|
|
|
|
|
: @args == 2 ? CORE::syswrite($fh, $buf, $args[0], $args[1]) |
152
|
|
|
|
|
|
|
: Carp::croak 'Too many arguments for syswrite'; |
153
|
4
|
50
|
|
|
|
13
|
die "Cannot write to $fname: $!" unless $res; |
154
|
|
|
|
|
|
|
|
155
|
4
|
|
|
|
|
8
|
$fh; |
156
|
4
|
|
|
|
|
20
|
}); |
157
|
|
|
|
|
|
|
} |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
1; |
160
|
|
|
|
|
|
|
__END__ |