blob: b7f5f2de88b5cbced593c5a4c2a6cf808db9a0fd [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ZIRCON_SYSTEM_ULIB_BLOBFS_COMPRESSION_ZSTD_SEEKABLE_BLOB_H_
#define ZIRCON_SYSTEM_ULIB_BLOBFS_COMPRESSION_ZSTD_SEEKABLE_BLOB_H_
#include <lib/fzl/vmo-mapper.h>
#include <stdint.h>
#include <zircon/status.h>
#include <zircon/types.h>
#include <memory>
#include <fbl/macros.h>
#include <zstd/zstd_seekable.h>
#include "zstd-compressed-block-collection.h"
#include "zstd-seekable.h"
namespace blobfs {
// RandomAccessCompressedBlob is an interface for reading contiguous *uncompressed data* from a
// compressed blob archive. Offsets in this API are in bytes relative to the start of the compressed
// archive (i.e., exclude merkle blocks and any BlobFS-managed archive header.)
//
// This interface is separated from the concrete implementation below to make testing easier.
class RandomAccessCompressedBlob {
public:
RandomAccessCompressedBlob() = default;
virtual ~RandomAccessCompressedBlob() = default;
// Load into |buf| exactly |num_bytes| bytes starting at _uncompressed_ file contents byte offset
// |data_byte_offset|. The value of data in |buf| is expected to be valid if and only if the
// return value is |ZX_OK|.
virtual zx_status_t Read(uint8_t* buf, uint64_t data_byte_offset, uint64_t num_bytes) = 0;
};
// ZSTDSeekableBlob as an implementation of |RandomAccessCompressedBlob| that uses the ZSTD Seekable
// Format.
//
// https://github.com/facebook/zstd/blob/dev/contrib/seekable_format/zstd_seekable_compression_format.md.
class ZSTDSeekableBlob : public RandomAccessCompressedBlob {
public:
// Create a |ZSTDSeekableBlob|. It is the invoker's responsibility to ensure that the VMO
// populated on |compressed_block_collection.Read()| corresponds to |mapped_vmo|.
static zx_status_t Create(
uint32_t node_index, fzl::VmoMapper* mapped_vmo,
std::unique_ptr<ZSTDCompressedBlockCollection> compressed_block_collection,
std::unique_ptr<ZSTDSeekableBlob>* out);
// RandomAccessCompressedBlob implementation.
zx_status_t Read(uint8_t* buf, uint64_t data_byte_offset, uint64_t num_bytes) final;
const uint8_t* compressed_data_start() const {
return static_cast<uint8_t*>(mapped_vmo_->start());
}
uint32_t node_index() { return node_index_; }
private:
ZSTDSeekableBlob(uint32_t node_index, fzl::VmoMapper* mapped_vmo,
std::unique_ptr<ZSTDCompressedBlockCollection> compressed_block_collection);
zx_status_t ReadHeader();
uint32_t node_index_;
ZSTDSeekableHeader header_;
fzl::VmoMapper* mapped_vmo_;
std::unique_ptr<ZSTDCompressedBlockCollection> compressed_block_collection_;
};
// Type used for opaque pointer in ZSTD Seekable custom |ZSTD_seekable_seek| and
// |ZSTD_seekable_read| API.
struct ZSTDSeekableFile {
ZSTDSeekableBlob* blob;
ZSTDCompressedBlockCollection* blocks;
unsigned long long byte_offset;
unsigned long long num_bytes;
zx_status_t status;
};
// ZSTD Seekable custom |ZSTD_seekable_seek| and |ZSTD_seekable_read| API.
int ZSTDSeek(void* void_ptr_zstd_seekable_file, long long byte_offset, int origin);
int ZSTDRead(void* void_ptr_zstd_seekable_file, void* buf, size_t num_bytes);
} // namespace blobfs
#endif // ZIRCON_SYSTEM_ULIB_BLOBFS_COMPRESSION_ZSTD_SEEKABLE_BLOB_H_