1 | /*****************************************************************************/ |
2 | /* */ |
3 | /* filetime.c */ |
4 | /* */ |
5 | /* Replacement for Windows code */ |
6 | /* */ |
7 | /* */ |
8 | /* */ |
9 | /* (C) 2012, Ullrich von Bassewitz */ |
10 | /* Roemerstrasse 52 */ |
11 | /* D-70794 Filderstadt */ |
12 | /* EMail: uz@cc65.org */ |
13 | /* */ |
14 | /* */ |
15 | /* This software is provided 'as-is', without any expressed or implied */ |
16 | /* warranty. In no event will the authors be held liable for any damages */ |
17 | /* arising from the use of this software. */ |
18 | /* */ |
19 | /* Permission is granted to anyone to use this software for any purpose, */ |
20 | /* including commercial applications, and to alter it and redistribute it */ |
21 | /* freely, subject to the following restrictions: */ |
22 | /* */ |
23 | /* 1. The origin of this software must not be misrepresented; you must not */ |
24 | /* claim that you wrote the original software. If you use this software */ |
25 | /* in a product, an acknowledgment in the product documentation would be */ |
26 | /* appreciated but is not required. */ |
27 | /* 2. Altered source versions must be plainly marked as such, and must not */ |
28 | /* be misrepresented as being the original software. */ |
29 | /* 3. This notice may not be removed or altered from any source */ |
30 | /* distribution. */ |
31 | /* */ |
32 | /*****************************************************************************/ |
33 | |
34 | |
35 | |
36 | /* This module works around bugs in the time conversion code supplied by |
37 | ** Microsoft. The problem described here: |
38 | ** http://www.codeproject.com/KB/datetime/dstbugs.aspx |
39 | ** is also true when setting file times via utime(), so we need a |
40 | ** replacement |
41 | */ |
42 | |
43 | |
44 | |
45 | #if defined(_WIN32) |
46 | # include <errno.h> |
47 | # include <windows.h> |
48 | #else |
49 | # include <sys/types.h> /* FreeBSD needs this */ |
50 | # include <utime.h> |
51 | #endif |
52 | |
53 | |
54 | /* common */ |
55 | #include "filetime.h" |
56 | |
57 | |
58 | |
59 | /*****************************************************************************/ |
60 | /* Code */ |
61 | /*****************************************************************************/ |
62 | |
63 | |
64 | |
65 | #if defined(_WIN32) |
66 | |
67 | |
68 | |
69 | static FILETIME* UnixTimeToFileTime (time_t T, FILETIME* FT) |
70 | /* Calculate a FILETIME value from a time_t. FILETIME contains a 64 bit |
71 | ** value with point zero at 1600-01-01 00:00:00 and counting 100ns intervals. |
72 | ** time_t is in seconds since 1970-01-01 00:00:00. |
73 | */ |
74 | { |
75 | /* Offset between 1600-01-01 and the Epoch in seconds. Watcom C has no |
76 | ** way to express a number > 32 bit (known to me) but is able to do |
77 | ** calculations with 64 bit integers, so we need to do it this way. |
78 | */ |
79 | static const ULARGE_INTEGER Offs = { { 0xB6109100UL, 0x00000020UL } }; |
80 | ULARGE_INTEGER V; |
81 | V.QuadPart = ((unsigned __int64) T + Offs.QuadPart) * 10000000U; |
82 | FT->dwLowDateTime = V.LowPart; |
83 | FT->dwHighDateTime = V.HighPart; |
84 | return FT; |
85 | } |
86 | |
87 | |
88 | |
89 | int SetFileTimes (const char* Path, time_t T) |
90 | /* Set the time of last modification and the time of last access of a file to |
91 | ** the given time T. This calls utime() for system where it works, and applies |
92 | ** workarounds for all others (which in fact means "WINDOWS"). |
93 | */ |
94 | { |
95 | HANDLE H; |
96 | FILETIME FileTime; |
97 | int Error = EACCES; /* Assume an error */ |
98 | |
99 | |
100 | /* Open the file */ |
101 | H = CreateFile (Path, |
102 | GENERIC_WRITE, |
103 | FILE_SHARE_READ, |
104 | 0, /* Security attributes */ |
105 | OPEN_EXISTING, |
106 | 0, /* File flags */ |
107 | 0); /* Template file */ |
108 | if (H != INVALID_HANDLE_VALUE) { |
109 | /* Set access and modification time */ |
110 | UnixTimeToFileTime (T, &FileTime); |
111 | if (SetFileTime (H, 0, &FileTime, &FileTime)) { |
112 | /* Done */ |
113 | Error = 0; |
114 | } |
115 | |
116 | /* Close the handle */ |
117 | (void) CloseHandle (H); |
118 | } |
119 | |
120 | /* Return the error code */ |
121 | return Error; |
122 | } |
123 | |
124 | |
125 | |
126 | #else |
127 | |
128 | |
129 | |
130 | int SetFileTimes (const char* Path, time_t T) |
131 | /* Set the time of last modification and the time of last access of a file to |
132 | ** the given time T. This calls utime() for system where it works, and applies |
133 | ** workarounds for all others (which in fact means "WINDOWS"). |
134 | */ |
135 | { |
136 | struct utimbuf U; |
137 | |
138 | /* Set access and modification time */ |
139 | U.actime = T; |
140 | U.modtime = T; |
141 | return utime (Path, &U); |
142 | } |
143 | |
144 | |
145 | |
146 | #endif |
147 | |