910e62b5创建于 1月15日历史提交
// Copyright 2022 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_SERVICES_FILE_UTIL_SINGLE_FILE_TAR_READER_H_
#define CHROME_SERVICES_FILE_UTIL_SINGLE_FILE_TAR_READER_H_

#include <optional>

#include "base/containers/span.h"
#include "base/gtest_prod_util.h"

class SingleFileTarReaderTest;

// SingleFileTarReader is a reader of tar archives with limited function. It
// only supports a tar archive with a single file entry.
// TODO(b/254591810): Reject an archive with multiple files.
class SingleFileTarReader {
 public:
  SingleFileTarReader();
  SingleFileTarReader(const SingleFileTarReader&) = delete;
  SingleFileTarReader& operator=(const SingleFileTarReader&) = delete;
  ~SingleFileTarReader();

  // Extracts a chunk of the tar file. To fully extract the file, the caller has
  // to repeatedly call this function until IsComplete() returns true.
  // Returns false if `src_buffer` is an invalid tar chunk. If not, `dst_buffer`
  // will point to a span within `src_buffer`.
  bool ExtractChunk(base::span<const uint8_t> src_buffer,
                    base::span<const uint8_t>& dst_buffer);

  bool IsComplete() const;

  // The return type uses uint64_t, because SingleFileTarReader supports large
  // files such as OS image files.
  std::optional<uint64_t> tar_content_size() const { return tar_content_size_; }
  uint64_t bytes_processed() const { return bytes_processed_; }

 private:
  FRIEND_TEST_ALL_PREFIXES(SingleFileTarReaderTest, ReadOctalNumber);

  // Read a number in Tar file header. It is normally a null-terminated octal
  // ASCII number but can be big-endian integer with padding when GNU extension
  // is used. The size of `buffer` must greater than 8.
  static std::optional<uint64_t> ReadOctalNumber(
      base::span<const uint8_t> buffer);

  // Populated once the size has been parsed. The value 0 means the file in
  // the tar is empty.
  std::optional<uint64_t> tar_content_size_;

  uint64_t bytes_processed_ = 0;
};

#endif  // CHROME_SERVICES_FILE_UTIL_SINGLE_FILE_TAR_READER_H_