1 // Copyright 2011 Google Inc. All Rights Reserved.
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 #include "disk_interface.h"
30 string DirName(const string& path) {
32 const char kPathSeparator = '\\';
34 const char kPathSeparator = '/';
37 string::size_type slash_pos = path.rfind(kPathSeparator);
38 if (slash_pos == string::npos)
39 return string(); // Nothing to do.
40 while (slash_pos > 0 && path[slash_pos - 1] == kPathSeparator)
42 return path.substr(0, slash_pos);
47 // DiskInterface ---------------------------------------------------------------
49 bool DiskInterface::MakeDirs(const string& path) {
50 string dir = DirName(path);
52 return true; // Reached root; assume it's there.
53 TimeStamp mtime = Stat(dir);
55 return false; // Error.
57 return true; // Exists already; we're done.
59 // Directory doesn't exist. Try creating its parent first.
60 bool success = MakeDirs(dir);
66 // RealDiskInterface -----------------------------------------------------------
68 TimeStamp RealDiskInterface::Stat(const string& path) {
70 _WIN32_FILE_ATTRIBUTE_DATA attrs;
71 if (!GetFileAttributesEx(path.c_str(), GetFileExInfoStandard, &attrs)) {
72 DWORD err = GetLastError();
73 if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND)
75 Error("GetFileAttributesEx(%s): %s", path.c_str(),
76 GetLastErrorString().c_str());
79 const FILETIME& filetime = attrs.ftLastWriteTime;
80 // FILETIME is in 100-nanosecond increments since the Windows epoch.
81 // We don't much care about epoch correctness but we do want the
82 // resulting value to fit in an integer.
83 uint64_t mtime = ((uint64_t)filetime.dwHighDateTime << 32) |
84 ((uint64_t)filetime.dwLowDateTime);
85 mtime /= 1000000000LL / 100; // 100ns -> s.
86 mtime -= 12622770400LL; // 1600 epoch -> 2000 epoch (subtract 400 years).
87 return (TimeStamp)mtime;
90 if (stat(path.c_str(), &st) < 0) {
93 Error("stat(%s): %s", path.c_str(), strerror(errno));
100 bool RealDiskInterface::MakeDir(const string& path) {
101 if (::MakeDir(path) < 0) {
102 Error("mkdir(%s): %s", path.c_str(), strerror(errno));
108 string RealDiskInterface::ReadFile(const string& path, string* err) {
110 int ret = ::ReadFile(path, &contents, err);
111 if (ret == -ENOENT) {
118 int RealDiskInterface::RemoveFile(const string& path) {
119 if (remove(path.c_str()) < 0) {
124 Error("remove(%s): %s", path.c_str(), strerror(errno));