update_engine: Share payloads for a maximum of five days only.
This helps limit exposure of what version the device may or may not be
running.
BUG=chromium:424823
TEST=New unit test + unit tests pass.
Change-Id: I9db6f8d560e359c2b8a65d1381dc44320ed4b3a1
Reviewed-on: https://chromium-review.googlesource.com/227592
Reviewed-by: Gilad Arnold <garnold@chromium.org>
Tested-by: David Zeuthen <zeuthen@chromium.org>
Commit-Queue: David Zeuthen <zeuthen@chromium.org>
diff --git a/p2p_manager.cc b/p2p_manager.cc
index 240b44a..abfb3d7 100644
--- a/p2p_manager.cc
+++ b/p2p_manager.cc
@@ -96,8 +96,10 @@
public:
P2PManagerImpl(Configuration *configuration,
PrefsInterface *prefs,
+ ClockInterface *clock,
const string& file_extension,
- const int num_files_to_keep);
+ const int num_files_to_keep,
+ const base::TimeDelta& max_file_age);
// P2PManager methods.
virtual void SetDevicePolicy(const policy::DevicePolicy* device_policy);
@@ -138,6 +140,10 @@
// Utility function used by EnsureP2PRunning() and EnsureP2PNotRunning().
bool EnsureP2P(bool should_be_running);
+ // Utility function to delete a file given by |path| and log the
+ // path as well as |reason|. Returns false on failure.
+ bool DeleteP2PFile(const FilePath& path, const std::string& reason);
+
// The device policy being used or null if no policy is being used.
const policy::DevicePolicy* device_policy_;
@@ -147,6 +153,9 @@
// Object for persisted state.
PrefsInterface* prefs_;
+ // Object for telling the time.
+ ClockInterface* clock_;
+
// A short string unique to the application (for example "cros_au")
// used to mark a file as being owned by a particular application.
const string file_extension_;
@@ -156,6 +165,10 @@
// performing housekeeping.
const int num_files_to_keep_;
+ // If non-zero, files older than this will not be kept after
+ // performing housekeeping.
+ const base::TimeDelta max_file_age_;
+
// The string ".p2p".
static const char kP2PExtension[];
@@ -174,12 +187,16 @@
P2PManagerImpl::P2PManagerImpl(Configuration *configuration,
PrefsInterface *prefs,
+ ClockInterface *clock,
const string& file_extension,
- const int num_files_to_keep)
+ const int num_files_to_keep,
+ const base::TimeDelta& max_file_age)
: device_policy_(nullptr),
prefs_(prefs),
+ clock_(clock),
file_extension_(file_extension),
- num_files_to_keep_(num_files_to_keep) {
+ num_files_to_keep_(num_files_to_keep),
+ max_file_age_(max_file_age) {
configuration_.reset(configuration != nullptr ? configuration :
new ConfigurationImpl());
}
@@ -318,27 +335,35 @@
return configuration_->GetP2PDir().Append(file_id + GetExt(visibility));
}
-bool P2PManagerImpl::PerformHousekeeping() {
- GDir* dir = nullptr;
- GError* error = nullptr;
- const char* name = nullptr;
- vector<pair<FilePath, Time>> matches;
+bool P2PManagerImpl::DeleteP2PFile(const FilePath& path,
+ const std::string& reason) {
+ LOG(INFO) << "Deleting p2p file " << path.value()
+ << " (reason: " << reason << ")";
+ if (unlink(path.value().c_str()) != 0) {
+ PLOG(ERROR) << "Error deleting p2p file " << path.value();
+ return false;
+ }
+ return true;
+}
- // Go through all files in the p2p dir and pick the ones that match
- // and get their ctime.
+
+bool P2PManagerImpl::PerformHousekeeping() {
+ // Open p2p dir.
FilePath p2p_dir = configuration_->GetP2PDir();
- dir = g_dir_open(p2p_dir.value().c_str(), 0, &error);
+ GError* error = nullptr;
+ GDir* dir = g_dir_open(p2p_dir.value().c_str(), 0, &error);
if (dir == nullptr) {
LOG(ERROR) << "Error opening directory " << p2p_dir.value() << ": "
<< utils::GetAndFreeGError(&error);
return false;
}
- if (num_files_to_keep_ == 0)
- return true;
-
+ // Go through all files and collect their mtime.
string ext_visible = GetExt(kVisible);
string ext_non_visible = GetExt(kNonVisible);
+ bool deletion_failed = false;
+ const char* name = nullptr;
+ vector<pair<FilePath, Time>> matches;
while ((name = g_dir_read_name(dir)) != nullptr) {
if (!(g_str_has_suffix(name, ext_visible.c_str()) ||
g_str_has_suffix(name, ext_non_visible.c_str())))
@@ -351,26 +376,34 @@
continue;
}
- Time time = utils::TimeFromStructTimespec(&statbuf.st_ctim);
- matches.push_back(std::make_pair(file, time));
+ Time time = utils::TimeFromStructTimespec(&statbuf.st_mtim);
+
+ // If instructed to keep only files younger than a given age
+ // (|max_file_age_| != 0), delete files satisfying this criteria
+ // right now. Otherwise add it to a list we'll consider for later.
+ if (clock_ != nullptr && max_file_age_ != base::TimeDelta() &&
+ clock_->GetWallclockTime() - time > max_file_age_) {
+ if (!DeleteP2PFile(file, "file too old"))
+ deletion_failed = true;
+ } else {
+ matches.push_back(std::make_pair(file, time));
+ }
}
g_dir_close(dir);
- // Sort list of matches, newest (biggest time) to oldest (lowest time).
- std::sort(matches.begin(), matches.end(), MatchCompareFunc);
-
- // Delete starting at element num_files_to_keep_.
- vector<pair<FilePath, Time>>::const_iterator i;
- for (i = matches.begin() + num_files_to_keep_; i < matches.end(); ++i) {
- const FilePath& file = i->first;
- LOG(INFO) << "Deleting p2p file " << file.value();
- if (unlink(file.value().c_str()) != 0) {
- PLOG(ERROR) << "Error deleting p2p file " << file.value();
- return false;
+ // If instructed to only keep N files (|max_files_to_keep_ != 0),
+ // sort list of matches, newest (biggest time) to oldest (lowest
+ // time). Then delete starting at element |num_files_to_keep_|.
+ if (num_files_to_keep_ > 0) {
+ std::sort(matches.begin(), matches.end(), MatchCompareFunc);
+ vector<pair<FilePath, Time>>::const_iterator i;
+ for (i = matches.begin() + num_files_to_keep_; i < matches.end(); ++i) {
+ if (!DeleteP2PFile(i->first, "too many files"))
+ deletion_failed = true;
}
}
- return true;
+ return !deletion_failed;
}
// Helper class for implementing LookupUrlForFile().
@@ -774,12 +807,16 @@
P2PManager* P2PManager::Construct(Configuration *configuration,
PrefsInterface *prefs,
+ ClockInterface *clock,
const string& file_extension,
- const int num_files_to_keep) {
+ const int num_files_to_keep,
+ const base::TimeDelta& max_file_age) {
return new P2PManagerImpl(configuration,
prefs,
+ clock,
file_extension,
- num_files_to_keep);
+ num_files_to_keep,
+ max_file_age);
}
} // namespace chromeos_update_engine