mbxmlutils 1.3.0 Multi-Body XML Utils

last_write_time.h
1 /*
2 * Author: Markus Friedrich
3 *
4 * This file is free and unencumbered software released into the public domain.
5 *
6 * Anyone is free to copy, modify, publish, use, compile, sell, or
7 * distribute this software, either in source code form or as a compiled
8 * binary, for any purpose, commercial or non-commercial, and by any
9 * means.
10 *
11 * In jurisdictions that recognize copyright laws, the author or authors
12 * of this software dedicate any and all copyright interest in the
13 * software to the public domain. We make this dedication for the benefit
14 * of the public at large and to the detriment of our heirs and
15 * successors. We intend this dedication to be an overt act of
16 * relinquishment in perpetuity of all present and future rights to this
17 * software under copyright law.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 * OTHER DEALINGS IN THE SOFTWARE.
26 *
27 * For more information, please refer to <http://unlicense.org/>
28 */
29
30 #ifndef _MBXMLUTILS_LAST_WRITE_TIME_H_
31 #define _MBXMLUTILS_LAST_WRITE_TIME_H_
32
33 /* This is a varaint of the boost::filesystem::last_write_time functions.
34 * It only differs in the argument/return value being here a boost::posix_time::ptime instead of a time_t.
35 * This enables file timestamps on microsecond level.
36 * We use type string for argument p (instead of boost::filesystem::path) here to avoid a dependency to boost::filesystem here. */
37 #include <boost/date_time/posix_time/posix_time.hpp>
38 #include <string>
39 #include <sys/stat.h>
40 #ifdef _WIN32
41 #define WIN32_LEAN_AND_MEAN
42 #include <windows.h>
43 #endif
44
45 namespace boost::myfilesystem {
46
47 inline boost::posix_time::ptime last_write_time(const std::string &p);
48 inline void last_write_time(const std::string &p, const boost::posix_time::ptime &time);
49
50 boost::posix_time::ptime last_write_time(const std::string &p) {
51 #ifndef _WIN32
52 struct stat st;
53 if(stat(p.c_str(), &st)!=0)
54 throw std::runtime_error("system stat call failed: "+p);
55 boost::posix_time::ptime time;
56 time=boost::posix_time::from_time_t(st.st_mtime);
57 time+=boost::posix_time::microsec(st.st_mtim.tv_nsec/1000);
58 return time;
59 #else
60 HANDLE f=CreateFile(p.c_str(), GENERIC_READ, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
61 if(f==INVALID_HANDLE_VALUE)
62 throw std::runtime_error("CreateFile failed: "+p);
63 FILETIME create, lastAccess, lastWrite;
64 if(GetFileTime(f, &create, &lastAccess, &lastWrite)==0) {
65 CloseHandle(f);
66 throw std::runtime_error("GetFileTime failed: "+p);
67 }
68 CloseHandle(f);
69 uint64_t microSecSince1601=((((uint64_t)(lastWrite.dwHighDateTime))<<32)+lastWrite.dwLowDateTime)/10;
70 uint64_t hoursSince1601=microSecSince1601/1000000/60/60;
71 return boost::posix_time::ptime(boost::gregorian::date(1601,boost::gregorian::Jan,1),
72 boost::posix_time::hours(hoursSince1601)+
73 boost::posix_time::microseconds(microSecSince1601-hoursSince1601*60*60*1000000));
74 #endif
75 }
76 void last_write_time(const std::string &p, const boost::posix_time::ptime &time) {
77 #ifndef _WIN32
78 struct timeval times[2];
79 boost::posix_time::time_period sinceEpoch(boost::posix_time::ptime(boost::gregorian::date(1970, boost::gregorian::Jan, 1)), time);
80 times[0].tv_sec =sinceEpoch.length().total_seconds();
81 times[0].tv_usec=sinceEpoch.length().total_microseconds()-1000000*times[0].tv_sec;
82 times[1].tv_sec =times[0].tv_sec;
83 times[1].tv_usec=times[0].tv_usec;
84 if(utimes(p.c_str(), times)!=0)
85 throw std::runtime_error("system utimes call failed: "+p);
86 #else
87 HANDLE f=CreateFile(p.c_str(), FILE_WRITE_ATTRIBUTES, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
88 if(f==INVALID_HANDLE_VALUE)
89 throw std::runtime_error("CreateFile failed: "+p);
90 boost::posix_time::time_period since1601(boost::posix_time::ptime(boost::gregorian::date(1601, boost::gregorian::Jan, 1)), time);
91 boost::posix_time::time_duration dt=since1601.length();
92 uint64_t winTime=((uint64_t)(dt.hours()))*60*60*10000000;
93 dt-=boost::posix_time::hours(dt.hours());
94 winTime+=dt.total_microseconds()*10;
95 FILETIME changeTime;
96 changeTime.dwHighDateTime=(winTime>>32);
97 changeTime.dwLowDateTime=(winTime & ((((uint64_t)1)<<32)-1));
98 if(SetFileTime(f, NULL, &changeTime, &changeTime)==0) {
99 CloseHandle(f);
100 throw std::runtime_error("SetFileTime failed: "+p);
101 }
102 CloseHandle(f);
103 #endif
104 }
105
106 }
107
108 #endif