blob: 27529bc08a16994f3389bc32f23742a54b92aede [file] [log] [blame]
Adam Lesinski00451162017-10-03 07:44:08 -07001/*
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 "io/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/macros.h"
26#include "android-base/utf8.h"
27
Adam Lesinskia693c4a2017-11-09 11:29:39 -080028#if defined(_WIN32)
29// This is only needed for O_CLOEXEC.
30#include <windows.h>
31#define O_CLOEXEC O_NOINHERIT
32#endif
33
Adam Lesinski00451162017-10-03 07:44:08 -070034using ::android::base::SystemErrorCodeToString;
Adam Lesinski93190b72017-11-03 15:20:17 -070035using ::android::base::unique_fd;
Adam Lesinski00451162017-10-03 07:44:08 -070036
37namespace aapt {
38namespace io {
39
40FileInputStream::FileInputStream(const std::string& path, size_t buffer_capacity)
Adam Lesinskia693c4a2017-11-09 11:29:39 -080041 : buffer_capacity_(buffer_capacity) {
42 int mode = O_RDONLY | O_CLOEXEC | O_BINARY;
43 fd_.reset(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 }
Adam Lesinski00451162017-10-03 07:44:08 -070049}
50
51FileInputStream::FileInputStream(int fd, size_t buffer_capacity)
Adam Lesinskia693c4a2017-11-09 11:29:39 -080052 : fd_(fd), buffer_capacity_(buffer_capacity) {
53 if (fd_ < 0) {
54 error_ = "Bad File Descriptor";
Adam Lesinski00451162017-10-03 07:44:08 -070055 } else {
56 buffer_.reset(new uint8_t[buffer_capacity_]);
57 }
58}
59
60bool FileInputStream::Next(const void** data, size_t* size) {
61 if (HadError()) {
62 return false;
63 }
64
65 // Deal with any remaining bytes after BackUp was called.
66 if (buffer_offset_ != buffer_size_) {
67 *data = buffer_.get() + buffer_offset_;
68 *size = buffer_size_ - buffer_offset_;
69 total_byte_count_ += buffer_size_ - buffer_offset_;
70 buffer_offset_ = buffer_size_;
71 return true;
72 }
73
74 ssize_t n = TEMP_FAILURE_RETRY(read(fd_, buffer_.get(), buffer_capacity_));
75 if (n < 0) {
76 error_ = SystemErrorCodeToString(errno);
77 fd_.reset();
78 buffer_.reset();
79 return false;
80 }
81
82 buffer_size_ = static_cast<size_t>(n);
83 buffer_offset_ = buffer_size_;
84 total_byte_count_ += buffer_size_;
85
86 *data = buffer_.get();
87 *size = buffer_size_;
88 return buffer_size_ != 0u;
89}
90
91void FileInputStream::BackUp(size_t count) {
92 if (count > buffer_offset_) {
93 count = buffer_offset_;
94 }
95 buffer_offset_ -= count;
96 total_byte_count_ -= count;
97}
98
99size_t FileInputStream::ByteCount() const {
100 return total_byte_count_;
101}
102
103bool FileInputStream::HadError() const {
104 return fd_ == -1;
105}
106
107std::string FileInputStream::GetError() const {
108 return error_;
109}
110
Adam Lesinskia693c4a2017-11-09 11:29:39 -0800111FileOutputStream::FileOutputStream(const std::string& path, size_t buffer_capacity)
112 : buffer_capacity_(buffer_capacity) {
113 int mode = O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_BINARY;
114 owned_fd_.reset(TEMP_FAILURE_RETRY(::android::base::utf8::open(path.c_str(), mode, 0666)));
115 fd_ = owned_fd_.get();
116 if (fd_ < 0) {
117 error_ = SystemErrorCodeToString(errno);
118 } else {
119 buffer_.reset(new uint8_t[buffer_capacity_]);
120 }
Adam Lesinski93190b72017-11-03 15:20:17 -0700121}
122
123FileOutputStream::FileOutputStream(unique_fd fd, size_t buffer_capacity)
124 : FileOutputStream(fd.get(), buffer_capacity) {
125 owned_fd_ = std::move(fd);
Adam Lesinski00451162017-10-03 07:44:08 -0700126}
127
128FileOutputStream::FileOutputStream(int fd, size_t buffer_capacity)
Adam Lesinskia693c4a2017-11-09 11:29:39 -0800129 : fd_(fd), buffer_capacity_(buffer_capacity) {
130 if (fd_ < 0) {
131 error_ = "Bad File Descriptor";
Adam Lesinski00451162017-10-03 07:44:08 -0700132 } else {
133 buffer_.reset(new uint8_t[buffer_capacity_]);
134 }
135}
136
137FileOutputStream::~FileOutputStream() {
138 // Flush the buffer.
139 Flush();
140}
141
142bool FileOutputStream::Next(void** data, size_t* size) {
Adam Lesinski93190b72017-11-03 15:20:17 -0700143 if (HadError()) {
Adam Lesinski00451162017-10-03 07:44:08 -0700144 return false;
145 }
146
147 if (buffer_offset_ == buffer_capacity_) {
148 if (!FlushImpl()) {
149 return false;
150 }
151 }
152
153 const size_t buffer_size = buffer_capacity_ - buffer_offset_;
154 *data = buffer_.get() + buffer_offset_;
155 *size = buffer_size;
156 total_byte_count_ += buffer_size;
157 buffer_offset_ = buffer_capacity_;
158 return true;
159}
160
161void FileOutputStream::BackUp(size_t count) {
162 if (count > buffer_offset_) {
163 count = buffer_offset_;
164 }
165 buffer_offset_ -= count;
166 total_byte_count_ -= count;
167}
168
169size_t FileOutputStream::ByteCount() const {
170 return total_byte_count_;
171}
172
173bool FileOutputStream::Flush() {
174 if (!HadError()) {
175 return FlushImpl();
176 }
177 return false;
178}
179
180bool FileOutputStream::FlushImpl() {
181 ssize_t n = TEMP_FAILURE_RETRY(write(fd_, buffer_.get(), buffer_offset_));
182 if (n < 0) {
183 error_ = SystemErrorCodeToString(errno);
Adam Lesinski93190b72017-11-03 15:20:17 -0700184 owned_fd_.reset();
185 fd_ = -1;
Adam Lesinski00451162017-10-03 07:44:08 -0700186 buffer_.reset();
187 return false;
188 }
189
190 buffer_offset_ = 0u;
191 return true;
192}
193
194bool FileOutputStream::HadError() const {
195 return fd_ == -1;
196}
197
198std::string FileOutputStream::GetError() const {
199 return error_;
200}
201
202} // namespace io
203} // namespace aapt