blob: 294f2cf079ad367be8fe016870179ebede79dc38 [file] [log] [blame] [edit]
// Copyright 2024 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <base/at_exit.h>
#include <base/check.h>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/logging.h>
#include <base/timer/elapsed_timer.h>
#include <brillo/cryptohome.h>
#include <brillo/files/safe_fd.h>
#include <brillo/flag_helper.h>
#include <brillo/syslog_logging.h>
namespace {
constexpr char kExecName[] = "extended-updates-arc-remove-data";
// Copied from ArcSetup::RemoveStaleDataDirectory().
// TODO(niwa): Consolidate into a shared utility for broader reuse.
bool SafeRemoveDir(const base::FilePath& path) {
constexpr int kRmdirMaxDepth = 768;
brillo::SafeFD root_fd = brillo::SafeFD::Root().first;
brillo::SafeFD::SafeFDResult parent_dir =
root_fd.OpenExistingDir(path.DirName());
if (brillo::SafeFD::IsError(parent_dir.second)) {
if (parent_dir.second != brillo::SafeFD::Error::kDoesNotExist) {
LOG(ERROR) << "Errors while removing data from " << path
<< ": failed to open the parent directory";
}
return false;
}
brillo::SafeFD::Error err =
parent_dir.first.Rmdir(path.BaseName().value(), true /*recursive*/,
kRmdirMaxDepth, true /*keep_going*/);
if (brillo::SafeFD::IsError(err) &&
err != brillo::SafeFD::Error::kDoesNotExist) {
LOG(ERROR) << "Errors while removing data from " << path
<< ": failed to remove the directory";
return false;
}
return true;
}
// Removes /home/root/<user_hash>/{android-data,android-data-old}
bool RemoveAndroidDataDirs(const std::string& chromeos_user) {
brillo::cryptohome::home::Username username(chromeos_user);
const base::FilePath root_path =
brillo::cryptohome::home::GetRootPath(username);
CHECK(!root_path.empty() && base::DirectoryExists(root_path));
const base::FilePath android_data_dir = root_path.Append("android-data");
const base::FilePath android_data_old_dir =
root_path.Append("android-data-old");
bool success = true;
if (base::DirectoryExists(android_data_dir)) {
LOG(INFO) << "Removing " << android_data_dir;
success &= SafeRemoveDir(android_data_dir);
}
if (base::DirectoryExists(android_data_old_dir)) {
LOG(INFO) << "Removing " << android_data_old_dir;
success &= SafeRemoveDir(android_data_old_dir);
}
return success;
}
} // namespace
int main(int argc, char** argv) {
DEFINE_string(chromeos_user, "", "Target user name (CHROMEOS_USER)");
base::ElapsedTimer timer;
base::AtExitManager at_exit;
brillo::FlagHelper::Init(argc, argv, kExecName);
brillo::OpenLog(kExecName, true /*log_pid*/);
brillo::InitLog(brillo::kLogToSyslog | brillo::kLogHeader |
brillo::kLogToStderrIfTty);
CHECK(!FLAGS_chromeos_user.empty()) << "Must specify --chromeos_user";
const bool success = RemoveAndroidDataDirs(FLAGS_chromeos_user);
// TODO(b/327140239): Support data removal for devices using virtio-blk /data
LOG(INFO) << kExecName << " took "
<< timer.Elapsed().InMillisecondsRoundedUp() << "ms";
return success ? 0 : 1;
}