fd_file.cc revision 07ed66b5ae659c452cbe1ab20c3dbf1d6f546461
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) {
33761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes}
34761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes
35761600567d73b23324ae0251e871c15d6849ffd8Elliott HughesFdFile::~FdFile() {
36761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  if (auto_close_ && fd_ != -1) {
37761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes    Close();
38761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  }
39761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes}
40761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes
41761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughesvoid FdFile::DisableAutoClose() {
42761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  auto_close_ = false;
43761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes}
44761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes
45761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughesbool FdFile::Open(const std::string& path, int flags) {
46761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  return Open(path, flags, 0640);
47761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes}
48761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes
49761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughesbool FdFile::Open(const std::string& path, int flags, mode_t mode) {
50761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  CHECK_EQ(fd_, -1) << path;
51761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  fd_ = TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode));
52761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  if (fd_ == -1) {
53761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes    return false;
54761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  }
55761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  file_path_ = path;
56761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  return true;
57761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes}
58761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes
59761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughesint FdFile::Close() {
60761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  int result = TEMP_FAILURE_RETRY(close(fd_));
61761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  if (result == -1) {
62761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes    return -errno;
63761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  } else {
64761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes    fd_ = -1;
65761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes    file_path_ = "";
66761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes    return 0;
67761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  }
68761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes}
69761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes
70761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughesint FdFile::Flush() {
71761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  int rc = TEMP_FAILURE_RETRY(fdatasync(fd_));
72761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  return (rc == -1) ? -errno : rc;
73761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes}
74761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes
75761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughesint64_t FdFile::Read(char* buf, int64_t byte_count, int64_t offset) const {
76761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  int rc = TEMP_FAILURE_RETRY(pread64(fd_, buf, byte_count, offset));
77761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  return (rc == -1) ? -errno : rc;
78761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes}
79761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes
80761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughesint FdFile::SetLength(int64_t new_length) {
81761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  int rc = TEMP_FAILURE_RETRY(ftruncate64(fd_, new_length));
82761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  return (rc == -1) ? -errno : rc;
83761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes}
84761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes
85761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughesint64_t FdFile::GetLength() const {
86761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  struct stat s;
87761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  int rc = TEMP_FAILURE_RETRY(fstat(fd_, &s));
88761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  return (rc == -1) ? -errno : s.st_size;
89761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes}
90761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes
91761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughesint64_t FdFile::Write(const char* buf, int64_t byte_count, int64_t offset) {
92761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  int rc = TEMP_FAILURE_RETRY(pwrite64(fd_, buf, byte_count, offset));
93761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  return (rc == -1) ? -errno : rc;
94761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes}
95761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes
96761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughesint FdFile::Fd() const {
97761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  return fd_;
98761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes}
99761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes
100761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughesbool FdFile::IsOpened() const {
101761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  return fd_ >= 0;
102761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes}
103761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes
104761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughesstd::string FdFile::GetPath() const {
105761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  return file_path_;
106761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes}
107761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes
108761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughesbool FdFile::ReadFully(void* buffer, int64_t byte_count) {
109761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  char* ptr = static_cast<char*>(buffer);
110761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  while (byte_count > 0) {
111761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes    int bytes_read = TEMP_FAILURE_RETRY(read(fd_, ptr, byte_count));
112761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes    if (bytes_read <= 0) {
113761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes      return false;
114761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes    }
115761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes    byte_count -= bytes_read;  // Reduce the number of remaining bytes.
116761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes    ptr += bytes_read;  // Move the buffer forward.
117761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  }
118761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  return true;
119761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes}
120761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes
121761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughesbool FdFile::WriteFully(const void* buffer, int64_t byte_count) {
122761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  const char* ptr = static_cast<const char*>(buffer);
123761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  while (byte_count > 0) {
124761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes    int bytes_read = TEMP_FAILURE_RETRY(write(fd_, ptr, byte_count));
125761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes    if (bytes_read < 0) {
126761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes      return false;
127761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes    }
128761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes    byte_count -= bytes_read;  // Reduce the number of remaining bytes.
129761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes    ptr += bytes_read;  // Move the buffer forward.
130761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  }
131761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  return true;
132761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes}
133761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes
134761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes}  // namespace unix_file
135