| // Copyright 2018 The Bazel Authors. All rights reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #include "src/main/cpp/util/path_platform.h" |
| |
| #include <limits.h> // PATH_MAX |
| |
| #include <stdlib.h> // getenv |
| #include <string.h> // strncmp |
| #include <unistd.h> // access, open, close, fsync |
| #include "src/main/cpp/util/errors.h" |
| #include "src/main/cpp/util/exit_code.h" |
| #include "src/main/cpp/util/file_platform.h" |
| #include "src/main/cpp/util/logging.h" |
| #include "src/main/cpp/util/path.h" |
| |
| namespace blaze_util { |
| |
| std::string ConvertPath(const std::string &path) { return path; } |
| |
| std::string PathAsJvmFlag(const std::string &path) { return path; } |
| |
| bool CompareAbsolutePaths(const std::string &a, const std::string &b) { |
| return a == b; |
| } |
| |
| std::pair<std::string, std::string> SplitPath(const std::string &path) { |
| size_t pos = path.rfind('/'); |
| |
| // Handle the case with no '/' in 'path'. |
| if (pos == std::string::npos) return std::make_pair("", path); |
| |
| // Handle the case with a single leading '/' in 'path'. |
| if (pos == 0) |
| return std::make_pair(std::string(path, 0, 1), std::string(path, 1)); |
| |
| return std::make_pair(std::string(path, 0, pos), std::string(path, pos + 1)); |
| } |
| |
| bool IsDevNull(const char *path) { |
| return path != nullptr && *path != 0 && strncmp("/dev/null\0", path, 10) == 0; |
| } |
| |
| bool IsRootDirectory(const std::string &path) { |
| return path.size() == 1 && path[0] == '/'; |
| } |
| |
| bool IsRootDirectory(const Path &path) { |
| return IsRootDirectory(path.AsNativePath()); |
| } |
| |
| bool IsAbsolute(const std::string &path) { |
| return !path.empty() && path[0] == '/'; |
| } |
| |
| std::string MakeAbsolute(const std::string &path) { |
| if (blaze_util::IsAbsolute(path) || path.empty()) { |
| return path; |
| } |
| |
| return JoinPath(blaze_util::GetCwd(), path); |
| } |
| |
| std::string ResolveEnvvars(const std::string &path) { |
| std::string result = path; |
| size_t start = 0; |
| while ((start = result.find("${", start)) != std::string::npos) { |
| // Just match to the next } |
| size_t end = result.find('}', start + 1); |
| if (end == std::string::npos) { |
| BAZEL_DIE(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR) |
| << "ResolveEnvvars(" << path << "): incomplete variable at position " |
| << start; |
| } |
| // Extract the variable name |
| const std::string name = result.substr(start + 2, end - start - 2); |
| // Get the value from the environment |
| const char *c_value = getenv(name.c_str()); |
| const std::string value = std::string(c_value ? c_value : ""); |
| result.replace(start, end - start + 1, value); |
| start += value.length(); |
| } |
| return result; |
| } |
| |
| std::string MakeAbsoluteAndResolveEnvvars(const std::string &path) { |
| return MakeAbsolute(ResolveEnvvars(path)); |
| } |
| |
| static std::string NormalizeAbsPath(const std::string &p) { |
| if (p.empty() || p[0] != '/') { |
| return ""; |
| } |
| typedef std::string::size_type index; |
| std::vector<std::pair<index, index> > segments; |
| for (index s = 0; s < p.size();) { |
| index e = p.find_first_of('/', s); |
| if (e == std::string::npos) { |
| e = p.size(); |
| } |
| if (e > s) { |
| if (p.compare(s, e - s, "..") == 0) { |
| if (!segments.empty()) { |
| segments.pop_back(); |
| } |
| } else if (p.compare(s, e - s, ".") != 0) { |
| segments.push_back(std::make_pair(s, e - s)); |
| } |
| } |
| s = e + 1; |
| } |
| if (segments.empty()) { |
| return "/"; |
| } else { |
| std::stringstream r; |
| for (const auto &s : segments) { |
| r << "/" << p.substr(s.first, s.second); |
| } |
| if (p[p.size() - 1] == '/') { |
| r << "/"; |
| } |
| return r.str(); |
| } |
| } |
| |
| std::string TestOnly_NormalizeAbsPath(const std::string &s) { |
| return NormalizeAbsPath(s); |
| } |
| |
| Path::Path(const std::string &path) |
| : path_(NormalizeAbsPath(MakeAbsolute(path))) {} |
| |
| Path::Path(const std::string &path, std::string *errorText) |
| : path_(NormalizeAbsPath(MakeAbsolute(path))) {} |
| |
| bool Path::IsNull() const { return path_ == "/dev/null"; } |
| |
| bool Path::Contains(const char c) const { |
| return path_.find_first_of(c) != std::string::npos; |
| } |
| |
| bool Path::Contains(const std::string &s) const { |
| return path_.find(s) != std::string::npos; |
| } |
| |
| Path Path::GetRelative(const std::string &r) const { |
| return Path(JoinPath(path_, r)); |
| } |
| |
| Path Path::Canonicalize() const { return Path(MakeCanonical(path_.c_str())); } |
| |
| Path Path::GetParent() const { return Path(SplitPath(path_).first); } |
| |
| std::string Path::AsPrintablePath() const { return path_; } |
| |
| std::string Path::AsJvmArgument() const { return path_; } |
| |
| std::string Path::AsCommandLineArgument() const { return path_; } |
| |
| } // namespace blaze_util |