chromium/chrome/browser/ash/system_logs/single_log_file_log_source.h

// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_ASH_SYSTEM_LOGS_SINGLE_LOG_FILE_LOG_SOURCE_H_
#define CHROME_BROWSER_ASH_SYSTEM_LOGS_SINGLE_LOG_FILE_LOG_SOURCE_H_

#include <stddef.h>
#include <sys/types.h>

#include "base/files/file.h"
#include "base/memory/weak_ptr.h"
#include "components/feedback/system_logs/system_logs_source.h"

namespace base {
class Time;
}

namespace system_logs {

// Gathers log data from a single source, possibly incrementally.
class SingleLogFileLogSource : public SystemLogsSource {
 public:
  enum class SupportedSource {
    // For /var/log/messages.
    kMessages,

    // For /var/log/ui/ui.LATEST.
    kUiLatest,

    // For /var/log/atrus.log.
    kAtrusLog,

    // For /var/log/net.log.
    kNetLog,

    // For /var/log/eventlog.txt.
    kEventLog,

    // For /var/log/update_engine.log.
    kUpdateEngineLog,

    // For /var/log/power_manager/powerd.LATEST.
    kPowerdLatest,

    // For /var/log/power_manager/powerd.PREVIOUS.
    kPowerdPrevious,
  };

  explicit SingleLogFileLogSource(SupportedSource source);

  SingleLogFileLogSource(const SingleLogFileLogSource&) = delete;
  SingleLogFileLogSource& operator=(const SingleLogFileLogSource&) = delete;

  ~SingleLogFileLogSource() override;

  // During testing, use this to set a custom Chrome start time to override the
  // actual start time. Does not take ownership of |start_time|. Call this again
  // with |start_time|=nullptr when done with testing.
  static void SetChromeStartTimeForTesting(const base::Time* start_time);

  // system_logs::SystemLogsSource:
  void Fetch(SysLogsSourceCallback callback) override;

  void SetMaxReadSizeForTesting(size_t max_read_size);

 private:
  friend class SingleLogFileLogSourceTest;

  // Returns the full path of the log file.
  base::FilePath GetLogFilePath() const;

  // Reads all available content from |file_| that has not already been read.
  // Stores results as a single entry in |response|, with |source_name()| as key
  // and the read log contents as value.
  //
  // Handles rotation of underlying log file by reading all remaining contents
  // of old file and then opening and reading from new file.
  //
  // |num_rotations_allowed| limits the number of rotations that can take place
  // before the function returns. This avoids this function never returning due
  // to indefinitely repeated log file rotation. If this number is exceeded
  // during a call, ReadFile() stops checking for log file rotation for the
  // remainder of its execution. Any further rotation could result in missed log
  // data.
  void ReadFile(size_t num_rotations_allowed, SystemLogsResponse* response);

  // Continues an in-progress file read.
  //
  // |result_string| stores accumulated logs read across file rotations to
  // ensure at most |max_read_size_| bytes are read when combining data from
  // multiple rotations for a log file into a single read.
  //
  // |bytes_skipped| is true when some bytes in the current read were skipped
  // to avoid exceeding |max_read_size_|.
  //
  // See |ReadFile| for |num_rotations_allowed| and |response|.
  void ContinueReadFile(std::unique_ptr<std::string> result_string,
                        bool bytes_skipped,
                        size_t num_rotations_allowed,
                        SystemLogsResponse* response);

  // The source type.
  const SupportedSource source_type_;

  // Path to system log file directory.
  base::FilePath log_file_dir_path_;

  // The maximum size of a read from |file_|.
  size_t max_read_size_;

  // Keeps track of how much data has been read or skipped from |file_|.
  size_t file_cursor_position_;

  // Handle for reading the log file that is source of logging data.
  base::File file_;

  // File system inode value that was associated with |log_file_path_| when it
  // was originally opened for reading.
  ino_t file_inode_;

  base::WeakPtrFactory<SingleLogFileLogSource> weak_ptr_factory_{this};
};

}  // namespace system_logs

#endif  // CHROME_BROWSER_ASH_SYSTEM_LOGS_SINGLE_LOG_FILE_LOG_SOURCE_H_