Home | History | Annotate | Download | only in src
      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/set_errors.h"
     15 
     16 namespace puffin {
     17 
     18 using std::string;
     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