diff options
author | deanm@chromium.org <deanm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-10-06 10:17:31 +0000 |
---|---|---|
committer | deanm@chromium.org <deanm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-10-06 10:17:31 +0000 |
commit | 095214d9fd4f7dc5b9218d3fe78cf3ee08f480b8 (patch) | |
tree | 15e796824bac8c4825cf03ea9e179c3db59209fb /net | |
parent | cdd6c77f03f43b3531ae504d4c067b235d786ff4 (diff) | |
download | chromium_src-095214d9fd4f7dc5b9218d3fe78cf3ee08f480b8.zip chromium_src-095214d9fd4f7dc5b9218d3fe78cf3ee08f480b8.tar.gz chromium_src-095214d9fd4f7dc5b9218d3fe78cf3ee08f480b8.tar.bz2 |
Add Posix sync only support to FileInputStream.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@2875 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r-- | net/SConscript | 2 | ||||
-rw-r--r-- | net/base/file_input_stream.h | 14 | ||||
-rw-r--r-- | net/base/file_input_stream_posix.cc | 110 |
3 files changed, 107 insertions, 19 deletions
diff --git a/net/SConscript b/net/SConscript index 28f730b..ed8faa8 100644 --- a/net/SConscript +++ b/net/SConscript @@ -230,6 +230,7 @@ unittest_files = [ 'base/cookie_policy_unittest.cc', 'base/data_url_unittest.cc', 'base/escape_unittest.cc', + 'base/file_input_stream_unittest.cc', 'base/gzip_filter_unittest.cc', 'base/host_resolver_unittest.cc', 'base/mime_sniffer_unittest.cc', @@ -258,7 +259,6 @@ unittest_files = [ if env['PLATFORM'] == 'win32': unittest_files.extend([ 'base/directory_lister_unittest.cc', - 'base/file_input_stream_unittest.cc', 'base/sdch_filter_unitest.cc', 'base/ssl_config_service_unittest.cc', 'base/ssl_client_socket_unittest.cc', diff --git a/net/base/file_input_stream.h b/net/base/file_input_stream.h index efebadc..eb4b2ae 100644 --- a/net/base/file_input_stream.h +++ b/net/base/file_input_stream.h @@ -17,10 +17,11 @@ typedef void* HANDLE; namespace net { // TODO(darin): Move this to a more generic location. +// This explicit mapping matches both FILE_ on Windows and SEEK_ on Linux. enum Whence { - FROM_BEGIN, - FROM_CURRENT, - FROM_END + FROM_BEGIN = 0, + FROM_CURRENT = 1, + FROM_END = 2 }; class FileInputStream { @@ -35,10 +36,7 @@ class FileInputStream { // Call this method to open the FileInputStream. The remaining methods // cannot be used unless this method returns OK. If the file cannot be // opened then an error code is returned. - // - // NOTE: The file input stream is opened with non-exclusive access to the - // underlying file. - // + // NOTE: The underlying file is opened with non-exclusive access. int Open(const std::wstring& path, bool asynchronous_mode); // Returns true if Open succeeded and Close has not been called. @@ -82,6 +80,8 @@ class FileInputStream { #if defined(OS_WIN) HANDLE handle_; +#elif defined(OS_POSIX) + int fd_; #endif DISALLOW_COPY_AND_ASSIGN(FileInputStream); diff --git a/net/base/file_input_stream_posix.cc b/net/base/file_input_stream_posix.cc index 335805c..4f2eb937 100644 --- a/net/base/file_input_stream_posix.cc +++ b/net/base/file_input_stream_posix.cc @@ -2,21 +2,49 @@ // source code is governed by a BSD-style license that can be found in the // LICENSE file. +// For 64-bit file access (off_t = off64_t, lseek64, etc). +#define _FILE_OFFSET_BITS 64 + #include "net/base/file_input_stream.h" +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> + +#include "base/basictypes.h" #include "base/logging.h" +#include "base/message_loop.h" +#include "base/string_util.h" #include "net/base/net_errors.h" +// We cast back and forth, so make sure it's the size we're expecting. +COMPILE_ASSERT(sizeof(int64) == sizeof(off_t), off_t_64_bit); + +// Make sure our Whence mappings match the system headers. +COMPILE_ASSERT(net::FROM_BEGIN == SEEK_SET && + net::FROM_CURRENT == SEEK_CUR && + net::FROM_END == SEEK_END, whence_matches_system); + namespace net { // FileInputStream::AsyncContext ---------------------------------------------- +// TODO(deanm): Figure out how to best do async IO. class FileInputStream::AsyncContext { + public: + + CompletionCallback* callback() const { return NULL; } + private: + + DISALLOW_COPY_AND_ASSIGN(AsyncContext); }; // FileInputStream ------------------------------------------------------------ -FileInputStream::FileInputStream() { +FileInputStream::FileInputStream() : fd_(-1) { + DCHECK(!IsOpen()); } FileInputStream::~FileInputStream() { @@ -24,32 +52,92 @@ FileInputStream::~FileInputStream() { } void FileInputStream::Close() { + if (fd_ != -1) { + if (close(fd_) != 0) { + NOTREACHED(); + } + fd_ = -1; + } + async_context_.reset(); +} + +// Map from errno to net error codes. +static int64 MapErrorCode(int err) { + switch(err) { + case ENOENT: + return ERR_FILE_NOT_FOUND; + case EACCES: + return ERR_ACCESS_DENIED; + default: + LOG(WARNING) << "Unknown error " << err << " mapped to net::ERR_FAILED"; + return ERR_FAILED; + } } int FileInputStream::Open(const std::wstring& path, bool asynchronous_mode) { - NOTIMPLEMENTED(); - return ERR_FAILED; + // We don't need O_LARGEFILE here since we set the 64-bit off_t feature. + fd_ = open(WideToUTF8(path).c_str(), 0, O_RDONLY); + if (fd_ == -1) + return MapErrorCode(errno); + + return OK; } bool FileInputStream::IsOpen() const { - NOTIMPLEMENTED(); - return false; + return fd_ != -1; } int64 FileInputStream::Seek(Whence whence, int64 offset) { - NOTIMPLEMENTED(); - return ERR_FAILED; + if (!IsOpen()) + return ERR_UNEXPECTED; + + // If we're in async, make sure we don't have a request in flight. + DCHECK(!async_context_.get() || !async_context_->callback()); + + off_t res = lseek(fd_, static_cast<off_t>(offset), static_cast<int>(whence)); + if (res == static_cast<off_t>(-1)) + return MapErrorCode(errno); + + return res; } int64 FileInputStream::Available() { - NOTIMPLEMENTED(); - return ERR_FAILED; + if (!IsOpen()) + return ERR_UNEXPECTED; + + int64 cur_pos = Seek(FROM_CURRENT, 0); + if (cur_pos < 0) + return cur_pos; + + struct stat info; + if (fstat(fd_, &info) != 0) + return MapErrorCode(errno); + + int64 size = static_cast<int64>(info.st_size); + DCHECK(size >= cur_pos); + + return size - cur_pos; } +// TODO(deanm): async. int FileInputStream::Read( char* buf, int buf_len, CompletionCallback* callback) { - NOTIMPLEMENTED(); - return ERR_FAILED; + // read(..., 0) will return 0, which indicates end-of-file. + DCHECK(buf_len > 0 && buf_len <= SSIZE_MAX); + + if (!IsOpen()) + return ERR_UNEXPECTED; + + // Loop in the case of getting interrupted by a signal. + for (;;) { + ssize_t res = read(fd_, buf, static_cast<size_t>(buf_len)); + if (res == static_cast<ssize_t>(-1)) { + if (errno == EINTR) + continue; + return MapErrorCode(errno); + } + return static_cast<int>(res); + } } } // namespace net |