blob: 214372abd6b53d3b588c4329a692a6b2db34ebff [file]
// Copyright 2016 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/file_platform.h"
#include <windows.h>
#include "src/main/cpp/util/errors.h"
#include "src/main/cpp/util/file.h"
namespace blaze_util {
using std::string;
class WindowsPipe : public IPipe {
public:
bool Send(void* buffer, int size) override {
// TODO(bazel-team): implement this.
pdie(255, "blaze_util::WindowsPipe::Send is not yet implemented");
return false;
}
int Receive(void* buffer, int size) override {
// TODO(bazel-team): implement this.
pdie(255, "blaze_util::WindowsPipe::Receive is not yet implemented");
return 0;
}
};
IPipe* CreatePipe() {
// TODO(bazel-team): implement this.
pdie(255, "blaze_util::CreatePipe is not implemented on Windows");
return nullptr;
}
bool ReadFile(const string& filename, string* content, int max_size) {
// TODO(bazel-team): implement this.
pdie(255, "blaze_util::ReadFile is not implemented on Windows");
return false;
}
bool WriteFile(const void* data, size_t size, const string& filename) {
// TODO(bazel-team): implement this.
pdie(255, "blaze_util::WriteFile is not implemented on Windows");
return false;
}
bool UnlinkPath(const string& file_path) {
// TODO(bazel-team): implement this.
pdie(255, "blaze_util::UnlinkPath is not implemented on Windows");
return false;
}
string Which(const string &executable) {
pdie(255, "blaze_util::Which is not implemented on Windows");
return "";
}
bool PathExists(const string& path) {
// TODO(bazel-team): implement this.
pdie(255, "blaze_util::PathExists is not implemented on Windows");
return false;
}
string MakeCanonical(const char *path) {
// TODO(bazel-team): implement this.
pdie(255, "blaze_util::MakeCanonical is not implemented on Windows");
return "";
}
bool CanAccess(const string& path, bool read, bool write, bool exec) {
// TODO(bazel-team): implement this.
pdie(255, "blaze_util::CanAccess is not implemented on Windows");
return false;
}
bool IsDirectory(const string& path) {
// TODO(bazel-team): implement this.
pdie(255, "blaze_util::IsDirectory is not implemented on Windows");
return false;
}
void SyncFile(const string& path) {
// No-op on Windows native; unsupported by Cygwin.
}
time_t GetMtimeMillisec(const string& path) {
// TODO(bazel-team): implement this.
pdie(255, "blaze_util::GetMtimeMillisec is not implemented on Windows");
return -1;
}
bool SetMtimeMillisec(const string& path, time_t mtime) {
// TODO(bazel-team): implement this.
pdie(255, "blaze_util::SetMtimeMillisec is not implemented on Windows");
return false;
}
#ifdef COMPILER_MSVC
bool MakeDirectories(const string& path, unsigned int mode) {
// TODO(bazel-team): implement this.
pdie(255, "blaze::MakeDirectories is not implemented on Windows");
return false;
}
#else // not COMPILER_MSVC
// Runs "stat" on `path`. Returns -1 and sets errno if stat fails or
// `path` isn't a directory. If check_perms is true, this will also
// make sure that `path` is owned by the current user and has `mode`
// permissions (observing the umask). It attempts to run chmod to
// correct the mode if necessary. If `path` is a symlink, this will
// check ownership of the link, not the underlying directory.
static bool GetDirectoryStat(const string& path, mode_t mode,
bool check_perms) {
struct stat filestat = {};
if (stat(path.c_str(), &filestat) == -1) {
return false;
}
if (!S_ISDIR(filestat.st_mode)) {
errno = ENOTDIR;
return false;
}
if (check_perms) {
// If this is a symlink, run checks on the link. (If we did lstat above
// then it would return false for ISDIR).
struct stat linkstat = {};
if (lstat(path.c_str(), &linkstat) != 0) {
return false;
}
if (linkstat.st_uid != geteuid()) {
// The directory isn't owned by me.
errno = EACCES;
return false;
}
mode_t mask = umask(022);
umask(mask);
mode = (mode & ~mask);
if ((filestat.st_mode & 0777) != mode && chmod(path.c_str(), mode) == -1) {
// errno set by chmod.
return false;
}
}
return true;
}
static bool MakeDirectories(const string& path, mode_t mode, bool childmost) {
if (path.empty() || path == "/") {
errno = EACCES;
return false;
}
bool stat_succeeded = GetDirectoryStat(path, mode, childmost);
if (stat_succeeded) {
return true;
}
if (errno == ENOENT) {
// Path does not exist, attempt to create its parents, then it.
string parent = Dirname(path);
if (!MakeDirectories(parent, mode, false)) {
// errno set by stat.
return false;
}
if (mkdir(path.c_str(), mode) == -1) {
if (errno == EEXIST) {
if (childmost) {
// If there are multiple bazel calls at the same time then the
// directory could be created between the MakeDirectories and mkdir
// calls. This is okay, but we still have to check the permissions.
return GetDirectoryStat(path, mode, childmost);
} else {
// If this isn't the childmost directory, we don't care what the
// permissions were. If it's not even a directory then that error will
// get caught when we attempt to create the next directory down the
// chain.
return true;
}
}
// errno set by mkdir.
return false;
}
return true;
}
return stat_succeeded;
}
// mkdir -p path. Returns 0 if the path was created or already exists and could
// be chmod-ed to exactly the given permissions. If final part of the path is a
// symlink, this ensures that the destination of the symlink has the desired
// permissions. It also checks that the directory or symlink is owned by us.
// On failure, this returns -1 and sets errno.
bool MakeDirectories(const string& path, mode_t mode) {
return MakeDirectories(path, mode, true);
}
#endif // COMPILER_MSVC
string GetCwd() {
// TODO(bazel-team): implement this.
pdie(255, "blaze_util::GetCwd is not implemented on Windows");
return "";
}
bool ChangeDirectory(const string& path) {
// TODO(bazel-team): implement this.
pdie(255, "blaze_util::ChangeDirectory is not implemented on Windows");
return false;
}
void ForEachDirectoryEntry(const string &path,
DirectoryEntryConsumer *consume) {
// TODO(bazel-team): implement this.
pdie(255, "blaze_util::ForEachDirectoryEntry is not implemented on Windows");
}
} // namespace blaze_util