blob: 98634a420a6ca5e6d2598722c9b483565f0539b1 [file] [log] [blame]
// Copyright 2019 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.
#include "src/storage/lib/paver/stream-reader.h"
#include <memory>
#include "src/storage/lib/paver/pave-logging.h"
namespace paver {
zx::status<std::unique_ptr<StreamReader>> StreamReader::Create(zx::channel stream) {
zx::vmo vmo;
auto status = zx::make_status(zx::vmo::create(8192, 0, &vmo));
if (status.is_error()) {
ERROR("Unable to create vmo.\n");
return status.take_error();
}
zx::vmo dup;
status = zx::make_status(vmo.duplicate(ZX_RIGHT_SAME_RIGHTS, &dup));
if (status.is_error()) {
ERROR("Unable to duplicate vmo.\n");
return status.take_error();
}
auto result = ::llcpp::fuchsia::paver::PayloadStream::Call::RegisterVmo(zx::unowned(stream),
std::move(dup));
status = zx::make_status(result.ok() ? result.value().status : result.status());
if (status.is_error()) {
ERROR("Unable to register vmo: %d\n", status.error_value());
return status.take_error();
}
return zx::ok(new StreamReader(std::move(stream), std::move(vmo)));
}
zx_status_t StreamReader::Read(void* buf, size_t buf_size, size_t* size_actual) {
if (size_ == 0) {
auto call_result = stream_.ReadData();
if (call_result.status() != ZX_OK) {
return call_result.status();
}
const ::llcpp::fuchsia::paver::ReadResult& read_result = call_result.value().result;
switch (read_result.which()) {
case llcpp::fuchsia::paver::ReadResult::Tag::kErr:
return read_result.err();
case llcpp::fuchsia::paver::ReadResult::Tag::kEof:
*size_actual = 0;
return ZX_OK;
case llcpp::fuchsia::paver::ReadResult::Tag::kInfo:
offset_ = read_result.info().offset;
size_ = read_result.info().size;
break;
default:
return ZX_ERR_INTERNAL;
}
}
const auto size = std::min(size_, buf_size);
auto status = vmo_.read(buf, offset_, size);
if (status != ZX_OK) {
return status;
}
offset_ += size;
size_ -= size;
*size_actual = size;
return ZX_OK;
}
} // namespace paver