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