| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
=head1 NAME |
|
2
|
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
Win32API::File::Time - Set file times, even on open or readonly files. |
|
4
|
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
=head1 SYNOPSIS |
|
6
|
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
use Win32API::File::Time qw{:win}; |
|
8
|
|
|
|
|
|
|
($atime, $mtime, $ctime) = GetFileTime ($filename); |
|
9
|
|
|
|
|
|
|
SetFileTime ($filename, $atime, $mtime, $ctime); |
|
10
|
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
or |
|
12
|
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
use Win32API::File::Time qw{utime}; |
|
14
|
|
|
|
|
|
|
utime $atime, $mtime, $filename or die $^E; |
|
15
|
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
17
|
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
The purpose of Win32API::File::Time is to provide maximal access to |
|
19
|
|
|
|
|
|
|
the file creation, modification, and access times under MSWin32. |
|
20
|
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
Under Windows, the Perl utime module will not modify the time of an |
|
22
|
|
|
|
|
|
|
open file, nor a read-only file. The comments in win32.c indicate |
|
23
|
|
|
|
|
|
|
that this is the intended functionality, at least for read-only |
|
24
|
|
|
|
|
|
|
files. |
|
25
|
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
This module will read and modify the time on open files, read-only |
|
27
|
|
|
|
|
|
|
files, and directories. I |
|
28
|
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
This module is based on the SetFileTime function in kernel32.dll. |
|
30
|
|
|
|
|
|
|
Perl's utime built-in also makes explicit use of this function if |
|
31
|
|
|
|
|
|
|
the "C" run-time version of utime fails. The difference is in how |
|
32
|
|
|
|
|
|
|
the filehandle is created. The Perl built-in requests access |
|
33
|
|
|
|
|
|
|
GENERIC_READ | GENERIC_WRITE when modifying file dates, whereas |
|
34
|
|
|
|
|
|
|
this module requests access FILE_WRITE_ATTRIBUTES. |
|
35
|
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
Nothing is exported by default, but all documented subroutines |
|
37
|
|
|
|
|
|
|
are exportable. In addition, the following export tags are |
|
38
|
|
|
|
|
|
|
supported: |
|
39
|
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
:all => exports everything exportable |
|
41
|
|
|
|
|
|
|
:win => exports GetFileTime and SetFileTime |
|
42
|
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
Wide system calls are implemented (based on the truth of |
|
44
|
|
|
|
|
|
|
${^WIDE_SYSTEM_CALLS}) but not currently supported. In other words: I |
|
45
|
|
|
|
|
|
|
wrote the code, but haven't tested it and don't have any plans to. |
|
46
|
|
|
|
|
|
|
Feedback will be accepted, and implemented when I get a sufficient |
|
47
|
|
|
|
|
|
|
supply of tuits. |
|
48
|
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
=over 4 |
|
50
|
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
=cut |
|
52
|
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
# Modifications: |
|
54
|
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
# 0.001 13-May-2004 T. R. Wyant |
|
56
|
|
|
|
|
|
|
# Initial version. |
|
57
|
|
|
|
|
|
|
# 0.002 02-Oct-2004 T. R. Wyant |
|
58
|
|
|
|
|
|
|
# No code changes. Add the readme file to the manifest, |
|
59
|
|
|
|
|
|
|
# and add the dependencies to Makefile.PL, since they |
|
60
|
|
|
|
|
|
|
# really _should_ be there, and Active State is |
|
61
|
|
|
|
|
|
|
# complaining about them missing. |
|
62
|
|
|
|
|
|
|
# 0.003 17-Dec-2004 T. R. Wyant |
|
63
|
|
|
|
|
|
|
# Reimplement time conversion. Also modified the self- |
|
64
|
|
|
|
|
|
|
# test to use a scratch file for the date modification |
|
65
|
|
|
|
|
|
|
# portion of the test. |
|
66
|
|
|
|
|
|
|
# 0.003_01 28-Dec-2004 T. R. Wyant |
|
67
|
|
|
|
|
|
|
# Close handles after use. In case of error, preserve |
|
68
|
|
|
|
|
|
|
# the windows error around the close. |
|
69
|
|
|
|
|
|
|
# 0.004 13-Jan-2005 T. R. Wyant |
|
70
|
|
|
|
|
|
|
# Fix export tags. |
|
71
|
|
|
|
|
|
|
# Tweak "Bugs" section to more accurately represent what |
|
72
|
|
|
|
|
|
|
# I think is going on. |
|
73
|
|
|
|
|
|
|
# Release to CPAN. |
|
74
|
|
|
|
|
|
|
# 0.004_01 28-Apr-2005 T. R. Wyant |
|
75
|
|
|
|
|
|
|
# Assert FILE_FLAG_BACKUP_SEMANTICS when reading times, |
|
76
|
|
|
|
|
|
|
# so that it works for directories under XP and |
|
77
|
|
|
|
|
|
|
# 2003 server. |
|
78
|
|
|
|
|
|
|
# Centralize code to close handles on error. |
|
79
|
|
|
|
|
|
|
# 0.004_02 04-May-2005 T. R. Wyant |
|
80
|
|
|
|
|
|
|
# Document behaviour of FAT (and change test to |
|
81
|
|
|
|
|
|
|
# accomodate. |
|
82
|
|
|
|
|
|
|
# 0.005 04-May-2005 T. R. Wyant |
|
83
|
|
|
|
|
|
|
# Release to CPAN. |
|
84
|
|
|
|
|
|
|
|
|
85
|
1
|
|
|
1
|
|
60372
|
use strict; |
|
|
1
|
|
|
|
|
3
|
|
|
|
1
|
|
|
|
|
38
|
|
|
86
|
1
|
|
|
1
|
|
5
|
use warnings; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
50
|
|
|
87
|
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
package Win32API::File::Time; |
|
89
|
|
|
|
|
|
|
|
|
90
|
1
|
|
|
1
|
|
5
|
use base qw{Exporter}; |
|
|
1
|
|
|
|
|
6
|
|
|
|
1
|
|
|
|
|
129
|
|
|
91
|
1
|
|
|
1
|
|
6
|
use vars qw{@EXPORT_OK %EXPORT_TAGS $VERSION}; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
75
|
|
|
92
|
1
|
|
|
|
|
85
|
use vars qw{ |
|
93
|
|
|
|
|
|
|
$FileTimeToSystemTime |
|
94
|
|
|
|
|
|
|
$FileTimeToLocalFileTime |
|
95
|
|
|
|
|
|
|
$GetFileTime |
|
96
|
|
|
|
|
|
|
$LocalFileTimeToFileTime |
|
97
|
|
|
|
|
|
|
$SetFileTime |
|
98
|
|
|
|
|
|
|
$SystemTimeToFileTime |
|
99
|
1
|
|
|
1
|
|
6
|
}; |
|
|
1
|
|
|
|
|
2
|
|
|
100
|
|
|
|
|
|
|
|
|
101
|
1
|
|
|
1
|
|
6
|
use Carp; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
74
|
|
|
102
|
1
|
|
|
1
|
|
1076
|
use Time::Local; |
|
|
1
|
|
|
|
|
2591
|
|
|
|
1
|
|
|
|
|
149
|
|
|
103
|
1
|
|
|
1
|
|
2056
|
use Win32::API; |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
use Win32API::File qw{:ALL}; |
|
105
|
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
$VERSION = '0.006'; |
|
107
|
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
@EXPORT_OK = qw{GetFileTime SetFileTime utime}; |
|
109
|
|
|
|
|
|
|
%EXPORT_TAGS = ( |
|
110
|
|
|
|
|
|
|
all => [@EXPORT_OK], |
|
111
|
|
|
|
|
|
|
win => [qw{GetFileTime SetFileTime}], |
|
112
|
|
|
|
|
|
|
); |
|
113
|
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
=item ($atime, $mtime, $ctime) = GetFileTime ($filename); |
|
115
|
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
This subroutine returns the access, modification, and creation times of |
|
117
|
|
|
|
|
|
|
the given file. If it fails, nothing is returned, and the error code |
|
118
|
|
|
|
|
|
|
can be found in $^E. |
|
119
|
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
No, there's no additional functionality here versus the stat |
|
121
|
|
|
|
|
|
|
built-in. But it was useful for development and testing, and |
|
122
|
|
|
|
|
|
|
has been exposed for orthogonality's sake. |
|
123
|
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
=cut |
|
125
|
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
sub GetFileTime { |
|
127
|
|
|
|
|
|
|
my $fn = shift or croak "usage: GetFileTime (filename)"; |
|
128
|
|
|
|
|
|
|
my $fh = _get_handle ($fn) or return; |
|
129
|
|
|
|
|
|
|
$GetFileTime ||= _map ('KERNEL32', 'GetFileTime', [qw{N P P P}], 'I'); |
|
130
|
|
|
|
|
|
|
my ($atime, $mtime, $ctime); |
|
131
|
|
|
|
|
|
|
$atime = $mtime = $ctime = pack 'LL', 0, 0; # Preallocate 64 bits. |
|
132
|
|
|
|
|
|
|
$GetFileTime->Call ($fh, $ctime, $atime, $mtime) or |
|
133
|
|
|
|
|
|
|
return _close_handle ($fh); |
|
134
|
|
|
|
|
|
|
CloseHandle ($fh); |
|
135
|
|
|
|
|
|
|
return _filetime_to_perltime ($atime, $mtime, $ctime); |
|
136
|
|
|
|
|
|
|
} |
|
137
|
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
=item SetFileTime (filename, atime, mtime, ctime); |
|
140
|
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
This subroutine sets the access, modification, and creation times of |
|
142
|
|
|
|
|
|
|
the given file. The return is true for success, and false for failure. |
|
143
|
|
|
|
|
|
|
In the latter case, $^E will contain the error. |
|
144
|
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
If you don't want to set all of the times, pass 0 or undef for the |
|
146
|
|
|
|
|
|
|
times you don't want to set. For example, |
|
147
|
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
$now = time (); |
|
149
|
|
|
|
|
|
|
SetFileTime ($filename, $now, $now); |
|
150
|
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
is equivalent to the "touch" command for the given file. |
|
152
|
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
=cut |
|
154
|
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
sub SetFileTime { |
|
156
|
|
|
|
|
|
|
my $fn = shift or croak "usage: SetFileTime (filename, atime, mtime, ctime)"; |
|
157
|
|
|
|
|
|
|
my $atime = _perltime_to_filetime (shift); |
|
158
|
|
|
|
|
|
|
my $mtime = _perltime_to_filetime (shift); |
|
159
|
|
|
|
|
|
|
my $ctime = _perltime_to_filetime (shift); |
|
160
|
|
|
|
|
|
|
# We assume we can do something useful for an undef. |
|
161
|
|
|
|
|
|
|
$SetFileTime ||= _map ('KERNEL32', 'SetFileTime', [qw{N P P P}], 'I'); |
|
162
|
|
|
|
|
|
|
my $fh = _get_handle ($fn, 1) or return; |
|
163
|
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
$SetFileTime->Call ($fh, $ctime, $atime, $mtime) or |
|
165
|
|
|
|
|
|
|
return _close_handle ($fh); |
|
166
|
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
CloseHandle ($fh); |
|
168
|
|
|
|
|
|
|
return 1; |
|
169
|
|
|
|
|
|
|
} |
|
170
|
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
=item utime ($atime, $mtime, $filename, ...) |
|
172
|
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
This subroutine overrides the built-in of the same name. It does |
|
174
|
|
|
|
|
|
|
exactly the same thing, but has a different idea than the built-in |
|
175
|
|
|
|
|
|
|
about what files are legal to change. |
|
176
|
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
Like the core utime, it returns the number of files successfully |
|
178
|
|
|
|
|
|
|
modified. If not all files can be modified, $^E contains the last |
|
179
|
|
|
|
|
|
|
error encountered. |
|
180
|
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
=cut |
|
182
|
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
sub utime { |
|
184
|
|
|
|
|
|
|
my $atime = shift; |
|
185
|
|
|
|
|
|
|
my $mtime = shift; |
|
186
|
|
|
|
|
|
|
my $num = 0; |
|
187
|
|
|
|
|
|
|
foreach my $fn (@_) { |
|
188
|
|
|
|
|
|
|
SetFileTime ($fn, $atime, $mtime) and $num++; |
|
189
|
|
|
|
|
|
|
} |
|
190
|
|
|
|
|
|
|
return $num; |
|
191
|
|
|
|
|
|
|
} |
|
192
|
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
####################################################################### |
|
195
|
|
|
|
|
|
|
# |
|
196
|
|
|
|
|
|
|
# Internal subroutines |
|
197
|
|
|
|
|
|
|
# |
|
198
|
|
|
|
|
|
|
# _close_handle |
|
199
|
|
|
|
|
|
|
# |
|
200
|
|
|
|
|
|
|
# This subroutine closes the given handle, preserving status |
|
201
|
|
|
|
|
|
|
# around the call. |
|
202
|
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
sub _close_handle { |
|
204
|
|
|
|
|
|
|
my $fh = shift; |
|
205
|
|
|
|
|
|
|
my $err = Win32::GetLastError (); |
|
206
|
|
|
|
|
|
|
CloseHandle ($fh); |
|
207
|
|
|
|
|
|
|
$^E = $err; |
|
208
|
|
|
|
|
|
|
return; |
|
209
|
|
|
|
|
|
|
} |
|
210
|
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
# _filetime_to_perltime |
|
213
|
|
|
|
|
|
|
# |
|
214
|
|
|
|
|
|
|
# This subroutine takes as input a number of Windows file times |
|
215
|
|
|
|
|
|
|
# and converts them to Perl times. |
|
216
|
|
|
|
|
|
|
# |
|
217
|
|
|
|
|
|
|
# The algorithm is due to the unsung heros at Hip Communications |
|
218
|
|
|
|
|
|
|
# Inc (currently known as ActiveState), who found a way around |
|
219
|
|
|
|
|
|
|
# the fact that Perl and Windows have a fundamentally different |
|
220
|
|
|
|
|
|
|
# idea of what local time corresponds to a given GMT when summer |
|
221
|
|
|
|
|
|
|
# time was in effect at the given GMT, but not at the time the |
|
222
|
|
|
|
|
|
|
# conversion is made. The given algorithm is consistent with the |
|
223
|
|
|
|
|
|
|
# results of the stat () function. |
|
224
|
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
sub _filetime_to_perltime { |
|
226
|
|
|
|
|
|
|
my @result; |
|
227
|
|
|
|
|
|
|
$FileTimeToSystemTime ||= _map ( |
|
228
|
|
|
|
|
|
|
'KERNEL32', 'FileTimeToSystemTime', [qw{P P}], 'I'); |
|
229
|
|
|
|
|
|
|
$FileTimeToLocalFileTime ||= _map ( |
|
230
|
|
|
|
|
|
|
'KERNEL32', 'FileTimeToLocalFileTime', [qw{P P}], 'I'); |
|
231
|
|
|
|
|
|
|
my $st = pack 'ssssssss', 0, 0, 0, 0, 0, 0, 0, 0; |
|
232
|
|
|
|
|
|
|
foreach my $ft (@_) { |
|
233
|
|
|
|
|
|
|
my ($low, $high) = unpack 'LL', $ft; |
|
234
|
|
|
|
|
|
|
$high or do { |
|
235
|
|
|
|
|
|
|
push @result, undef; |
|
236
|
|
|
|
|
|
|
next; |
|
237
|
|
|
|
|
|
|
}; |
|
238
|
|
|
|
|
|
|
my $lf = $ft; # Just to get the space allocated. |
|
239
|
|
|
|
|
|
|
$FileTimeToLocalFileTime->Call ($ft, $lf) && |
|
240
|
|
|
|
|
|
|
$FileTimeToSystemTime->Call ($lf, $st) or do { |
|
241
|
|
|
|
|
|
|
push @result, undef; |
|
242
|
|
|
|
|
|
|
next; |
|
243
|
|
|
|
|
|
|
}; |
|
244
|
|
|
|
|
|
|
my @tm = unpack 'ssssssss', $st; |
|
245
|
|
|
|
|
|
|
push @result, $tm[0] > 0 ? |
|
246
|
|
|
|
|
|
|
timelocal (@tm[6, 5, 4, 3], $tm[1] - 1, $tm[0]) : |
|
247
|
|
|
|
|
|
|
undef; |
|
248
|
|
|
|
|
|
|
} |
|
249
|
|
|
|
|
|
|
return wantarray ? @result : $result[0]; |
|
250
|
|
|
|
|
|
|
} |
|
251
|
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
# _get_handle |
|
254
|
|
|
|
|
|
|
# |
|
255
|
|
|
|
|
|
|
# This subroutine takes a file name and returns a handle to the |
|
256
|
|
|
|
|
|
|
# file. If the second argument is true, the handle is configured |
|
257
|
|
|
|
|
|
|
# appropriately for writing attributes; otherwise it is |
|
258
|
|
|
|
|
|
|
# configured appropriately for reading attributes. |
|
259
|
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
sub _get_handle { |
|
261
|
|
|
|
|
|
|
my $fn = shift; |
|
262
|
|
|
|
|
|
|
my $write = shift; |
|
263
|
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
${^WIDE_SYSTEM_CALLS} ? |
|
265
|
|
|
|
|
|
|
CreateFileW ($fn, |
|
266
|
|
|
|
|
|
|
($write ? FILE_WRITE_ATTRIBUTES : FILE_READ_ATTRIBUTES), |
|
267
|
|
|
|
|
|
|
($write ? FILE_SHARE_WRITE | FILE_SHARE_READ : FILE_SHARE_READ), |
|
268
|
|
|
|
|
|
|
[], |
|
269
|
|
|
|
|
|
|
OPEN_EXISTING, |
|
270
|
|
|
|
|
|
|
($write ? FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS : FILE_FLAG_BACKUP_SEMANTICS), |
|
271
|
|
|
|
|
|
|
0, |
|
272
|
|
|
|
|
|
|
) : |
|
273
|
|
|
|
|
|
|
CreateFile ($fn, |
|
274
|
|
|
|
|
|
|
($write ? FILE_WRITE_ATTRIBUTES : FILE_READ_ATTRIBUTES), |
|
275
|
|
|
|
|
|
|
($write ? FILE_SHARE_WRITE | FILE_SHARE_READ : FILE_SHARE_READ), |
|
276
|
|
|
|
|
|
|
[], |
|
277
|
|
|
|
|
|
|
OPEN_EXISTING, |
|
278
|
|
|
|
|
|
|
($write ? FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS : FILE_FLAG_BACKUP_SEMANTICS), |
|
279
|
|
|
|
|
|
|
0, |
|
280
|
|
|
|
|
|
|
) |
|
281
|
|
|
|
|
|
|
or do { |
|
282
|
|
|
|
|
|
|
$^E = Win32::GetLastError (); |
|
283
|
|
|
|
|
|
|
return; |
|
284
|
|
|
|
|
|
|
}; |
|
285
|
|
|
|
|
|
|
} |
|
286
|
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
# _map |
|
289
|
|
|
|
|
|
|
# |
|
290
|
|
|
|
|
|
|
# This subroutine calls Win32API to map an entry point. |
|
291
|
|
|
|
|
|
|
|
|
292
|
|
|
|
|
|
|
sub _map { |
|
293
|
|
|
|
|
|
|
return Win32::API->new (@_) || |
|
294
|
|
|
|
|
|
|
croak "Error - Failed to map $_[1] from $_[0]: $^E"; |
|
295
|
|
|
|
|
|
|
} |
|
296
|
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
# _perltime_to_filetime |
|
299
|
|
|
|
|
|
|
# |
|
300
|
|
|
|
|
|
|
# This subroutine converts perl times to Windows file times. |
|
301
|
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
# The same considerations apply to the algorithm used here as to |
|
303
|
|
|
|
|
|
|
# the one used in _filetime_to_perltime. |
|
304
|
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
sub _perltime_to_filetime { |
|
306
|
|
|
|
|
|
|
my @result; |
|
307
|
|
|
|
|
|
|
$SystemTimeToFileTime ||= _map ( |
|
308
|
|
|
|
|
|
|
'KERNEL32', 'SystemTimeToFileTime', [qw{P P}], 'I'); |
|
309
|
|
|
|
|
|
|
$LocalFileTimeToFileTime ||= _map ( |
|
310
|
|
|
|
|
|
|
'KERNEL32', 'LocalFileTimeToFileTime', [qw{P P}], 'I'); |
|
311
|
|
|
|
|
|
|
my $zero = pack 'LL', 0, 0; # To get a quadword zero. |
|
312
|
|
|
|
|
|
|
my ($ft, $lf) = ($zero, $zero); # To get the space allocated. |
|
313
|
|
|
|
|
|
|
foreach my $pt (@_) { |
|
314
|
|
|
|
|
|
|
if (defined $pt) { |
|
315
|
|
|
|
|
|
|
my @tm = localtime ($pt); |
|
316
|
|
|
|
|
|
|
my $st = pack 'ssssssss', $tm[5] + 1900, $tm[4] + 1, 0, |
|
317
|
|
|
|
|
|
|
@tm[3, 2, 1, 0], 0; |
|
318
|
|
|
|
|
|
|
push @result, $SystemTimeToFileTime->Call ($st, $lf) && |
|
319
|
|
|
|
|
|
|
$LocalFileTimeToFileTime->Call ($lf, $ft) ? $ft : $zero; |
|
320
|
|
|
|
|
|
|
} |
|
321
|
|
|
|
|
|
|
else { |
|
322
|
|
|
|
|
|
|
push @result, $zero; |
|
323
|
|
|
|
|
|
|
} |
|
324
|
|
|
|
|
|
|
} |
|
325
|
|
|
|
|
|
|
return wantarray ? @result : $result[0]; |
|
326
|
|
|
|
|
|
|
} |
|
327
|
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
=back |
|
329
|
|
|
|
|
|
|
|
|
330
|
|
|
|
|
|
|
=head1 HISTORY |
|
331
|
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
0.001 Initial release |
|
333
|
|
|
|
|
|
|
0.002 Correct MANIFEST and Makefile.PL dependencies. |
|
334
|
|
|
|
|
|
|
Tweak documentation. No code changes. |
|
335
|
|
|
|
|
|
|
0.003 Correct time conversion. |
|
336
|
|
|
|
|
|
|
Modify test to not change own date. |
|
337
|
|
|
|
|
|
|
0.004 Close handles after use. Thanks to Chris |
|
338
|
|
|
|
|
|
|
Camejo for pointing out the leak. |
|
339
|
|
|
|
|
|
|
Fix export tags to agree with docs. |
|
340
|
|
|
|
|
|
|
Tweak "BUGS" documentation. |
|
341
|
|
|
|
|
|
|
0.005 Assert FILE_FLAG_BACKUP_SEMANTICS when reading |
|
342
|
|
|
|
|
|
|
times, so that it works for directories |
|
343
|
|
|
|
|
|
|
under XP and 2003 server. Thanks to Leigh |
|
344
|
|
|
|
|
|
|
Power for pointing out the problem and |
|
345
|
|
|
|
|
|
|
suggesting the solution. |
|
346
|
|
|
|
|
|
|
Document FAT, and accomodate it in self-test. |
|
347
|
|
|
|
|
|
|
Thanks again, Leigh. |
|
348
|
|
|
|
|
|
|
Centralize code to close handles on error. |
|
349
|
|
|
|
|
|
|
0.006 T. R. Wyant |
|
350
|
|
|
|
|
|
|
Re-layout kit, add POD tests. |
|
351
|
|
|
|
|
|
|
|
|
352
|
|
|
|
|
|
|
=head1 BUGS |
|
353
|
|
|
|
|
|
|
|
|
354
|
|
|
|
|
|
|
As implemented, GetFileTime () constitutes an access, and |
|
355
|
|
|
|
|
|
|
therefore updates the access time. |
|
356
|
|
|
|
|
|
|
|
|
357
|
|
|
|
|
|
|
The stat () builtin, on the other hand, doesn't report |
|
358
|
|
|
|
|
|
|
an access time change even after GetFileTime () has been |
|
359
|
|
|
|
|
|
|
used. In fact, it looks to me very much like stat () reports |
|
360
|
|
|
|
|
|
|
the modification time in element [8] of the list, but I |
|
361
|
|
|
|
|
|
|
find this nowhere documented. |
|
362
|
|
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
FAT file time resolution is 2 seconds at best, as documented |
|
364
|
|
|
|
|
|
|
at F. |
|
365
|
|
|
|
|
|
|
Access time resolution seems to be to the nearest day. |
|
366
|
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
=head1 ACKNOWLEDGMENTS |
|
368
|
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
This module would not exist without the following people: |
|
370
|
|
|
|
|
|
|
|
|
371
|
|
|
|
|
|
|
Aldo Calpini, who gave us Win32::API. |
|
372
|
|
|
|
|
|
|
|
|
373
|
|
|
|
|
|
|
Tye McQueen, who gave us Win32API::File. |
|
374
|
|
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
Jenda Krynicky, whose "How2 create a PPM distribution" |
|
376
|
|
|
|
|
|
|
(F) gave me a leg up on |
|
377
|
|
|
|
|
|
|
both PPM and tar distributions. |
|
378
|
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
The folks of ActiveState (F, |
|
380
|
|
|
|
|
|
|
formerly known as Hip Communications), who found a way to reconcile |
|
381
|
|
|
|
|
|
|
Windows' and Perl's subtly different ideas of what time it is. |
|
382
|
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
The folks of Cygwin (F), especially those |
|
384
|
|
|
|
|
|
|
who worked on times.cc in the Cygwin core. This is the B |
|
385
|
|
|
|
|
|
|
implementation of utime I could find which did what B wanted |
|
386
|
|
|
|
|
|
|
it to do. |
|
387
|
|
|
|
|
|
|
|
|
388
|
|
|
|
|
|
|
|
|
389
|
|
|
|
|
|
|
=head1 AUTHOR |
|
390
|
|
|
|
|
|
|
|
|
391
|
|
|
|
|
|
|
Thomas R. Wyant, III (F) |
|
392
|
|
|
|
|
|
|
|
|
393
|
|
|
|
|
|
|
=head1 COPYRIGHT |
|
394
|
|
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
Copyright 2004, 2005 by |
|
396
|
|
|
|
|
|
|
E. I. DuPont de Nemours and Company, Inc. |
|
397
|
|
|
|
|
|
|
All rights reserved. |
|
398
|
|
|
|
|
|
|
|
|
399
|
|
|
|
|
|
|
Changes since version 0.005 copyright 2007 by Thomas R. Wyant, III. All |
|
400
|
|
|
|
|
|
|
rights reserved. |
|
401
|
|
|
|
|
|
|
|
|
402
|
|
|
|
|
|
|
=head1 LICENSE |
|
403
|
|
|
|
|
|
|
|
|
404
|
|
|
|
|
|
|
This module is free software; you can use it, redistribute it and/or |
|
405
|
|
|
|
|
|
|
modify it under the same terms as Perl itself. Please see |
|
406
|
|
|
|
|
|
|
L for current licenses. |
|
407
|
|
|
|
|
|
|
|
|
408
|
|
|
|
|
|
|
=cut |
|
409
|
|
|
|
|
|
|
|