Ninja
disk_interface.cc
Go to the documentation of this file.
00001 // Copyright 2011 Google Inc. All Rights Reserved.
00002 //
00003 // Licensed under the Apache License, Version 2.0 (the "License");
00004 // you may not use this file except in compliance with the License.
00005 // You may obtain a copy of the License at
00006 //
00007 //     http://www.apache.org/licenses/LICENSE-2.0
00008 //
00009 // Unless required by applicable law or agreed to in writing, software
00010 // distributed under the License is distributed on an "AS IS" BASIS,
00011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00012 // See the License for the specific language governing permissions and
00013 // limitations under the License.
00014 
00015 #include "disk_interface.h"
00016 
00017 #include <errno.h>
00018 #include <stdio.h>
00019 #include <string.h>
00020 #include <sys/stat.h>
00021 
00022 #include "util.h"
00023 
00024 namespace {
00025 
00026 std::string DirName(const std::string& path) {
00027 #ifdef WIN32
00028   const char kPathSeparator = '\\';
00029 #else
00030   const char kPathSeparator = '/';
00031 #endif
00032 
00033   std::string::size_type slash_pos = path.rfind(kPathSeparator);
00034   if (slash_pos == std::string::npos)
00035     return std::string();  // Nothing to do.
00036   while (slash_pos > 0 && path[slash_pos - 1] == kPathSeparator)
00037     --slash_pos;
00038   return path.substr(0, slash_pos);
00039 }
00040 
00041 }  // namespace
00042 
00043 // DiskInterface ---------------------------------------------------------------
00044 
00045 bool DiskInterface::MakeDirs(const std::string& path) {
00046   std::string dir = DirName(path);
00047   if (dir.empty())
00048     return true;  // Reached root; assume it's there.
00049   int mtime = Stat(dir);
00050   if (mtime < 0)
00051     return false;  // Error.
00052   if (mtime > 0)
00053     return true;  // Exists already; we're done.
00054 
00055   // Directory doesn't exist.  Try creating its parent first.
00056   bool success = MakeDirs(dir);
00057   if (!success)
00058     return false;
00059   return MakeDir(dir);
00060 }
00061 
00062 // RealDiskInterface -----------------------------------------------------------
00063 
00064 int RealDiskInterface::Stat(const std::string& path) {
00065   struct stat st;
00066   if (stat(path.c_str(), &st) < 0) {
00067     if (errno == ENOENT) {
00068       return 0;
00069     } else {
00070       Error("stat(%s): %s", path.c_str(), strerror(errno));
00071       return -1;
00072     }
00073   }
00074 
00075   return st.st_mtime;
00076   return true;
00077 }
00078 
00079 bool RealDiskInterface::MakeDir(const std::string& path) {
00080   if (::MakeDir(path) < 0) {
00081     Error("mkdir(%s): %s", path.c_str(), strerror(errno));
00082     return false;
00083   }
00084   return true;
00085 }
00086 
00087 std::string RealDiskInterface::ReadFile(const std::string& path,
00088                                         std::string* err) {
00089   std::string contents;
00090   int ret = ::ReadFile(path, &contents, err);
00091   if (ret == -ENOENT) {
00092     // Swallow ENOENT.
00093     err->clear();
00094   }
00095   return contents;
00096 }
00097 
00098 int RealDiskInterface::RemoveFile(const std::string& path) {
00099   if (remove(path.c_str()) < 0) {
00100     switch (errno) {
00101       case ENOENT:
00102         return 1;
00103       default:
00104         Error("remove(%s): %s", path.c_str(), strerror(errno));
00105         return -1;
00106     }
00107   } else {
00108     return 0;
00109   }
00110 }