Loading [MathJax]/extensions/tex2jax.js
mbxmlutils  1.3.0
Multi-Body XML Utils
All Classes Functions Typedefs Enumerations
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#ifndef WIN32_LEAN_AND_MEAN
42#define WIN32_LEAN_AND_MEAN
43#endif
44#include <windows.h>
45#endif
46
47namespace boost::myfilesystem {
48
49 inline boost::posix_time::ptime last_write_time(const std::string &p);
50 inline void last_write_time(const std::string &p, const boost::posix_time::ptime &time);
51
52 boost::posix_time::ptime last_write_time(const std::string &p) {
53#ifndef _WIN32
54 struct stat st;
55 if(stat(p.c_str(), &st)!=0)
56 throw std::runtime_error("system stat call failed: "+p);
57 boost::posix_time::ptime time;
58 time=boost::posix_time::from_time_t(st.st_mtime);
59 time+=boost::posix_time::microsec(st.st_mtim.tv_nsec/1000);
60 return time;
61#else
62 HANDLE f=CreateFile(p.c_str(), GENERIC_READ, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
63 if(f==INVALID_HANDLE_VALUE)
64 throw std::runtime_error("CreateFile failed: "+p);
65 FILETIME create, lastAccess, lastWrite;
66 if(GetFileTime(f, &create, &lastAccess, &lastWrite)==0) {
67 CloseHandle(f);
68 throw std::runtime_error("GetFileTime failed: "+p);
69 }
70 CloseHandle(f);
71 uint64_t microSecSince1601=((((uint64_t)(lastWrite.dwHighDateTime))<<32)+lastWrite.dwLowDateTime)/10;
72 uint64_t hoursSince1601=microSecSince1601/1000000/60/60;
73 return boost::posix_time::ptime(boost::gregorian::date(1601,boost::gregorian::Jan,1),
74 boost::posix_time::hours(hoursSince1601)+
75 boost::posix_time::microseconds(microSecSince1601-hoursSince1601*60*60*1000000));
76#endif
77 }
78 void last_write_time(const std::string &p, const boost::posix_time::ptime &time) {
79#ifndef _WIN32
80 struct timeval times[2];
81 boost::posix_time::time_period sinceEpoch(boost::posix_time::ptime(boost::gregorian::date(1970, boost::gregorian::Jan, 1)), time);
82 times[0].tv_sec =sinceEpoch.length().total_seconds();
83 times[0].tv_usec=sinceEpoch.length().total_microseconds()-1000000*times[0].tv_sec;
84 times[1].tv_sec =times[0].tv_sec;
85 times[1].tv_usec=times[0].tv_usec;
86 if(utimes(p.c_str(), times)!=0)
87 throw std::runtime_error("system utimes call failed: "+p);
88#else
89 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);
90 if(f==INVALID_HANDLE_VALUE)
91 throw std::runtime_error("CreateFile failed: "+p);
92 boost::posix_time::time_period since1601(boost::posix_time::ptime(boost::gregorian::date(1601, boost::gregorian::Jan, 1)), time);
93 boost::posix_time::time_duration dt=since1601.length();
94 uint64_t winTime=((uint64_t)(dt.hours()))*60*60*10000000;
95 dt-=boost::posix_time::hours(dt.hours());
96 winTime+=dt.total_microseconds()*10;
97 FILETIME changeTime;
98 changeTime.dwHighDateTime=(winTime>>32);
99 changeTime.dwLowDateTime=(winTime & ((((uint64_t)1)<<32)-1));
100 if(SetFileTime(f, NULL, &changeTime, &changeTime)==0) {
101 CloseHandle(f);
102 throw std::runtime_error("SetFileTime failed: "+p);
103 }
104 CloseHandle(f);
105#endif
106 }
107
108}
109
110#endif