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
69static 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
89int 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
130int 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