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 |