|  | /* | 
|  | * Copyright (C) 2022 The Android Open Source Project | 
|  | * | 
|  | * Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | * you may not use this file except in compliance with the License. | 
|  | * You may obtain a copy of the License at | 
|  | * | 
|  | *      http://www.apache.org/licenses/LICENSE-2.0 | 
|  | * | 
|  | * Unless required by applicable law or agreed to in writing, software | 
|  | * distributed under the License is distributed on an "AS IS" BASIS, | 
|  | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | * See the License for the specific language governing permissions and | 
|  | * limitations under the License. | 
|  | */ | 
|  |  | 
|  | #include "interprocess_fifo.h" | 
|  |  | 
|  | #include <android-base/logging.h> | 
|  |  | 
|  | #include <unistd.h> | 
|  |  | 
|  | using ::android::base::ErrnoError; | 
|  | using ::android::base::Error; | 
|  | using ::android::base::Result; | 
|  |  | 
|  | namespace android { | 
|  | namespace init { | 
|  |  | 
|  | InterprocessFifo::InterprocessFifo() noexcept : fds_({-1, -1}) {} | 
|  |  | 
|  | InterprocessFifo::InterprocessFifo(InterprocessFifo&& orig) noexcept : fds_({-1, -1}) { | 
|  | std::swap(fds_, orig.fds_); | 
|  | } | 
|  |  | 
|  | InterprocessFifo::~InterprocessFifo() noexcept { | 
|  | Close(); | 
|  | } | 
|  |  | 
|  | void InterprocessFifo::CloseFd(int& fd) noexcept { | 
|  | if (fd >= 0) { | 
|  | close(fd); | 
|  | fd = -1; | 
|  | } | 
|  | } | 
|  |  | 
|  | void InterprocessFifo::CloseReadFd() noexcept { | 
|  | CloseFd(fds_[0]); | 
|  | } | 
|  |  | 
|  | void InterprocessFifo::CloseWriteFd() noexcept { | 
|  | CloseFd(fds_[1]); | 
|  | } | 
|  |  | 
|  | void InterprocessFifo::Close() noexcept { | 
|  | CloseReadFd(); | 
|  | CloseWriteFd(); | 
|  | } | 
|  |  | 
|  | Result<void> InterprocessFifo::Initialize() noexcept { | 
|  | if (fds_[0] >= 0) { | 
|  | return Error() << "already initialized"; | 
|  | } | 
|  | if (pipe(fds_.data()) < 0) {  // NOLINT(android-cloexec-pipe) | 
|  | return ErrnoError() << "pipe()"; | 
|  | } | 
|  | return {}; | 
|  | } | 
|  |  | 
|  | Result<uint8_t> InterprocessFifo::Read() noexcept { | 
|  | uint8_t byte; | 
|  | ssize_t count = read(fds_[0], &byte, 1); | 
|  | if (count < 0) { | 
|  | return ErrnoError() << "read()"; | 
|  | } | 
|  | if (count == 0) { | 
|  | return Error() << "read() EOF"; | 
|  | } | 
|  | DCHECK_EQ(count, 1); | 
|  | return byte; | 
|  | } | 
|  |  | 
|  | Result<void> InterprocessFifo::Write(uint8_t byte) noexcept { | 
|  | ssize_t written = write(fds_[1], &byte, 1); | 
|  | if (written < 0) { | 
|  | return ErrnoError() << "write()"; | 
|  | } | 
|  | if (written == 0) { | 
|  | return Error() << "write() EOF"; | 
|  | } | 
|  | DCHECK_EQ(written, 1); | 
|  | return {}; | 
|  | } | 
|  |  | 
|  | }  // namespace init | 
|  | }  // namespace android |