blob: a0e982333e66146fbfc963697fe01941443dd1c9 [file] [log] [blame]
// Copyright 2023 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 SRC_STORAGE_LIB_SPARSE_C_SPARSE_H_
#define SRC_STORAGE_LIB_SPARSE_C_SPARSE_H_
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
// An opaque handle to a buffer which can be used to write to a SparseIoInterface.
// This might just point to an in-memory buffer, or some special structure (e.g. a VMO registered
// with a block device for use with the block FIDL protocol).
typedef void* SparseIoBufferHandle;
// Operations that can be performed on a `SparseIoBufferHandle`.
typedef struct SparseIoBufferOps {
// Returns the size, in bytes, of the handle.
size_t (*size)(SparseIoBufferHandle handle);
// Reads `size` bytes from the handle at `offset` into `dst`.
// Returns false if the read failed.
bool (*read)(SparseIoBufferHandle handle, uint64_t offset, uint8_t* dst, size_t size);
// Writes `size` bytes from `src` into the handle at `offset`.
// Returns false if the write failed.
bool (*write)(SparseIoBufferHandle handle, uint64_t offset, const uint8_t* src, size_t size);
// Fills the handle with repeated instances of `payload`.
// Returns false if the write failed.
bool (*fill)(SparseIoBufferHandle handle, uint32_t payload);
} SparseIoBufferOps;
typedef struct SparseIoInterface {
void* ctx;
// A buffer used to optimize `fill` writing.
//
// Warning: the contents of the fill handle may be reused by sparse writing code across
// function calls. Once the fill handle has been set up, it is NOT safe for the caller
// to modify it until destruction.
SparseIoBufferHandle fill_handle;
SparseIoBufferOps handle_ops;
// Writes `size` bytes from `src` at `src_offset` to the device at `dev_offset`.
// Returns false if the write failed.
// The implementor is not responsible for bounds-checking `src`.
bool (*write)(void* ctx, uint64_t dev_offset, SparseIoBufferHandle src, uint64_t src_offset,
size_t size);
} SparseIoInterface;
typedef int (*SparseLogFn)(const char*, ...);
int sparse_nop_logger(const char*, ...);
// Returns true if the passed in buffer contains a well formed sparse image header.
//
// @handle_ops: Ops table.
// @src: Buffer containing sparse image.
//
bool sparse_is_sparse_image(SparseIoBufferOps* handle_ops, SparseIoBufferHandle src);
// Unpacks a sparse image and writes it to the passed I/O sink.
//
// @io: I/O sink.
// @log: An optional log sink for error messages.
// @src: Handle containing the sparse image.
//
// Returns true on success, false otherwise.
//
// Failure can occur if any of the following occur:
// *) Invalid sparse image header
// *) Inconsistent sparse image data, e.g. total_blks disagrees with number of chunks and
// corresponding chunk_sz
// *) Newer sparse image format than expected
// *) A larger expanded image than the destination partition can support
// *) Checksum mismatch
// *) Write failure to the underlying storage
//
// This function is not thread-safe.
bool sparse_unpack_image(SparseIoInterface* io, SparseLogFn log, SparseIoBufferHandle src);
#ifdef __cplusplus
} // __cplusplus
#endif
#endif // SRC_STORAGE_LIB_SPARSE_C_SPARSE_H_