All Classes Namespaces Functions Variables 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 #include <windows.h>
42 #endif
43 
44 namespace boost {
45  namespace 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 
109 #endif

Impressum / Disclaimer / Datenschutz Generated by doxygen 1.8.5 Valid HTML