| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // LICENSE file. | |
| 4 | |
| 5 // For 64-bit file access (off_t = off64_t, lseek64, etc). | |
| 6 #define _FILE_OFFSET_BITS 64 | |
| 7 | |
| 8 #include "net/base/file_input_stream.h" | |
| 9 | |
| 10 #include <sys/types.h> | |
| 11 #include <sys/stat.h> | |
| 12 #include <fcntl.h> | |
| 13 #include <unistd.h> | |
| 14 #include <errno.h> | |
| 15 | |
| 16 #include "base/basictypes.h" | |
| 17 #include "base/logging.h" | |
| 18 #include "base/message_loop.h" | |
| 19 #include "base/string_util.h" | |
| 20 #include "net/base/net_errors.h" | |
| 21 | |
| 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); | |
| 24 | |
| 25 // Make sure our Whence mappings match the system headers. | |
| 26 COMPILE_ASSERT(net::FROM_BEGIN == SEEK_SET && | |
| 27 net::FROM_CURRENT == SEEK_CUR && | |
| 28 net::FROM_END == SEEK_END, whence_matches_system); | |
| 29 | |
| 30 namespace net { | |
| 31 | |
| 32 // FileInputStream::AsyncContext ---------------------------------------------- | |
| 33 | |
| 34 // TODO(deanm): Figure out how to best do async IO. | |
| 35 class FileInputStream::AsyncContext { | |
| 36 public: | |
| 37 | |
| 38 CompletionCallback* callback() const { return NULL; } | |
| 39 private: | |
| 40 | |
| 41 DISALLOW_COPY_AND_ASSIGN(AsyncContext); | |
| 42 }; | |
| 43 | |
| 44 // FileInputStream ------------------------------------------------------------ | |
| 45 | |
| 46 FileInputStream::FileInputStream() : fd_(-1) { | |
| 47 DCHECK(!IsOpen()); | |
| 48 } | |
| 49 | |
| 50 FileInputStream::~FileInputStream() { | |
| 51 Close(); | |
| 52 } | |
| 53 | |
| 54 void FileInputStream::Close() { | |
| 55 if (fd_ != -1) { | |
| 56 if (close(fd_) != 0) { | |
| 57 NOTREACHED(); | |
| 58 } | |
| 59 fd_ = -1; | |
| 60 } | |
| 61 async_context_.reset(); | |
| 62 } | |
| 63 | |
| 64 // Map from errno to net error codes. | |
| 65 static int64 MapErrorCode(int err) { | |
| 66 switch(err) { | |
| 67 case ENOENT: | |
| 68 return ERR_FILE_NOT_FOUND; | |
| 69 case EACCES: | |
| 70 return ERR_ACCESS_DENIED; | |
| 71 default: | |
| 72 LOG(WARNING) << "Unknown error " << err << " mapped to net::ERR_FAILED"; | |
| 73 return ERR_FAILED; | |
| 74 } | |
| 75 } | |
| 76 | |
| 77 int FileInputStream::Open(const std::wstring& path, bool asynchronous_mode) { | |
| 78 // We don't need O_LARGEFILE here since we set the 64-bit off_t feature. | |
| 79 fd_ = open(WideToUTF8(path).c_str(), 0, O_RDONLY); | |
| 80 if (fd_ == -1) | |
| 81 return MapErrorCode(errno); | |
| 82 | |
| 83 return OK; | |
| 84 } | |
| 85 | |
| 86 bool FileInputStream::IsOpen() const { | |
| 87 return fd_ != -1; | |
| 88 } | |
| 89 | |
| 90 int64 FileInputStream::Seek(Whence whence, int64 offset) { | |
| 91 if (!IsOpen()) | |
| 92 return ERR_UNEXPECTED; | |
| 93 | |
| 94 // If we're in async, make sure we don't have a request in flight. | |
| 95 DCHECK(!async_context_.get() || !async_context_->callback()); | |
| 96 | |
| 97 off_t res = lseek(fd_, static_cast<off_t>(offset), static_cast<int>(whence)); | |
| 98 if (res == static_cast<off_t>(-1)) | |
| 99 return MapErrorCode(errno); | |
| 100 | |
| 101 return res; | |
| 102 } | |
| 103 | |
| 104 int64 FileInputStream::Available() { | |
| 105 if (!IsOpen()) | |
| 106 return ERR_UNEXPECTED; | |
| 107 | |
| 108 int64 cur_pos = Seek(FROM_CURRENT, 0); | |
| 109 if (cur_pos < 0) | |
| 110 return cur_pos; | |
| 111 | |
| 112 struct stat info; | |
| 113 if (fstat(fd_, &info) != 0) | |
| 114 return MapErrorCode(errno); | |
| 115 | |
| 116 int64 size = static_cast<int64>(info.st_size); | |
| 117 DCHECK(size >= cur_pos); | |
| 118 | |
| 119 return size - cur_pos; | |
| 120 } | |
| 121 | |
| 122 // TODO(deanm): async. | |
| 123 int FileInputStream::Read( | |
| 124 char* buf, int buf_len, CompletionCallback* callback) { | |
| 125 // read(..., 0) will return 0, which indicates end-of-file. | |
| 126 DCHECK(buf_len > 0 && buf_len <= SSIZE_MAX); | |
| 127 | |
| 128 if (!IsOpen()) | |
| 129 return ERR_UNEXPECTED; | |
| 130 | |
| 131 // Loop in the case of getting interrupted by a signal. | |
| 132 for (;;) { | |
| 133 ssize_t res = read(fd_, buf, static_cast<size_t>(buf_len)); | |
| 134 if (res == static_cast<ssize_t>(-1)) { | |
| 135 if (errno == EINTR) | |
| 136 continue; | |
| 137 return MapErrorCode(errno); | |
| 138 } | |
| 139 return static_cast<int>(res); | |
| 140 } | |
| 141 } | |
| 142 | |
| 143 } // namespace net | |
| OLD | NEW |