summaryrefslogtreecommitdiffstats
path: root/src/disk_interface.cc
diff options
context:
space:
mode:
authorEvan Martin <martine@danga.com>2011-12-20 20:13:11 (GMT)
committerEvan Martin <martine@danga.com>2011-12-20 20:13:11 (GMT)
commit93c78361e30e33f950eef754742b236251e2c81e (patch)
treec054fb902a71b4892a76280e5e38adda8bc4b664 /src/disk_interface.cc
parentbf9116ffbb9c9fdfa8a38fa681b25dd34092ad43 (diff)
downloadNinja-93c78361e30e33f950eef754742b236251e2c81e.zip
Ninja-93c78361e30e33f950eef754742b236251e2c81e.tar.gz
Ninja-93c78361e30e33f950eef754742b236251e2c81e.tar.bz2
windows: use GetFileAttributesEx instead of stat
From a Hacker News comment: "Recent finding, that sped up our systems from 15->3sec on 300,000+ files filestamp check was to move from _stat to GetFileAttributesEx." I do recall reading that calls to stat() on Windows were one of the potential reasons Subversion is so slow on Windows...
Diffstat (limited to 'src/disk_interface.cc')
-rw-r--r--src/disk_interface.cc33
1 files changed, 27 insertions, 6 deletions
diff --git a/src/disk_interface.cc b/src/disk_interface.cc
index d82b544..b60cd6f 100644
--- a/src/disk_interface.cc
+++ b/src/disk_interface.cc
@@ -19,6 +19,10 @@
#include <string.h>
#include <sys/stat.h>
+#ifdef WIN32
+#include <windows.h>
+#endif
+
#include "util.h"
namespace {
@@ -62,17 +66,34 @@ bool DiskInterface::MakeDirs(const std::string& path) {
// RealDiskInterface -----------------------------------------------------------
int RealDiskInterface::Stat(const std::string& path) {
+#ifdef WIN32
+ WIN32_FILE_ATTRIBUTE_DATA attrs;
+ if (!GetFileAttributesEx(path.c_str(), GetFileExInfoStandard, &attrs)) {
+ if (GetLastError() == ERROR_FILE_NOT_FOUND)
+ return 0;
+ Error("GetFileAttributesEx(%s): %s", path.c_str(),
+ GetLastErrorString().c_str());
+ return -1;
+ }
+ const FILETIME& filetime = attrs.ftLastWriteTime;
+ // FILETIME is in 100-nanosecond increments since the Windows epoch.
+ // We don't much care about epoch correctness but we do want the
+ // resulting value to fit in an integer.
+ uint64_t mtime = ((uint64_t)filetime.dwHighDateTime << 32) |
+ ((uint64_t)filetime.dwLowDateTime);
+ mtime /= 1000000000LL / 100; // 100ns -> s.
+ mtime -= 12622770400LL; // 1600 epoch -> 2000 epoch (subtract 400 years).
+ return mtime;
+#else
struct stat st;
if (stat(path.c_str(), &st) < 0) {
- if (errno == ENOENT) {
+ if (errno == ENOENT)
return 0;
- } else {
- Error("stat(%s): %s", path.c_str(), strerror(errno));
- return -1;
- }
+ Error("stat(%s): %s", path.c_str(), strerror(errno));
+ return -1;
}
-
return st.st_mtime;
+#endif
}
bool RealDiskInterface::MakeDir(const std::string& path) {