blob: 11b939e34b15d1fa7adce477689c9d172e79b593 [file] [log] [blame] [edit]
// Copyright 2023 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <fstream>
#include <unistd.h>
#include <base/logging.h>
namespace {
const char kResetCounterPath[] = "/var/lib/metrics/structured/reset-counter";
const int kMaxResetCounterLength = 19;
} // namespace
int main(int argc, char** argv) {
if (argc != 1) {
LOG(ERROR) << "Unexpected command line arguments";
return 1;
}
int64_t reset_counter = 0;
std::ifstream infile(kResetCounterPath);
if (!infile.is_open()) {
PLOG(ERROR) << "Error when opening input file " << kResetCounterPath;
return 1;
}
// Get the length of the reset counter integer in the file. There could be
// the following situations:
// - length > 0 and length <= kMaxResetCounterLength: The length is valid.
// Read the reset counter value from the file.
// - length == 0: The file is empty. This could happen if it is the first
// time to boot or after power wash.
// - length > kMaxResetCounterLength: The file is corrupted. It is not
// possible that the reset counter value can be so large.
// - length < 0: Can not get the length.
infile.seekg(0, infile.end);
int length = infile.tellg();
infile.seekg(0, infile.beg);
if (length > 0 && length <= kMaxResetCounterLength) {
infile >> reset_counter;
if (infile.bad()) {
PLOG(ERROR) << "Error when reading " << kResetCounterPath;
return 1;
}
if (reset_counter < 0 || reset_counter == INT64_MAX) {
// This should not happen unless the file is corrupted. In that case,
// reset the reset counter.
reset_counter = 0;
LOG(ERROR) << "Invalid reset counter value. The reset counter is reset.";
}
} else if (length != 0) {
// This should not happen unless the file is corrupted. In that case,
// reset the reset counter.
LOG(ERROR) << "Invalid reset counter value. The reset counter is reset.";
}
infile.close();
if (infile.fail()) {
PLOG(ERROR) << "Error when closing input file " << kResetCounterPath;
}
// Increment the reset counter.
reset_counter++;
// Update the reset counter file.
std::ofstream outfile(kResetCounterPath);
if (!outfile.is_open()) {
// Only metrics and root will be able to open the output file. Other users
// will get permission denied.
PLOG(ERROR) << "Error when opening output file " << kResetCounterPath;
return 1;
}
outfile << reset_counter;
if (outfile.bad()) {
PLOG(ERROR) << "Error when writing " << kResetCounterPath;
return 1;
}
outfile.close();
if (outfile.fail()) {
PLOG(ERROR) << "Error when closing output file " << kResetCounterPath;
}
return 0;
}