| OLD | NEW |
| 1 // Copyright (c) 2008 The Chromium Authors. All rights reserved. Use of this | 1 // Copyright (c) 2008 The Chromium Authors. All rights reserved. Use of this |
| 2 // source code is governed by a BSD-style license that can be found in the | 2 // source code is governed by a BSD-style license that can be found in the |
| 3 // LICENSE file. | 3 // LICENSE file. |
| 4 | 4 |
| 5 // For 64-bit file access (off_t = off64_t, lseek64, etc). | 5 // For 64-bit file access (off_t = off64_t, lseek64, etc). |
| 6 #define _FILE_OFFSET_BITS 64 | 6 #define _FILE_OFFSET_BITS 64 |
| 7 | 7 |
| 8 #include "net/base/file_input_stream.h" | 8 #include "net/base/file_stream.h" |
| 9 | 9 |
| 10 #include <sys/types.h> | 10 #include <sys/types.h> |
| 11 #include <sys/stat.h> | 11 #include <sys/stat.h> |
| 12 #include <fcntl.h> | 12 #include <fcntl.h> |
| 13 #include <unistd.h> | 13 #include <unistd.h> |
| 14 #include <errno.h> | 14 #include <errno.h> |
| 15 | 15 |
| 16 #include "base/basictypes.h" | 16 #include "base/basictypes.h" |
| 17 #include "base/logging.h" | 17 #include "base/logging.h" |
| 18 #include "base/message_loop.h" | 18 #include "base/message_loop.h" |
| 19 #include "base/string_util.h" | 19 #include "base/string_util.h" |
| 20 #include "net/base/net_errors.h" | 20 #include "net/base/net_errors.h" |
| 21 | 21 |
| 22 // We cast back and forth, so make sure it's the size we're expecting. | 22 // We cast back and forth, so make sure it's the size we're expecting. |
| 23 COMPILE_ASSERT(sizeof(int64) == sizeof(off_t), off_t_64_bit); | 23 COMPILE_ASSERT(sizeof(int64) == sizeof(off_t), off_t_64_bit); |
| 24 | 24 |
| 25 // Make sure our Whence mappings match the system headers. | 25 // Make sure our Whence mappings match the system headers. |
| 26 COMPILE_ASSERT(net::FROM_BEGIN == SEEK_SET && | 26 COMPILE_ASSERT(net::FROM_BEGIN == SEEK_SET && |
| 27 net::FROM_CURRENT == SEEK_CUR && | 27 net::FROM_CURRENT == SEEK_CUR && |
| 28 net::FROM_END == SEEK_END, whence_matches_system); | 28 net::FROM_END == SEEK_END, whence_matches_system); |
| 29 | 29 |
| 30 namespace net { | 30 namespace net { |
| 31 | 31 |
| 32 // FileInputStream::AsyncContext ---------------------------------------------- | 32 // FileStream::AsyncContext ---------------------------------------------- |
| 33 | 33 |
| 34 // TODO(deanm): Figure out how to best do async IO. | 34 // TODO(deanm): Figure out how to best do async IO. |
| 35 class FileInputStream::AsyncContext { | 35 class FileStream::AsyncContext { |
| 36 public: | 36 public: |
| 37 | 37 |
| 38 CompletionCallback* callback() const { return NULL; } | 38 CompletionCallback* callback() const { return NULL; } |
| 39 private: | 39 private: |
| 40 | 40 |
| 41 DISALLOW_COPY_AND_ASSIGN(AsyncContext); | 41 DISALLOW_COPY_AND_ASSIGN(AsyncContext); |
| 42 }; | 42 }; |
| 43 | 43 |
| 44 // FileInputStream ------------------------------------------------------------ | 44 // FileStream ------------------------------------------------------------ |
| 45 | 45 |
| 46 FileInputStream::FileInputStream() : fd_(-1) { | 46 FileStream::FileStream() : file_(base::kInvalidPlatformFileValue) { |
| 47 DCHECK(!IsOpen()); | 47 DCHECK(!IsOpen()); |
| 48 } | 48 } |
| 49 | 49 |
| 50 FileInputStream::~FileInputStream() { | 50 FileStream::~FileStream() { |
| 51 Close(); | 51 Close(); |
| 52 } | 52 } |
| 53 | 53 |
| 54 void FileInputStream::Close() { | 54 void FileStream::Close() { |
| 55 if (fd_ != -1) { | 55 if (file_ != base::kInvalidPlatformFileValue) { |
| 56 if (close(fd_) != 0) { | 56 if (close(file_) != 0) { |
| 57 NOTREACHED(); | 57 NOTREACHED(); |
| 58 } | 58 } |
| 59 fd_ = -1; | 59 file_ = base::kInvalidPlatformFileValue; |
| 60 } | 60 } |
| 61 async_context_.reset(); | 61 async_context_.reset(); |
| 62 } | 62 } |
| 63 | 63 |
| 64 // Map from errno to net error codes. | 64 // Map from errno to net error codes. |
| 65 static int64 MapErrorCode(int err) { | 65 static int64 MapErrorCode(int err) { |
| 66 switch(err) { | 66 switch(err) { |
| 67 case ENOENT: | 67 case ENOENT: |
| 68 return ERR_FILE_NOT_FOUND; | 68 return ERR_FILE_NOT_FOUND; |
| 69 case EACCES: | 69 case EACCES: |
| 70 return ERR_ACCESS_DENIED; | 70 return ERR_ACCESS_DENIED; |
| 71 default: | 71 default: |
| 72 LOG(WARNING) << "Unknown error " << err << " mapped to net::ERR_FAILED"; | 72 LOG(WARNING) << "Unknown error " << err << " mapped to net::ERR_FAILED"; |
| 73 return ERR_FAILED; | 73 return ERR_FAILED; |
| 74 } | 74 } |
| 75 } | 75 } |
| 76 | 76 |
| 77 int FileInputStream::Open(const std::wstring& path, bool asynchronous_mode) { | 77 int FileStream::Open(const std::wstring& path, int open_flags) { |
| 78 // We don't need O_LARGEFILE here since we set the 64-bit off_t feature. | 78 if (IsOpen()) { |
| 79 fd_ = open(WideToUTF8(path).c_str(), 0, O_RDONLY); | 79 DLOG(FATAL) << "File is already open!"; |
| 80 if (fd_ == -1) | 80 return ERR_UNEXPECTED; |
| 81 } |
| 82 |
| 83 open_flags_ = open_flags; |
| 84 file_ = base::CreatePlatformFile(path, open_flags_, NULL); |
| 85 if (file_ == base::kInvalidPlatformFileValue) { |
| 86 LOG(WARNING) << "Failed to open file: " << errno; |
| 81 return MapErrorCode(errno); | 87 return MapErrorCode(errno); |
| 88 } |
| 82 | 89 |
| 83 return OK; | 90 return OK; |
| 84 } | 91 } |
| 85 | 92 |
| 86 bool FileInputStream::IsOpen() const { | 93 bool FileStream::IsOpen() const { |
| 87 return fd_ != -1; | 94 return file_ != base::kInvalidPlatformFileValue; |
| 88 } | 95 } |
| 89 | 96 |
| 90 int64 FileInputStream::Seek(Whence whence, int64 offset) { | 97 int64 FileStream::Seek(Whence whence, int64 offset) { |
| 91 if (!IsOpen()) | 98 if (!IsOpen()) |
| 92 return ERR_UNEXPECTED; | 99 return ERR_UNEXPECTED; |
| 93 | 100 |
| 94 // If we're in async, make sure we don't have a request in flight. | 101 // If we're in async, make sure we don't have a request in flight. |
| 95 DCHECK(!async_context_.get() || !async_context_->callback()); | 102 DCHECK(!async_context_.get() || !async_context_->callback()); |
| 96 | 103 |
| 97 off_t res = lseek(fd_, static_cast<off_t>(offset), static_cast<int>(whence)); | 104 off_t res = lseek(file_, static_cast<off_t>(offset), |
| 105 static_cast<int>(whence)); |
| 98 if (res == static_cast<off_t>(-1)) | 106 if (res == static_cast<off_t>(-1)) |
| 99 return MapErrorCode(errno); | 107 return MapErrorCode(errno); |
| 100 | 108 |
| 101 return res; | 109 return res; |
| 102 } | 110 } |
| 103 | 111 |
| 104 int64 FileInputStream::Available() { | 112 int64 FileStream::Available() { |
| 105 if (!IsOpen()) | 113 if (!IsOpen()) |
| 106 return ERR_UNEXPECTED; | 114 return ERR_UNEXPECTED; |
| 107 | 115 |
| 108 int64 cur_pos = Seek(FROM_CURRENT, 0); | 116 int64 cur_pos = Seek(FROM_CURRENT, 0); |
| 109 if (cur_pos < 0) | 117 if (cur_pos < 0) |
| 110 return cur_pos; | 118 return cur_pos; |
| 111 | 119 |
| 112 struct stat info; | 120 struct stat info; |
| 113 if (fstat(fd_, &info) != 0) | 121 if (fstat(file_, &info) != 0) |
| 114 return MapErrorCode(errno); | 122 return MapErrorCode(errno); |
| 115 | 123 |
| 116 int64 size = static_cast<int64>(info.st_size); | 124 int64 size = static_cast<int64>(info.st_size); |
| 117 DCHECK(size >= cur_pos); | 125 DCHECK(size >= cur_pos); |
| 118 | 126 |
| 119 return size - cur_pos; | 127 return size - cur_pos; |
| 120 } | 128 } |
| 121 | 129 |
| 122 // TODO(deanm): async. | 130 // TODO(deanm): async. |
| 123 int FileInputStream::Read( | 131 int FileStream::Read( |
| 124 char* buf, int buf_len, CompletionCallback* callback) { | 132 char* buf, int buf_len, CompletionCallback* callback) { |
| 125 // read(..., 0) will return 0, which indicates end-of-file. | 133 // read(..., 0) will return 0, which indicates end-of-file. |
| 126 DCHECK(buf_len > 0 && buf_len <= SSIZE_MAX); | 134 DCHECK(buf_len > 0 && buf_len <= SSIZE_MAX); |
| 127 | 135 |
| 128 if (!IsOpen()) | 136 if (!IsOpen()) |
| 129 return ERR_UNEXPECTED; | 137 return ERR_UNEXPECTED; |
| 130 | 138 |
| 131 // Loop in the case of getting interrupted by a signal. | 139 // Loop in the case of getting interrupted by a signal. |
| 132 for (;;) { | 140 for (;;) { |
| 133 ssize_t res = read(fd_, buf, static_cast<size_t>(buf_len)); | 141 ssize_t res = read(file_, buf, static_cast<size_t>(buf_len)); |
| 134 if (res == static_cast<ssize_t>(-1)) { | 142 if (res == static_cast<ssize_t>(-1)) { |
| 135 if (errno == EINTR) | 143 if (errno == EINTR) |
| 136 continue; | 144 continue; |
| 137 return MapErrorCode(errno); | 145 return MapErrorCode(errno); |
| 138 } | 146 } |
| 139 return static_cast<int>(res); | 147 return static_cast<int>(res); |
| 140 } | 148 } |
| 141 } | 149 } |
| 142 | 150 |
| 151 // TODO(deanm): async. |
| 152 int FileStream::Write( |
| 153 const char* buf, int buf_len, CompletionCallback* callback) { |
| 154 |
| 155 // read(..., 0) will return 0, which indicates end-of-file. |
| 156 DCHECK(buf_len > 0 && buf_len <= SSIZE_MAX); |
| 157 |
| 158 if (!IsOpen()) |
| 159 return ERR_UNEXPECTED; |
| 160 |
| 161 int total_bytes_written = 0; |
| 162 size_t len = static_cast<size_t>(buf_len); |
| 163 while (total_bytes_written < buf_len) { |
| 164 ssize_t res = write(file_, buf, len); |
| 165 if (res == static_cast<ssize_t>(-1)) { |
| 166 if (errno == EINTR) |
| 167 continue; |
| 168 return MapErrorCode(errno); |
| 169 } |
| 170 total_bytes_written += res; |
| 171 buf += res; |
| 172 len -= res; |
| 173 } |
| 174 return total_bytes_written; |
| 175 } |
| 176 |
| 143 } // namespace net | 177 } // namespace net |
| OLD | NEW |