summaryrefslogtreecommitdiffstats
path: root/base
diff options
context:
space:
mode:
authorAdam Lesinski2017-07-25 17:22:21 -0500
committerGerrit Code Review2017-07-25 17:22:21 -0500
commita0360ad6a365b625da039b16e9b9b55ab2425afe (patch)
treed5a0aa2ddecec16d9a4a9a6f3555660093fa8dea /base
parent80ec81cf4b9f4e9a529df618ea38a3f995a2f249 (diff)
parentde117e4a49d6ed047c0c1a9270be5d8a191aa2db (diff)
downloadplatform-system-core-a0360ad6a365b625da039b16e9b9b55ab2425afe.tar.gz
platform-system-core-a0360ad6a365b625da039b16e9b9b55ab2425afe.tar.xz
platform-system-core-a0360ad6a365b625da039b16e9b9b55ab2425afe.zip
Merge "libziparchive: Use ReadAtOffset exclusively"
Diffstat (limited to 'base')
-rw-r--r--base/file.cpp31
-rw-r--r--base/include/android-base/file.h11
2 files changed, 42 insertions, 0 deletions
diff --git a/base/file.cpp b/base/file.cpp
index a2f28878e..2f697a1cc 100644
--- a/base/file.cpp
+++ b/base/file.cpp
@@ -153,6 +153,37 @@ bool ReadFully(int fd, void* data, size_t byte_count) {
153 return true; 153 return true;
154} 154}
155 155
156#if defined(_WIN32)
157// Windows implementation of pread. Note that this DOES move the file descriptors read position,
158// but it does so atomically.
159static ssize_t pread(int fd, void* data, size_t byte_count, off64_t offset) {
160 DWORD bytes_read;
161 OVERLAPPED overlapped;
162 memset(&overlapped, 0, sizeof(OVERLAPPED));
163 overlapped.Offset = static_cast<DWORD>(offset);
164 overlapped.OffsetHigh = static_cast<DWORD>(offset >> 32);
165 if (!ReadFile(reinterpret_cast<HANDLE>(_get_osfhandle(fd)), data, static_cast<DWORD>(byte_count),
166 &bytes_read, &overlapped)) {
167 // In case someone tries to read errno (since this is masquerading as a POSIX call)
168 errno = EIO;
169 return -1;
170 }
171 return static_cast<ssize_t>(bytes_read);
172}
173#endif
174
175bool ReadFullyAtOffset(int fd, void* data, size_t byte_count, off64_t offset) {
176 uint8_t* p = reinterpret_cast<uint8_t*>(data);
177 while (byte_count > 0) {
178 ssize_t n = TEMP_FAILURE_RETRY(pread(fd, p, byte_count, offset));
179 if (n <= 0) return false;
180 p += n;
181 byte_count -= n;
182 offset += n;
183 }
184 return true;
185}
186
156bool WriteFully(int fd, const void* data, size_t byte_count) { 187bool WriteFully(int fd, const void* data, size_t byte_count) {
157 const uint8_t* p = reinterpret_cast<const uint8_t*>(data); 188 const uint8_t* p = reinterpret_cast<const uint8_t*>(data);
158 size_t remaining = byte_count; 189 size_t remaining = byte_count;
diff --git a/base/include/android-base/file.h b/base/include/android-base/file.h
index 651f52962..af1489227 100644
--- a/base/include/android-base/file.h
+++ b/base/include/android-base/file.h
@@ -42,6 +42,17 @@ bool WriteStringToFile(const std::string& content, const std::string& path,
42#endif 42#endif
43 43
44bool ReadFully(int fd, void* data, size_t byte_count); 44bool ReadFully(int fd, void* data, size_t byte_count);
45
46// Reads `byte_count` bytes from the file descriptor at the specified offset.
47// Returns false if there was an IO error or EOF was reached before reading `byte_count` bytes.
48//
49// NOTE: On Linux/Mac, this function wraps pread, which provides atomic read support without
50// modifying the read pointer of the file descriptor. On Windows, however, the read pointer does
51// get modified. This means that ReadFullyAtOffset can be used concurrently with other calls to the
52// same function, but concurrently seeking or reading incrementally can lead to unexpected
53// behavior.
54bool ReadFullyAtOffset(int fd, void* data, size_t byte_count, off64_t offset);
55
45bool WriteFully(int fd, const void* data, size_t byte_count); 56bool WriteFully(int fd, const void* data, size_t byte_count);
46 57
47bool RemoveFileIfExists(const std::string& path, std::string* err = nullptr); 58bool RemoveFileIfExists(const std::string& path, std::string* err = nullptr);