1 // Copyright 2017 The Chromium OS Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "puffin/src/file_stream.h" 6 7 #include <fcntl.h> 8 #include <unistd.h> 9 10 #include <algorithm> 11 #include <utility> 12 13 #include "puffin/src/include/puffin/common.h" 14 #include "puffin/src/logging.h" 15 16 using std::string; 17 18 namespace puffin { 19 20 UniqueStreamPtr FileStream::Open(const string& path, bool read, bool write) { 21 TEST_AND_RETURN_VALUE(read || write, nullptr); 22 int flags = O_CLOEXEC; 23 if (read && write) { 24 flags |= O_RDWR | O_CREAT; 25 } else if (read) { 26 flags |= O_RDONLY; 27 } else { 28 flags |= O_WRONLY | O_CREAT; 29 } 30 31 mode_t mode = 0644; // -rw-r--r-- 32 int fd = open(path.c_str(), flags, mode); 33 TEST_AND_RETURN_VALUE(fd >= 0, nullptr); 34 return UniqueStreamPtr(new FileStream(fd)); 35 } 36 37 bool FileStream::GetSize(uint64_t* size) const { 38 auto cur_off = lseek(fd_, 0, SEEK_CUR); 39 TEST_AND_RETURN_FALSE(cur_off >= 0); 40 auto fsize = lseek(fd_, 0, SEEK_END); 41 TEST_AND_RETURN_FALSE(fsize >= 0); 42 cur_off = lseek(fd_, cur_off, SEEK_SET); 43 TEST_AND_RETURN_FALSE(cur_off >= 0); 44 *size = fsize; 45 return true; 46 } 47 48 bool FileStream::GetOffset(uint64_t* offset) const { 49 auto off = lseek(fd_, 0, SEEK_CUR); 50 TEST_AND_RETURN_FALSE(off >= 0); 51 *offset = off; 52 return true; 53 } 54 55 bool FileStream::Seek(uint64_t offset) { 56 auto off = lseek(fd_, offset, SEEK_SET); 57 TEST_AND_RETURN_FALSE(off == static_cast<off_t>(offset)); 58 return true; 59 } 60 61 bool FileStream::Read(void* buffer, size_t length) { 62 auto c_bytes = static_cast<uint8_t*>(buffer); 63 size_t total_bytes_read = 0; 64 while (total_bytes_read < length) { 65 auto bytes_read = 66 read(fd_, c_bytes + total_bytes_read, length - total_bytes_read); 67 // if bytes_read is zero then EOF is reached and we should not be here. 68 TEST_AND_RETURN_FALSE(bytes_read > 0); 69 total_bytes_read += bytes_read; 70 } 71 return true; 72 } 73 74 bool FileStream::Write(const void* buffer, size_t length) { 75 auto c_bytes = static_cast<const uint8_t*>(buffer); 76 size_t total_bytes_wrote = 0; 77 while (total_bytes_wrote < length) { 78 auto bytes_wrote = 79 write(fd_, c_bytes + total_bytes_wrote, length - total_bytes_wrote); 80 TEST_AND_RETURN_FALSE(bytes_wrote >= 0); 81 total_bytes_wrote += bytes_wrote; 82 } 83 return true; 84 } 85 86 bool FileStream::Close() { 87 return close(fd_) == 0; 88 } 89 90 } // namespace puffin 91