std::vector<BootEventRecordStore::BootEventRecord> BootEventRecordStore:: GetAllBootEvents() const { std::vector<BootEventRecord> events; std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(store_path_.c_str()), closedir); // This case could happen due to external manipulation of the filesystem, // so crash out if the record store doesn't exist. CHECK_NE(static_cast<DIR*>(nullptr), dir.get()); struct dirent* entry; while ((entry = readdir(dir.get())) != NULL) { // Only parse regular files. if (entry->d_type != DT_REG) { continue; } const std::string event = entry->d_name; const std::string record_path = GetBootEventPath(event); int32_t uptime; if (!ParseRecordEventTime(record_path, &uptime)) { LOG(ERROR) << "Failed to parse boot time record: " << record_path; continue; } events.push_back(std::make_pair(event, uptime)); } return events; }
bool BootEventRecordStore::GetBootEvent( const std::string& event, BootEventRecord* record) const { CHECK_NE(static_cast<BootEventRecord*>(nullptr), record); CHECK(!event.empty()); const std::string record_path = GetBootEventPath(event); int32_t uptime; if (!ParseRecordEventTime(record_path, &uptime)) { LOG(ERROR) << "Failed to parse boot time record: " << record_path; return false; } *record = std::make_pair(event, uptime); return true; }
// The implementation of AddBootEventValue makes use of the mtime file // attribute to store the value associated with a boot event in order to // optimize on-disk size requirements and small-file thrashing. void BootEventRecordStore::AddBootEventWithValue( const std::string& name, int32_t value) { std::string record_path = GetBootEventPath(name); if (creat(record_path.c_str(), S_IRUSR | S_IWUSR) == -1) { PLOG(ERROR) << "Failed to create " << record_path; } // Fill out the stat structure for |record_path| in order to get the atime to // set in the utime() call. struct stat file_stat; if (stat(record_path.c_str(), &file_stat) == -1) { PLOG(ERROR) << "Failed to read " << record_path; } // Set the |modtime| of the file to store the value of the boot event while // preserving the |actime| (as read by stat). struct utimbuf times = {/* actime */ file_stat.st_atime, /* modtime */ value}; if (utime(record_path.c_str(), ×) == -1) { PLOG(ERROR) << "Failed to set mtime for " << record_path; } }
// The implementation of AddBootEventValue makes use of the mtime file // attribute to store the value associated with a boot event in order to // optimize on-disk size requirements and small-file thrashing. void BootEventRecordStore::AddBootEventWithValue( const std::string& event, int32_t value) { std::string record_path = GetBootEventPath(event); int record_fd = creat(record_path.c_str(), S_IRUSR | S_IWUSR); if (record_fd == -1) { PLOG(ERROR) << "Failed to create " << record_path; return; } // Writing the value as content in the record file is a debug measure to // ensure the validity of the file mtime value, i.e., to check that the record // file mtime values are not changed once set. // TODO(jhawkins): Remove this block. if (!android::base::WriteStringToFd(std::to_string(value), record_fd)) { PLOG(ERROR) << "Failed to write value to " << record_path; close(record_fd); return; } // Fill out the stat structure for |record_path| in order to get the atime to // set in the utime() call. struct stat file_stat; if (stat(record_path.c_str(), &file_stat) == -1) { PLOG(ERROR) << "Failed to read " << record_path; close(record_fd); return; } // Set the |modtime| of the file to store the value of the boot event while // preserving the |actime| (as read by stat). struct utimbuf times = {/* actime */ file_stat.st_atime, /* modtime */ value}; if (utime(record_path.c_str(), ×) == -1) { PLOG(ERROR) << "Failed to set mtime for " << record_path; close(record_fd); return; } close(record_fd); }
void BootEventRecordStore::AddBootEvent(const std::string& name) { std::string uptime_str; if (!android::base::ReadFileToString("/proc/uptime", &uptime_str)) { LOG(ERROR) << "Failed to read /proc/uptime"; } std::string record_path = GetBootEventPath(name); if (creat(record_path.c_str(), S_IRUSR | S_IWUSR) == -1) { PLOG(ERROR) << "Failed to create " << record_path; } struct stat file_stat; if (stat(record_path.c_str(), &file_stat) == -1) { PLOG(ERROR) << "Failed to read " << record_path; } // Cast intentionally rounds down. time_t uptime = static_cast<time_t>(strtod(uptime_str.c_str(), NULL)); struct utimbuf times = {file_stat.st_atime, uptime}; if (utime(record_path.c_str(), ×) == -1) { PLOG(ERROR) << "Failed to set mtime for " << record_path; } }