91 lines
2.4 KiB
C++
91 lines
2.4 KiB
C++
// Copyright 2017 The Chromium OS Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "puffin/file_stream.h"
|
|
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
|
|
#include <algorithm>
|
|
#include <utility>
|
|
|
|
#include "puffin/src/include/puffin/common.h"
|
|
#include "puffin/src/logging.h"
|
|
|
|
using std::string;
|
|
|
|
namespace puffin {
|
|
|
|
UniqueStreamPtr FileStream::Open(const string& path, bool read, bool write) {
|
|
TEST_AND_RETURN_VALUE(read || write, nullptr);
|
|
int flags = O_CLOEXEC;
|
|
if (read && write) {
|
|
flags |= O_RDWR | O_CREAT;
|
|
} else if (read) {
|
|
flags |= O_RDONLY;
|
|
} else {
|
|
flags |= O_WRONLY | O_CREAT;
|
|
}
|
|
|
|
mode_t mode = 0644; // -rw-r--r--
|
|
int fd = open(path.c_str(), flags, mode);
|
|
TEST_AND_RETURN_VALUE(fd >= 0, nullptr);
|
|
return UniqueStreamPtr(new FileStream(fd));
|
|
}
|
|
|
|
bool FileStream::GetSize(uint64_t* size) const {
|
|
auto cur_off = lseek(fd_, 0, SEEK_CUR);
|
|
TEST_AND_RETURN_FALSE(cur_off >= 0);
|
|
auto fsize = lseek(fd_, 0, SEEK_END);
|
|
TEST_AND_RETURN_FALSE(fsize >= 0);
|
|
cur_off = lseek(fd_, cur_off, SEEK_SET);
|
|
TEST_AND_RETURN_FALSE(cur_off >= 0);
|
|
*size = fsize;
|
|
return true;
|
|
}
|
|
|
|
bool FileStream::GetOffset(uint64_t* offset) const {
|
|
auto off = lseek(fd_, 0, SEEK_CUR);
|
|
TEST_AND_RETURN_FALSE(off >= 0);
|
|
*offset = off;
|
|
return true;
|
|
}
|
|
|
|
bool FileStream::Seek(uint64_t offset) {
|
|
auto off = lseek(fd_, offset, SEEK_SET);
|
|
TEST_AND_RETURN_FALSE(off == static_cast<off_t>(offset));
|
|
return true;
|
|
}
|
|
|
|
bool FileStream::Read(void* buffer, size_t length) {
|
|
auto c_bytes = static_cast<uint8_t*>(buffer);
|
|
size_t total_bytes_read = 0;
|
|
while (total_bytes_read < length) {
|
|
auto bytes_read =
|
|
read(fd_, c_bytes + total_bytes_read, length - total_bytes_read);
|
|
// if bytes_read is zero then EOF is reached and we should not be here.
|
|
TEST_AND_RETURN_FALSE(bytes_read > 0);
|
|
total_bytes_read += bytes_read;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool FileStream::Write(const void* buffer, size_t length) {
|
|
auto c_bytes = static_cast<const uint8_t*>(buffer);
|
|
size_t total_bytes_wrote = 0;
|
|
while (total_bytes_wrote < length) {
|
|
auto bytes_wrote =
|
|
write(fd_, c_bytes + total_bytes_wrote, length - total_bytes_wrote);
|
|
TEST_AND_RETURN_FALSE(bytes_wrote >= 0);
|
|
total_bytes_wrote += bytes_wrote;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool FileStream::Close() {
|
|
return close(fd_) == 0;
|
|
}
|
|
|
|
} // namespace puffin
|