• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "androidfw/FileStream.h"
18 
19 #include <errno.h>   // for errno
20 #include <fcntl.h>   // for O_RDONLY
21 #include <unistd.h>  // for read
22 
23 #include "android-base/errors.h"
24 #include "android-base/file.h"  // for O_BINARY
25 #include "android-base/logging.h"
26 #include "android-base/macros.h"
27 #include "android-base/utf8.h"
28 
29 #if defined(_WIN32)
30 // This is only needed for O_CLOEXEC.
31 #include <windows.h>
32 #define O_CLOEXEC O_NOINHERIT
33 #endif
34 
35 using ::android::base::SystemErrorCodeToString;
36 using ::android::base::unique_fd;
37 
38 namespace android {
39 
FileInputStream(const std::string & path,size_t buffer_capacity)40 FileInputStream::FileInputStream(const std::string& path, size_t buffer_capacity)
41     : should_close_(true), buffer_capacity_(buffer_capacity) {
42   int mode = O_RDONLY | O_CLOEXEC | O_BINARY;
43   fd_ = TEMP_FAILURE_RETRY(::android::base::utf8::open(path.c_str(), mode));
44   if (fd_ == -1) {
45     error_ = SystemErrorCodeToString(errno);
46   } else {
47     buffer_.reset(new uint8_t[buffer_capacity_]);
48   }
49 }
50 
FileInputStream(int fd,size_t buffer_capacity)51 FileInputStream::FileInputStream(int fd, size_t buffer_capacity)
52     : fd_(fd), should_close_(true), buffer_capacity_(buffer_capacity) {
53   if (fd_ < 0) {
54     error_ = "Bad File Descriptor";
55   } else {
56     buffer_.reset(new uint8_t[buffer_capacity_]);
57   }
58 }
59 
FileInputStream(android::base::borrowed_fd fd,size_t buffer_capacity)60 FileInputStream::FileInputStream(android::base::borrowed_fd fd, size_t buffer_capacity)
61     : fd_(fd.get()), should_close_(false), buffer_capacity_(buffer_capacity) {
62 
63   if (fd_ < 0) {
64     error_ = "Bad File Descriptor";
65   } else {
66     buffer_.reset(new uint8_t[buffer_capacity_]);
67   }
68 }
69 
70 
Next(const void ** data,size_t * size)71 bool FileInputStream::Next(const void** data, size_t* size) {
72   if (HadError()) {
73     return false;
74   }
75 
76   // Deal with any remaining bytes after BackUp was called.
77   if (buffer_offset_ != buffer_size_) {
78     *data = buffer_.get() + buffer_offset_;
79     *size = buffer_size_ - buffer_offset_;
80     total_byte_count_ += buffer_size_ - buffer_offset_;
81     buffer_offset_ = buffer_size_;
82     return true;
83   }
84 
85   ssize_t n = TEMP_FAILURE_RETRY(read(fd_, buffer_.get(), buffer_capacity_));
86   if (n < 0) {
87     error_ = SystemErrorCodeToString(errno);
88     if (fd_ != -1) {
89       if (should_close_) {
90         close(fd_);
91       }
92       fd_ = -1;
93     }
94     buffer_.reset();
95     return false;
96   }
97 
98   buffer_size_ = static_cast<size_t>(n);
99   buffer_offset_ = buffer_size_;
100   total_byte_count_ += buffer_size_;
101 
102   *data = buffer_.get();
103   *size = buffer_size_;
104   return buffer_size_ != 0u;
105 }
106 
BackUp(size_t count)107 void FileInputStream::BackUp(size_t count) {
108   if (count > buffer_offset_) {
109     count = buffer_offset_;
110   }
111   buffer_offset_ -= count;
112   total_byte_count_ -= count;
113 }
114 
ByteCount() const115 size_t FileInputStream::ByteCount() const {
116   return total_byte_count_;
117 }
118 
HadError() const119 bool FileInputStream::HadError() const {
120   return fd_ == -1;
121 }
122 
GetError() const123 std::string FileInputStream::GetError() const {
124   return error_;
125 }
126 
ReadFullyAtOffset(void * data,size_t byte_count,off64_t offset)127 bool FileInputStream::ReadFullyAtOffset(void* data, size_t byte_count, off64_t offset) {
128   return base::ReadFullyAtOffset(fd_, data, byte_count, offset);
129 }
130 
FileOutputStream(const std::string & path,size_t buffer_capacity)131 FileOutputStream::FileOutputStream(const std::string& path, size_t buffer_capacity)
132     : buffer_capacity_(buffer_capacity) {
133   int mode = O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_BINARY;
134   owned_fd_.reset(TEMP_FAILURE_RETRY(::android::base::utf8::open(path.c_str(), mode, 0666)));
135   fd_ = owned_fd_.get();
136   if (fd_ < 0) {
137     error_ = SystemErrorCodeToString(errno);
138   } else {
139     buffer_.reset(new uint8_t[buffer_capacity_]);
140   }
141 }
142 
FileOutputStream(unique_fd fd,size_t buffer_capacity)143 FileOutputStream::FileOutputStream(unique_fd fd, size_t buffer_capacity)
144     : FileOutputStream(fd.get(), buffer_capacity) {
145   owned_fd_ = std::move(fd);
146 }
147 
FileOutputStream(int fd,size_t buffer_capacity)148 FileOutputStream::FileOutputStream(int fd, size_t buffer_capacity)
149     : fd_(fd), buffer_capacity_(buffer_capacity) {
150   if (fd_ < 0) {
151     error_ = "Bad File Descriptor";
152   } else {
153     buffer_.reset(new uint8_t[buffer_capacity_]);
154   }
155 }
156 
~FileOutputStream()157 FileOutputStream::~FileOutputStream() {
158   // Flush the buffer.
159   Flush();
160 }
161 
Next(void ** data,size_t * size)162 bool FileOutputStream::Next(void** data, size_t* size) {
163   if (HadError()) {
164     return false;
165   }
166 
167   if (buffer_offset_ == buffer_capacity_) {
168     if (!FlushImpl()) {
169       return false;
170     }
171   }
172 
173   const size_t buffer_size = buffer_capacity_ - buffer_offset_;
174   *data = buffer_.get() + buffer_offset_;
175   *size = buffer_size;
176   total_byte_count_ += buffer_size;
177   buffer_offset_ = buffer_capacity_;
178   return true;
179 }
180 
BackUp(size_t count)181 void FileOutputStream::BackUp(size_t count) {
182   if (count > buffer_offset_) {
183     count = buffer_offset_;
184   }
185   buffer_offset_ -= count;
186   total_byte_count_ -= count;
187 }
188 
ByteCount() const189 size_t FileOutputStream::ByteCount() const {
190   return total_byte_count_;
191 }
192 
Flush()193 bool FileOutputStream::Flush() {
194   if (!HadError()) {
195     return FlushImpl();
196   }
197   return false;
198 }
199 
FlushImpl()200 bool FileOutputStream::FlushImpl() {
201   ssize_t n = TEMP_FAILURE_RETRY(write(fd_, buffer_.get(), buffer_offset_));
202   if (n < 0) {
203     error_ = SystemErrorCodeToString(errno);
204     owned_fd_.reset();
205     fd_ = -1;
206     buffer_.reset();
207     return false;
208   }
209 
210   buffer_offset_ = 0u;
211   return true;
212 }
213 
HadError() const214 bool FileOutputStream::HadError() const {
215   return fd_ == -1;
216 }
217 
GetError() const218 std::string FileOutputStream::GetError() const {
219   return error_;
220 }
221 
222 }  // namespace android
223