1 // Copyright 2019 The Fuchsia Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #pragma once 6 7 #include <fbl/array.h> 8 #include <fbl/function.h> 9 #include <lib/inspect/block.h> 10 #include <lib/zx/vmo.h> 11 #include <unistd.h> 12 #include <zircon/types.h> 13 14 namespace inspect { 15 16 // |Snapshot| parses an incoming VMO buffer and produces a snapshot of 17 // the VMO contents. |Snapshot::Options| determines the behavior of 18 // snapshotting if a concurrent write potentially occurred. 19 // 20 // Example: 21 // fbl::unique_ptr<Snapshot> snapshot; 22 // zx_status_t status = Snapshot::Create(std::move(vmo), 23 // {.read_attempts = 1024, .skip_consistency_check = false}, 24 // &snapshot); 25 // 26 // Test Example: 27 // zx_status_t status = Snapshot::Create(std::move(vmo), 28 // {.read_attempts = 1024, .skip_consistency_check = false}, 29 // fbl::make_unique<TestCallback>(), 30 // &snapshot); 31 class Snapshot final { 32 public: 33 struct Options { 34 // The number of attempts to read a consistent snapshot. 35 // Reading fails if the number of attempts exceeds this number. 36 int read_attempts; 37 38 // If true, skip checking the buffer for consistency. 39 bool skip_consistency_check; 40 }; 41 42 // Type for observing reads on the VMO. 43 using ReadObserver = fbl::Function<void(uint8_t* buffer, size_t buffer_size)>; 44 45 // By default, ensure consistency of the incoming Inspect VMO and retry up to 46 // 1024 times. 47 static constexpr Options kDefaultOptions = {.read_attempts = 1024, 48 .skip_consistency_check = false}; 49 50 // Create a new snapshot of the given VMO and default options. 51 static zx_status_t Create(zx::vmo vmo, Snapshot* out_snapshot); 52 53 // Create a new snapshot of the given VMO and given options. 54 static zx_status_t Create(zx::vmo vmo, Options options, Snapshot* out_snapshot); 55 56 // Create a new snapshot of the given VMO, given options, and the given read observer 57 // for observing snapshot operations. 58 static zx_status_t Create(zx::vmo vmo, Options options, ReadObserver read_observer, 59 Snapshot* out_snapshot); 60 61 Snapshot() = default; 62 ~Snapshot() = default; 63 Snapshot(Snapshot&&) = default; 64 Snapshot& operator=(Snapshot&&) = default; 65 66 operator bool() const { return buffer_.size() > 0; } 67 68 // Returns the start of the snapshot data, if valid. data()69 const uint8_t* data() const { return buffer_.begin(); } 70 71 // Returns the size of the snapshot, if valid. size()72 size_t size() const { return buffer_.size(); } 73 74 // Get a pointer to a block in the buffer by index. 75 // Returns nullptr if the index is out of bounds. 76 internal::Block* GetBlock(internal::BlockIndex index) const; 77 78 private: 79 // Read from the VMO into a buffer. 80 static zx_status_t Read(zx::vmo& vmo, size_t size, uint8_t* buffer); 81 82 // Parse the header from a buffer and obtain the generation count. 83 static zx_status_t ParseHeader(uint8_t* buffer, uint64_t* out_generation_count); 84 85 // Take a new snapshot of the VMO with default options. 86 // If reading fails, the boolean value of the constructed |Snapshot| will be false. 87 explicit Snapshot(fbl::Array<uint8_t> buffer); 88 89 // The buffer storing the snapshot. 90 fbl::Array<uint8_t> buffer_; 91 }; 92 93 } // namespace inspect 94