Skip to content

Commit

Permalink
Use blaze_util::Path instead of std::string in more places.
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 698818638
Change-Id: Iea02eb6d3524ecc98970a63aa554927c701efe28
  • Loading branch information
tjgq authored and copybara-github committed Nov 21, 2024
1 parent 68cb6bf commit 6906ba6
Show file tree
Hide file tree
Showing 24 changed files with 470 additions and 561 deletions.
60 changes: 29 additions & 31 deletions src/main/cpp/archive_utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
#include "src/main/cpp/util/file.h"
#include "src/main/cpp/util/file_platform.h"
#include "src/main/cpp/util/logging.h"
#include "src/main/cpp/util/path.h"
#include "src/main/cpp/util/path_platform.h"
#include "third_party/ijar/zip.h"

namespace blaze {
Expand Down Expand Up @@ -116,12 +116,13 @@ std::optional<DurationMillis> ExtractData(
const string &self_path, const vector<string> &archive_contents,
const string &expected_install_md5, const StartupOptions &startup_options,
LoggingInfo *logging_info) {
const string &install_base = startup_options.install_base;
const blaze_util::Path &install_base = startup_options.install_base;
// If the install dir doesn't exist, create it, if it does, we know it's good.
if (!blaze_util::PathExists(install_base)) {
uint64_t st = GetMillisecondsMonotonic();
// Work in a temp dir to avoid races.
string tmp_install = blaze_util::CreateTempDir(install_base + ".tmp.");
// Work in a sibling temporary directory to avoid races.
blaze_util::Path tmp_install =
blaze_util::CreateSiblingTempDir(install_base);
ExtractArchiveOrDie(self_path, startup_options.product_name,
expected_install_md5, tmp_install);
BlessFiles(tmp_install);
Expand All @@ -144,7 +145,8 @@ std::optional<DurationMillis> ExtractData(
// (in case we're running on Windows) so we need to wait for that to
// finish and try renaming again.
++attempts;
BAZEL_LOG(USER) << "install base directory '" << tmp_install
BAZEL_LOG(USER) << "install base directory '"
<< tmp_install.AsPrintablePath()
<< "' could not be renamed into place after "
<< attempts << " second(s), trying again\r";
std::this_thread::sleep_for(std::chrono::seconds(1));
Expand All @@ -155,7 +157,7 @@ std::optional<DurationMillis> ExtractData(
if (attempts == 120) {
blaze_util::RemoveRecursively(tmp_install);
BAZEL_DIE(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR)
<< "install base directory '" << tmp_install
<< "install base directory '" << tmp_install.AsPrintablePath()
<< "' could not be renamed into place: "
<< blaze_util::GetLastErrorString();
}
Expand All @@ -165,7 +167,7 @@ std::optional<DurationMillis> ExtractData(
// us give a better error message.
if (!blaze_util::IsDirectory(install_base)) {
BAZEL_DIE(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR)
<< "install base directory '" << install_base
<< "install base directory '" << install_base.AsPrintablePath()
<< "' could not be created. It exists but is not a directory.";
}
blaze_util::Path install_dir(install_base);
Expand All @@ -175,8 +177,8 @@ std::optional<DurationMillis> ExtractData(
if (!IsUntampered(path)) {
BAZEL_DIE(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR)
<< "corrupt installation: file '" << path.AsPrintablePath()
<< "' is missing or modified. Please remove '" << install_base
<< "' and try again.";
<< "' is missing or modified. Please remove '"
<< install_base.AsPrintablePath() << "' and try again.";
}
}
// Also check that the installed files claim to match this binary.
Expand All @@ -191,7 +193,7 @@ std::optional<DurationMillis> ExtractData(
}
if (on_disk_key != expected_install_md5) {
BAZEL_DIE(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR)
<< "The install_base directory '" << install_base
<< "The install_base directory '" << install_base.AsPrintablePath()
<< "' contains a different " << startup_options.product_name
<< " version (found " << on_disk_key << " but this binary is "
<< expected_install_md5
Expand All @@ -209,7 +211,7 @@ void DetermineArchiveContents(const string &archive_path, vector<string> *files,

void ExtractArchiveOrDie(const string &archive_path, const string &product_name,
const string &expected_install_md5,
const string &output_dir) {
const blaze_util::Path &output_dir) {
string error;
std::unique_ptr<blaze::embedded_binaries::Dumper> dumper(
blaze::embedded_binaries::Create(&error));
Expand All @@ -219,17 +221,18 @@ void ExtractArchiveOrDie(const string &archive_path, const string &product_name,

if (!blaze_util::PathExists(output_dir)) {
BAZEL_DIE(blaze_exit_code::INTERNAL_ERROR)
<< "Archive output directory didn't exist: " << output_dir;
<< "Archive output directory didn't exist: "
<< output_dir.AsPrintablePath();
}

BAZEL_LOG(USER) << "Extracting " << product_name << " installation...";

PartialZipExtractor pze;
string install_md5 = pze.UnzipUntil(
archive_path, "install_base_key", nullptr,
[&](const char *name, const char *data, size_t size) {
dumper->Dump(data, size, blaze_util::JoinPath(output_dir, name));
});
string install_md5 =
pze.UnzipUntil(archive_path, "install_base_key", nullptr,
[&](const char *name, const char *data, size_t size) {
dumper->Dump(data, size, output_dir.GetRelative(name));
});

if (!dumper->Finish(&error)) {
BAZEL_DIE(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR)
Expand All @@ -248,55 +251,50 @@ void ExtractArchiveOrDie(const string &archive_path, const string &product_name,
}
}

void BlessFiles(const string &embedded_binaries) {
blaze_util::Path embedded_binaries_(embedded_binaries);

void BlessFiles(const blaze_util::Path &embedded_binaries) {
// Set the timestamps of the extracted files to the future and make sure (or
// at least as sure as we can...) that the files we have written are actually
// on the disk.

vector<string> extracted_files;
vector<blaze_util::Path> extracted_files;

// Walks the temporary directory recursively and collects full file paths.
blaze_util::GetAllFilesUnder(embedded_binaries, &extracted_files);

set<blaze_util::Path> synced_directories;
for (const auto &f : extracted_files) {
blaze_util::Path it(f);

for (const auto &file : extracted_files) {
// Set the time to a distantly futuristic value so we can observe tampering.
// Note that keeping a static, deterministic timestamp, such as the default
// timestamp set by unzip (1970-01-01) and using that to detect tampering is
// not enough, because we also need the timestamp to change between Bazel
// releases so that the metadata cache knows that the files may have
// changed. This is essential for the correctness of actions that use
// embedded binaries as artifacts.
if (!SetMtimeToDistantFuture(it)) {
if (!SetMtimeToDistantFuture(file)) {
string err = blaze_util::GetLastErrorString();
BAZEL_DIE(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR)
<< "failed to set timestamp on '" << it.AsPrintablePath()
<< "failed to set timestamp on '" << file.AsPrintablePath()
<< "': " << err;
}

blaze_util::SyncFile(it);
blaze_util::SyncFile(file);

blaze_util::Path directory = it.GetParent();
blaze_util::Path directory = file.GetParent();

// Now walk up until embedded_binaries and sync every directory in between.
// synced_directories is used to avoid syncing the same directory twice.
// The !directory.empty() and !blaze_util::IsRootDirectory(directory)
// conditions are not strictly needed, but it makes this loop more robust,
// because otherwise, if due to some glitch, directory was not under
// embedded_binaries, it would get into an infinite loop.
while (directory != embedded_binaries_ && !directory.IsEmpty() &&
while (directory != embedded_binaries && !directory.IsEmpty() &&
!blaze_util::IsRootDirectory(directory) &&
synced_directories.insert(directory).second) {
blaze_util::SyncFile(directory);
directory = directory.GetParent();
}
}

blaze_util::SyncFile(embedded_binaries_);
blaze_util::SyncFile(embedded_binaries);
}

void ExtractBuildLabel(const string &archive_path, string *build_label) {
Expand Down
4 changes: 2 additions & 2 deletions src/main/cpp/archive_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,14 +87,14 @@ std::optional<DurationMillis> ExtractData(
void ExtractArchiveOrDie(const std::string &archive_path,
const std::string &product_name,
const std::string &expected_install_md5,
const std::string &output_dir);
const blaze_util::Path &output_dir);

// Sets the timestamps of the extracted files to the future via
// blaze_util::IFileMtime::SetToDistanceFuture and ensures that the files we
// have written are actually on the disk. Later, the blaze client calls
// blaze_util::IFileMtime::IsUntampered to ensure the files were "blessed" with
// these distant mtimes.
void BlessFiles(const std::string &embedded_binaries);
void BlessFiles(const blaze_util::Path &embedded_binaries);

// Retrieves the build label (version string) from `archive_path` into
// `build_label`.
Expand Down
6 changes: 2 additions & 4 deletions src/main/cpp/bazel_startup_options.cc
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,9 @@ void BazelStartupOptions::MaybeLogStartupOptionWarnings() const {
"ignored, since --ignore_all_rc_files is on.";
}
}
bool output_user_root_has_space =
output_user_root.find_first_of(' ') != std::string::npos;
if (output_user_root_has_space) {
if (output_user_root.Contains(' ')) {
BAZEL_LOG(WARNING)
<< "Output user root \"" << output_user_root
<< "Output user root \"" << output_user_root.AsPrintablePath()
<< "\" contains a space. This will probably break the build. "
"You should set a different --output_user_root.";
} else if (output_base.Contains(' ')) {
Expand Down
44 changes: 22 additions & 22 deletions src/main/cpp/blaze.cc
Original file line number Diff line number Diff line change
Expand Up @@ -425,9 +425,9 @@ static vector<string> GetServerExeArgs(const blaze_util::Path &jvm_path,
blaze_util::ToString(startup_options.connect_timeout_secs));

result.push_back("--output_user_root=" +
blaze_util::ConvertPath(startup_options.output_user_root));
startup_options.output_user_root.AsCommandLineArgument());
result.push_back("--install_base=" +
blaze_util::ConvertPath(startup_options.install_base));
startup_options.install_base.AsCommandLineArgument());
result.push_back("--install_md5=" + install_md5);
result.push_back("--output_base=" +
startup_options.output_base.AsCommandLineArgument());
Expand Down Expand Up @@ -1006,13 +1006,13 @@ static void EnsureCorrectRunningVersion(const StartupOptions &startup_options,
// target dirs don't match, or if the symlink was not present, then kill any
// running servers. Lastly, symlink to our installation so others know which
// installation is running.
const blaze_util::Path installation_path =
const blaze_util::Path install_base_symlink =
startup_options.output_base.GetRelative("install");
string prev_installation;
bool ok =
blaze_util::ReadDirectorySymlink(installation_path, &prev_installation);
if (!ok || !blaze_util::CompareAbsolutePaths(prev_installation,
startup_options.install_base)) {
blaze_util::Path prev_install_base;
if (!blaze_util::ReadDirectorySymlink(install_base_symlink,
&prev_install_base) ||
!blaze_util::ArePathsEquivalent(prev_install_base,
startup_options.install_base)) {
if (server->Connected()) {
BAZEL_LOG(INFO)
<< "Killing running server because it is using another version of "
Expand All @@ -1021,23 +1021,24 @@ static void EnsureCorrectRunningVersion(const StartupOptions &startup_options,
logging_info->restart_reason = NEW_VERSION;
}

blaze_util::UnlinkPath(installation_path);
if (!SymlinkDirectories(startup_options.install_base, installation_path)) {
string err = GetLastErrorString();
blaze_util::UnlinkPath(install_base_symlink);
if (!SymlinkDirectories(startup_options.install_base,
install_base_symlink)) {
BAZEL_DIE(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR)
<< "failed to create installation symlink '"
<< installation_path.AsPrintablePath() << "': " << err;
<< install_base_symlink.AsPrintablePath()
<< "': " << GetLastErrorString();
}

// Update the mtime of the install base so that cleanup tools can
// find install bases that haven't been used for a long time.
// Ignore permissions errors (i.e. if the install base is not writable).
if (!SetMtimeToNowIfPossible(
blaze_util::Path(startup_options.install_base))) {
string err = GetLastErrorString();
BAZEL_DIE(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR)
<< "failed to set timestamp on '" << startup_options.install_base
<< "': " << err;
<< "failed to set timestamp on '"
<< startup_options.install_base.AsPrintablePath()
<< "': " << GetLastErrorString();
}
}
}
Expand Down Expand Up @@ -1142,24 +1143,23 @@ static void UpdateConfiguration(const string &install_md5,
// The default install_base is <output_user_root>/install/<md5(blaze)>
// but if an install_base is specified on the command line, we use that as
// the base instead.
if (startup_options->install_base.empty()) {
if (startup_options->install_base.IsEmpty()) {
if (server_mode) {
BAZEL_DIE(blaze_exit_code::BAD_ARGV)
<< "exec-server requires --install_base";
}
string install_user_root =
blaze_util::JoinPath(startup_options->output_user_root, "install");
startup_options->install_base =
blaze_util::JoinPath(install_user_root, install_md5);
blaze_util::Path install_user_root =
startup_options->output_user_root.GetRelative("install");
startup_options->install_base = install_user_root.GetRelative(install_md5);
}

if (startup_options->output_base.IsEmpty()) {
if (server_mode) {
BAZEL_DIE(blaze_exit_code::BAD_ARGV)
<< "exec-server requires --output_base";
}
startup_options->output_base = blaze_util::Path(
blaze::GetHashedBaseDir(startup_options->output_user_root, workspace));
startup_options->output_base =
blaze::GetHashedBaseDir(startup_options->output_user_root, workspace);
}

if (!blaze_util::PathExists(startup_options->output_base)) {
Expand Down
13 changes: 7 additions & 6 deletions src/main/cpp/blaze_util_platform.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include "src/main/cpp/util/path_platform.h"
// Copyright 2014 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -47,7 +48,7 @@ class Dumper {
// If writing fails, this method sets a flag in the `Dumper`, and `Finish`
// will return false. Subsequent `Dump` calls will have no effect.
virtual void Dump(const void* data, const size_t size,
const std::string& path) = 0;
const blaze_util::Path& path) = 0;

// Finishes dumping data.
//
Expand Down Expand Up @@ -187,16 +188,16 @@ int ExecuteDaemon(
const blaze_util::Path& exe, const std::vector<std::string>& args_vector,
const std::map<std::string, EnvVarValue>& env,
const blaze_util::Path& daemon_output, const bool daemon_output_append,
const std::string& binaries_dir, const blaze_util::Path& server_dir,
const blaze_util::Path& binaries_dir, const blaze_util::Path& server_dir,
const StartupOptions& options, BlazeServerStartup** server_startup);

// A character used to separate paths in a list.
extern const char kListSeparator;

// Create a symlink to directory ``target`` at location ``link``.
// Returns true on success, false on failure. The target must be absolute.
// Returns true on success, false on failure.
// Implemented via junctions on Windows.
bool SymlinkDirectories(const std::string& target,
bool SymlinkDirectories(const blaze_util::Path& target,
const blaze_util::Path& link);

typedef uintptr_t LockHandle;
Expand Down Expand Up @@ -237,8 +238,8 @@ void ExcludePathFromBackup(const blaze_util::Path& path);

// Returns the canonical form of the base dir given a root and a hashable
// string. The resulting dir is composed of the root + md5(hashable)
std::string GetHashedBaseDir(const std::string& root,
const std::string& hashable);
blaze_util::Path GetHashedBaseDir(const blaze_util::Path& root,
const std::string& hashable);

// Create a safe installation directory where we keep state, installations etc.
// This method ensures that the directory is created, is owned by the current
Expand Down
Loading

0 comments on commit 6906ba6

Please sign in to comment.