blob: c4a672be9b2c70bf0f1491b2cf422449b385b24d [file] [log] [blame]
// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by the GPL v2 license that can
// be found in the LICENSE file.
//
// Implementation of simple_file::File
#include "verity/simple_file/file.h"
namespace simple_file {
const Env *File::env() const {
if (env_) {
return env_;
}
return default_env_;
}
bool File::Initialize(const char *path,
int flags,
const Env *new_env) {
if (fd_ >= 0) {
LOG(ERROR) << "Attempted to Initialize while in use";
return false;
}
if (!new_env) {
DLOG(INFO) << "Using the default Env";
} else {
env_ = new_env;
}
if (flags & O_CREAT) {
// TODO(wad) less hacky
fd_ = env()->Create(path, flags, S_IRUSR|S_IWUSR);
} else {
fd_ = env()->Open(path, flags);
}
if (fd_ < 0) {
PLOG(ERROR) << "Failed to open the specified file";
return false;
}
return true;
}
void File::Reset() {
if (fd_ >= 0) {
env()->Close(fd_);
fd_ = -1;
}
env_ = NULL;
offset_ = 0;
delete default_env_;
default_env_ = new Env;
}
bool File::Seek(off_t location, bool absolute) {
int64_t size = Size();
if (absolute) {
if (location > size || location < 0)
return false;
offset_ = location;
return true;
}
off_t result = location + offset_;
if (result < 0 || result > size) {
return false;
}
offset_ = result;
return true;
}
off_t File::Whence() const {
return offset_;
}
bool File::Read(int bytes, uint8_t *buf) {
if (!ReadAt(bytes, buf, offset_)) {
return false;
}
offset_ += bytes;
return true;
}
bool File::ReadAt(int bytes, uint8_t *buf, off_t offset) {
if (fd_ < 0) {
LOG(ERROR) << "Read called with an invalid fd";
return false;
}
if (bytes <= 0) {
LOG(ERROR) << "Negative or 0 sized read requested";
return false;
}
ssize_t in_bytes = env()->Pread(fd_, buf, bytes, offset);
if (in_bytes == bytes) {
return true;
}
if (in_bytes < 0) {
// TODO(wad) Roll PLOG into the Env so that errno logging is encapsulated.
PLOG(ERROR) << "An error occurred reading from the file";
return false;
}
DLOG(INFO) << "Failed to read the total number of bytes requested.";
return false;
}
int64_t File::Size() const {
if (fd_ < 0) {
LOG(ERROR) << "Size called with an invalid fd";
return false;
}
struct stat buf;
if (env()->Fstat(fd_, &buf)) {
PLOG(ERROR) << "Failed to fstat() the file";
return -1;
}
if (!S_ISBLK(buf.st_mode)) {
return static_cast<int64_t>(buf.st_size);
}
// Handle use on block devices.
int64_t size = -1;
if (env()->BlockDevSize(fd_, &size)) {
PLOG(ERROR) << "Failed to get the block device size";
return -1;
}
return size;
}
bool File::WriteAt(int bytes, const uint8_t *buf, off_t offset) {
if (fd_ < 0) {
LOG(ERROR) << "Write called with an invalid fd";
return false;
}
if (bytes <= 0) {
LOG(ERROR) << "Negative or 0 sized write requested";
return false;
}
ssize_t out_bytes = env()->Pwrite(fd_, buf, bytes, offset);
if (out_bytes == bytes) {
return true;
}
if (out_bytes < 0) {
PLOG(ERROR) << "An error occurred writing to the file at " << offset;
return false;
}
DLOG(INFO) << "Failed to write the total number of bytes requested.";
return false;
}
bool File::Write(int bytes, const uint8_t *buf) {
if (!WriteAt(bytes, buf, offset_)) {
return false;
}
offset_ += bytes;
return true;
}
} // namespace simple_file