| // Copyright 2015 The ChromiumOS Authors | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #include <base/check_op.h> | |
| #include <brillo/streams/stream_utils.h> | |
| #include <algorithm> | |
| #include <limits> | |
| #include <memory> | |
| #include <utility> | |
| #include <vector> | |
| #include <base/functional/bind.h> | |
| #include <brillo/message_loops/message_loop.h> | |
| #include <brillo/streams/stream_errors.h> | |
| namespace brillo { | |
| namespace stream_utils { | |
| bool ErrorStreamClosed(const base::Location& location, ErrorPtr* error) { | |
| Error::AddTo(error, location, errors::stream::kDomain, | |
| errors::stream::kStreamClosed, "Stream is closed"); | |
| return false; | |
| } | |
| bool ErrorOperationNotSupported(const base::Location& location, | |
| ErrorPtr* error) { | |
| Error::AddTo(error, location, errors::stream::kDomain, | |
| errors::stream::kOperationNotSupported, | |
| "Stream operation not supported"); | |
| return false; | |
| } | |
| bool ErrorReadPastEndOfStream(const base::Location& location, ErrorPtr* error) { | |
| Error::AddTo(error, location, errors::stream::kDomain, | |
| errors::stream::kPartialData, "Reading past the end of stream"); | |
| return false; | |
| } | |
| bool ErrorOperationTimeout(const base::Location& location, ErrorPtr* error) { | |
| Error::AddTo(error, location, errors::stream::kDomain, | |
| errors::stream::kTimeout, "Operation timed out"); | |
| return false; | |
| } | |
| bool CheckInt64Overflow(const base::Location& location, | |
| uint64_t position, | |
| int64_t offset, | |
| ErrorPtr* error) { | |
| if (offset < 0) { | |
| // Subtracting the offset. Make sure we do not underflow. | |
| uint64_t unsigned_offset = static_cast<uint64_t>(-offset); | |
| if (position >= unsigned_offset) | |
| return true; | |
| } else { | |
| // Adding the offset. Make sure we do not overflow unsigned 64 bits first. | |
| if (position <= std::numeric_limits<uint64_t>::max() - offset) { | |
| // We definitely will not overflow the unsigned 64 bit integer. | |
| // Now check that we end up within the limits of signed 64 bit integer. | |
| uint64_t new_position = position + offset; | |
| uint64_t max = std::numeric_limits<int64_t>::max(); | |
| if (new_position <= max) | |
| return true; | |
| } | |
| } | |
| Error::AddTo(error, location, errors::stream::kDomain, | |
| errors::stream::kInvalidParameter, | |
| "The stream offset value is out of range"); | |
| return false; | |
| } | |
| bool CalculateStreamPosition(const base::Location& location, | |
| int64_t offset, | |
| Stream::Whence whence, | |
| uint64_t current_position, | |
| uint64_t stream_size, | |
| uint64_t* new_position, | |
| ErrorPtr* error) { | |
| uint64_t pos = 0; | |
| switch (whence) { | |
| case Stream::Whence::FROM_BEGIN: | |
| pos = 0; | |
| break; | |
| case Stream::Whence::FROM_CURRENT: | |
| pos = current_position; | |
| break; | |
| case Stream::Whence::FROM_END: | |
| pos = stream_size; | |
| break; | |
| default: | |
| Error::AddTo(error, location, errors::stream::kDomain, | |
| errors::stream::kInvalidParameter, | |
| "Invalid stream position whence"); | |
| return false; | |
| } | |
| if (!CheckInt64Overflow(location, pos, offset, error)) | |
| return false; | |
| *new_position = static_cast<uint64_t>(pos + offset); | |
| return true; | |
| } | |
| } // namespace stream_utils | |
| } // namespace brillo |