1 //
2 // Copyright (C) 2017 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16
17 #include "update_engine/payload_consumer/fake_file_descriptor.h"
18
19 namespace chromeos_update_engine {
20
Read(void * buf,size_t count)21 ssize_t FakeFileDescriptor::Read(void* buf, size_t count) {
22 // Record the read operation so it can later be inspected.
23 read_ops_.emplace_back(offset_, count);
24
25 // Check for the EOF condition first to avoid reporting it as a failure.
26 if (offset_ >= static_cast<uint64_t>(size_) || count == 0)
27 return 0;
28 // Find the first offset greater or equal than the current position where a
29 // failure will occur. This will mark the end of the read chunk.
30 uint64_t first_failure = size_;
31 for (const auto& failure : failure_ranges_) {
32 // A failure range that includes the current offset results in an
33 // immediate failure to read any bytes.
34 if (failure.first <= offset_ && offset_ < failure.first + failure.second) {
35 errno = EIO;
36 return -1;
37 }
38 if (failure.first > offset_)
39 first_failure = std::min(first_failure, failure.first);
40 }
41 count = std::min(static_cast<uint64_t>(count), first_failure - offset_);
42 static const char kHexChars[] = "0123456789ABCDEF";
43 for (size_t i = 0; i < count; ++i) {
44 // Encode the 16-bit number "offset_ / 4" as a hex digit in big-endian.
45 uint16_t current_num = offset_ / 4;
46 uint8_t current_digit = (current_num >> (4 * (3 - offset_ % 4))) & 0x0f;
47
48 static_cast<uint8_t*>(buf)[i] = kHexChars[current_digit];
49 offset_++;
50 }
51
52 return count;
53 }
54
Seek(off64_t offset,int whence)55 off64_t FakeFileDescriptor::Seek(off64_t offset, int whence) {
56 switch (whence) {
57 case SEEK_SET:
58 offset_ = offset;
59 break;
60 case SEEK_CUR:
61 offset_ += offset;
62 break;
63 case SEEK_END:
64 if (offset > size_)
65 offset_ = 0;
66 else
67 offset_ = size_ - offset_;
68 break;
69 default:
70 errno = EINVAL;
71 return -1;
72 }
73 return offset_;
74 }
75
FakeFileDescriptorData(size_t size)76 brillo::Blob FakeFileDescriptorData(size_t size) {
77 brillo::Blob ret(size);
78 FakeFileDescriptor fd;
79 fd.SetFileSize(size);
80 fd.Read(ret.data(), size);
81 return ret;
82 }
83
84 } // namespace chromeos_update_engine
85