1761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes/*
2761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes * Copyright (C) 2009 The Android Open Source Project
3761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes *
4761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
5761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes * you may not use this file except in compliance with the License.
6761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes * You may obtain a copy of the License at
7761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes *
8761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
9761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes *
10761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes * Unless required by applicable law or agreed to in writing, software
11761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
12761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes * See the License for the specific language governing permissions and
14761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes * limitations under the License.
15761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes */
16761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes
1707ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include "base/logging.h"
18761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes#include "base/unix_file/fd_file.h"
19761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes#include <errno.h>
20761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes#include <sys/stat.h>
21761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes#include <sys/types.h>
22761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes#include <unistd.h>
23761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes
24761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughesnamespace unix_file {
25761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes
26761600567d73b23324ae0251e871c15d6849ffd8Elliott HughesFdFile::FdFile() : fd_(-1), auto_close_(true) {
27761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes}
28761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes
29761600567d73b23324ae0251e871c15d6849ffd8Elliott HughesFdFile::FdFile(int fd) : fd_(fd), auto_close_(true) {
30761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes}
31761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes
32761600567d73b23324ae0251e871c15d6849ffd8Elliott HughesFdFile::FdFile(int fd, const std::string& path) : fd_(fd), file_path_(path), auto_close_(true) {
33b45ccbf0e3c8f576de2f8608e12dc8c6ad002e0bBrian Carlstrom  CHECK_NE(0U, path.size());
34761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes}
35761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes
36761600567d73b23324ae0251e871c15d6849ffd8Elliott HughesFdFile::~FdFile() {
37761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  if (auto_close_ && fd_ != -1) {
38761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes    Close();
39761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  }
40761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes}
41761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes
42761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughesvoid FdFile::DisableAutoClose() {
43761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  auto_close_ = false;
44761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes}
45761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes
46761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughesbool FdFile::Open(const std::string& path, int flags) {
47761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  return Open(path, flags, 0640);
48761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes}
49761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes
50761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughesbool FdFile::Open(const std::string& path, int flags, mode_t mode) {
51761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  CHECK_EQ(fd_, -1) << path;
52761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  fd_ = TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode));
53761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  if (fd_ == -1) {
54761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes    return false;
55761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  }
56761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  file_path_ = path;
57761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  return true;
58761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes}
59761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes
60761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughesint FdFile::Close() {
61761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  int result = TEMP_FAILURE_RETRY(close(fd_));
62761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  if (result == -1) {
63761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes    return -errno;
64761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  } else {
65761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes    fd_ = -1;
66761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes    file_path_ = "";
67761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes    return 0;
68761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  }
69761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes}
70761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes
71761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughesint FdFile::Flush() {
72761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  int rc = TEMP_FAILURE_RETRY(fdatasync(fd_));
73761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  return (rc == -1) ? -errno : rc;
74761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes}
75761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes
76761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughesint64_t FdFile::Read(char* buf, int64_t byte_count, int64_t offset) const {
77761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  int rc = TEMP_FAILURE_RETRY(pread64(fd_, buf, byte_count, offset));
78761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  return (rc == -1) ? -errno : rc;
79761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes}
80761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes
81761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughesint FdFile::SetLength(int64_t new_length) {
82761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  int rc = TEMP_FAILURE_RETRY(ftruncate64(fd_, new_length));
83761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  return (rc == -1) ? -errno : rc;
84761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes}
85761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes
86761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughesint64_t FdFile::GetLength() const {
87761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  struct stat s;
88761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  int rc = TEMP_FAILURE_RETRY(fstat(fd_, &s));
89761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  return (rc == -1) ? -errno : s.st_size;
90761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes}
91761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes
92761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughesint64_t FdFile::Write(const char* buf, int64_t byte_count, int64_t offset) {
93761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  int rc = TEMP_FAILURE_RETRY(pwrite64(fd_, buf, byte_count, offset));
94761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  return (rc == -1) ? -errno : rc;
95761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes}
96761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes
97761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughesint FdFile::Fd() const {
98761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  return fd_;
99761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes}
100761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes
101761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughesbool FdFile::IsOpened() const {
102761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  return fd_ >= 0;
103761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes}
104761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes
105761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughesstd::string FdFile::GetPath() const {
106761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  return file_path_;
107761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes}
108761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes
109761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughesbool FdFile::ReadFully(void* buffer, int64_t byte_count) {
110761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  char* ptr = static_cast<char*>(buffer);
111761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  while (byte_count > 0) {
112761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes    int bytes_read = TEMP_FAILURE_RETRY(read(fd_, ptr, byte_count));
113761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes    if (bytes_read <= 0) {
114761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes      return false;
115761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes    }
116761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes    byte_count -= bytes_read;  // Reduce the number of remaining bytes.
117761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes    ptr += bytes_read;  // Move the buffer forward.
118761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  }
119761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  return true;
120761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes}
121761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes
122761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughesbool FdFile::WriteFully(const void* buffer, int64_t byte_count) {
123761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  const char* ptr = static_cast<const char*>(buffer);
124761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  while (byte_count > 0) {
125761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes    int bytes_read = TEMP_FAILURE_RETRY(write(fd_, ptr, byte_count));
126761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes    if (bytes_read < 0) {
127761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes      return false;
128761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes    }
129761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes    byte_count -= bytes_read;  // Reduce the number of remaining bytes.
130761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes    ptr += bytes_read;  // Move the buffer forward.
131761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  }
132761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  return true;
133761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes}
134761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes
135761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes}  // namespace unix_file
136