0

* Add write and read/write support to FileStream (renamed from FileInputStream).

* Moved net/disk_cache/os_file to base/platform_file.

Review URL: http://codereview.chromium.org/8843

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@4454 0039d316-1c4b-4281-b951-d872f2087c98
This commit is contained in:
erikkay@google.com
2008-11-03 17:18:14 +00:00
parent 0a173a23af
commit 21da6eb1f8
30 changed files with 775 additions and 503 deletions

@ -142,6 +142,7 @@
93E703170E5D63E00046259B /* platform_thread_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = 93E703160E5D63E00046259B /* platform_thread_posix.cc */; };
93E7031B0E5D64390046259B /* thread_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = 93E7031A0E5D64390046259B /* thread_unittest.cc */; };
93E703240E5D64F00046259B /* thread.cc in Sources */ = {isa = PBXBuildFile; fileRef = 93E703230E5D64F00046259B /* thread.cc */; };
A573F5D90EBB78260055A84A /* platform_file_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = A573F5D80EBB78260055A84A /* platform_file_posix.cc */; };
A5A026550E4A214600498DA9 /* file_util.cc in Sources */ = {isa = PBXBuildFile; fileRef = A5A026540E4A214600498DA9 /* file_util.cc */; };
A5A0268E0E4A2BDC00498DA9 /* file_util_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = A5A0268D0E4A2BDC00498DA9 /* file_util_posix.cc */; };
A5A0270B0E4A630D00498DA9 /* file_util_mac.mm in Sources */ = {isa = PBXBuildFile; fileRef = A5A0270A0E4A630D00498DA9 /* file_util_mac.mm */; };
@ -171,9 +172,6 @@
B57E4D780E9C26340090055D /* idletimer_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = B57E4D770E9C26340090055D /* idletimer_unittest.cc */; };
B5D544AB0EAFB7E000272A1C /* sys_string_conversions_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = B5D544AA0EAFB7E000272A1C /* sys_string_conversions_unittest.cc */; };
B5EF235C0E89ABF500E1E114 /* platform_canvas_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = ABE1BA0C0E756EC4009041DA /* platform_canvas_unittest.cc */; };
B5F7AFD20EB77ACA00EDB165 /* stats_table_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = B5F7AFD10EB77ACA00EDB165 /* stats_table_unittest.cc */; };
B5F7AFD80EB77B1600EDB165 /* process_util_mac.mm in Sources */ = {isa = PBXBuildFile; fileRef = B5F7AFD70EB77B1600EDB165 /* process_util_mac.mm */; };
B5F7B1F30EB7B3DA00EDB165 /* process_util_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7BD8F4A00E65AA2400034DE9 /* process_util_unittest.cc */; };
BA0F69870E79D7980079A8A1 /* thread_local_storage_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = BA0F69860E79D7980079A8A1 /* thread_local_storage_unittest.cc */; };
BA5CC5840E788093004EDD45 /* shared_memory_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = BA5CC5830E788093004EDD45 /* shared_memory_unittest.cc */; };
BA739A020E5E3242009842A7 /* tracked_objects_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = BA739A000E5E3242009842A7 /* tracked_objects_unittest.cc */; };
@ -607,6 +605,8 @@
93E703160E5D63E00046259B /* platform_thread_posix.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = platform_thread_posix.cc; sourceTree = "<group>"; };
93E7031A0E5D64390046259B /* thread_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = thread_unittest.cc; sourceTree = "<group>"; };
93E703230E5D64F00046259B /* thread.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = thread.cc; sourceTree = "<group>"; };
A573F5D70EBB78260055A84A /* platform_file.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = platform_file.h; sourceTree = "<group>"; };
A573F5D80EBB78260055A84A /* platform_file_posix.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = platform_file_posix.cc; sourceTree = "<group>"; };
A5A026180E48FE1500498DA9 /* base_paths_mac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = base_paths_mac.h; sourceTree = "<group>"; };
A5A026540E4A214600498DA9 /* file_util.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = file_util.cc; sourceTree = "<group>"; };
A5A0268D0E4A2BDC00498DA9 /* file_util_posix.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = file_util_posix.cc; sourceTree = "<group>"; };
@ -630,8 +630,6 @@
B52C916B0E9428F500208D01 /* clipboard_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = clipboard_unittest.cc; sourceTree = "<group>"; };
B57E4D770E9C26340090055D /* idletimer_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = idletimer_unittest.cc; sourceTree = "<group>"; };
B5D544AA0EAFB7E000272A1C /* sys_string_conversions_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sys_string_conversions_unittest.cc; sourceTree = "<group>"; };
B5F7AFD10EB77ACA00EDB165 /* stats_table_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = stats_table_unittest.cc; sourceTree = "<group>"; };
B5F7AFD70EB77B1600EDB165 /* process_util_mac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = process_util_mac.mm; sourceTree = "<group>"; };
BA0F69860E79D7980079A8A1 /* thread_local_storage_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = thread_local_storage_unittest.cc; sourceTree = "<group>"; };
BA5CC5830E788093004EDD45 /* shared_memory_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = shared_memory_unittest.cc; sourceTree = "<group>"; };
BA739A000E5E3242009842A7 /* tracked_objects_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = tracked_objects_unittest.cc; sourceTree = "<group>"; };
@ -933,6 +931,8 @@
8254033E0D92D2210006B936 /* pickle.cc */,
8254033F0D92D2210006B936 /* pickle.h */,
E4562C680E2803C3005E4685 /* pickle_unittest.cc */,
A573F5D70EBB78260055A84A /* platform_file.h */,
A573F5D80EBB78260055A84A /* platform_file_posix.cc */,
A5CB82960E5C74E300FD6825 /* platform_test.h */,
A5CB82970E5C74E300FD6825 /* platform_test_mac.mm */,
82E23FCB0D9C219600F8B40A /* platform_thread.h */,
@ -945,7 +945,6 @@
820EB4F10E3A6127009668FC /* process.cc */,
820EB4F20E3A6127009668FC /* process.h */,
825403510D92D24D0006B936 /* process_util.h */,
B5F7AFD70EB77B1600EDB165 /* process_util_mac.mm */,
7BD8F49F0E65AA2400034DE9 /* process_util_posix.cc */,
7BD8F4A00E65AA2400034DE9 /* process_util_unittest.cc */,
8254034B0D92D23C0006B936 /* prtime.cc */,
@ -994,7 +993,6 @@
825403780D92D2CF0006B936 /* stats_counters.h */,
825403790D92D2CF0006B936 /* stats_table.cc */,
8254037A0D92D2CF0006B936 /* stats_table.h */,
B5F7AFD10EB77ACA00EDB165 /* stats_table_unittest.cc */,
7BD8F7730E65E89800034DE9 /* string16.cc */,
821B91680DAABD7F00F350D7 /* string16.h */,
E4A133420E37A3C400110AA2 /* string_escape.cc */,
@ -1390,7 +1388,6 @@
824654A60DC25CD7007C2BAA /* pickle.cc in Sources */,
7BF164F30E660CA500AA999E /* platform_thread_mac.mm in Sources */,
93E703170E5D63E00046259B /* platform_thread_posix.cc in Sources */,
B5F7AFD80EB77B1600EDB165 /* process_util_mac.mm in Sources */,
7BD8F4A10E65AA4600034DE9 /* process_util_posix.cc in Sources */,
824654DF0DC26521007C2BAA /* prtime.cc in Sources */,
4D11B59A0E91730200EF7617 /* rand_util.cc in Sources */,
@ -1425,6 +1422,7 @@
9301C03B0E54C839001EF103 /* waitable_event_generic.cc in Sources */,
824655DD0DC659B8007C2BAA /* word_iterator.cc in Sources */,
7BF1658D0E663B4800AA999E /* worker_pool_mac.mm in Sources */,
A573F5D90EBB78260055A84A /* platform_file_posix.cc in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -1474,7 +1472,6 @@
7B78D3970E54FE0100609465 /* pickle_unittest.cc in Sources */,
B5EF235C0E89ABF500E1E114 /* platform_canvas_unittest.cc in Sources */,
A5CB82980E5C74E300FD6825 /* platform_test_mac.mm in Sources */,
B5F7B1F30EB7B3DA00EDB165 /* process_util_unittest.cc in Sources */,
7B8505D50E5B441000730B43 /* png_codec_unittest.cc in Sources */,
7B78D3980E54FE0100609465 /* pr_time_unittest.cc in Sources */,
4D11B59C0E91730500EF7617 /* rand_util_unittest.cc in Sources */,
@ -1487,7 +1484,6 @@
7BAE30E60E6D939F00C3F750 /* simple_thread_unittest.cc in Sources */,
7B78D39C0E54FE0100609465 /* singleton_unittest.cc in Sources */,
7B78D39D0E54FE0100609465 /* stack_container_unittest.cc in Sources */,
B5F7AFD20EB77ACA00EDB165 /* stats_table_unittest.cc in Sources */,
7B78D39E0E54FE0100609465 /* string_escape_unittest.cc in Sources */,
7B78D39F0E54FE0100609465 /* string_piece_unittest.cc in Sources */,
7B78D3A00E54FE0100609465 /* string_tokenizer_unittest.cc in Sources */,

@ -121,6 +121,7 @@ if env['PLATFORM'] == 'win32':
'lock_impl_win.cc',
'message_pump_win.cc',
'pe_image.cc',
'platform_file_win.cc',
'platform_thread_win.cc',
'process_util_win.cc',
'process_win.cc',
@ -146,6 +147,7 @@ if env['PLATFORM'] in ('darwin', 'posix'):
'file_util_posix.cc',
'lock_impl_posix.cc',
'message_pump_libevent.cc',
'platform_file_posix.cc',
'platform_thread_posix.cc',
'process_util_posix.cc',
'rand_util_posix.cc',

@ -529,6 +529,14 @@
RelativePath="..\pickle.h"
>
</File>
<File
RelativePath="..\platform_file.h"
>
</File>
<File
RelativePath="..\platform_file_win.cc"
>
</File>
<File
RelativePath="..\platform_thread.h"
>

46
base/platform_file.h Normal file

@ -0,0 +1,46 @@
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_PLATFORM_FILE_H_
#define BASE_PLATFORM_FILE_H_
#include "build/build_config.h"
#if defined(OS_WIN)
#include <windows.h>
#endif
#include <string>
namespace base {
#if defined(OS_WIN)
typedef HANDLE PlatformFile;
const PlatformFile kInvalidPlatformFileValue = INVALID_HANDLE_VALUE;
#elif defined(OS_POSIX)
typedef int PlatformFile;
const PlatformFile kInvalidPlatformFileValue = -1;
#endif
enum PlatformFileFlags {
PLATFORM_FILE_OPEN = 1,
PLATFORM_FILE_CREATE = 2,
PLATFORM_FILE_OPEN_ALWAYS = 4, // May create a new file.
PLATFORM_FILE_CREATE_ALWAYS = 8, // May overwrite an old file.
PLATFORM_FILE_READ = 16,
PLATFORM_FILE_WRITE = 32,
PLATFORM_FILE_EXCLUSIVE_READ = 64, // EXCLUSIVE is opposite of Windows SHARE
PLATFORM_FILE_EXCLUSIVE_WRITE = 128,
PLATFORM_FILE_ASYNC = 256
};
// Creates or open the given file. If PLATFORM_FILE_OPEN_ALWAYS is used, and
// |created| is provided, |created| will be set to true if the file was created
// or to false in case the file was just opened.
PlatformFile CreatePlatformFile(const std::wstring& name,
int flags,
bool* created);
} // namespace base
#endif // BASE_PLATFORM_FILE_H_

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "net/disk_cache/os_file.h"
#include "base/platform_file.h"
#include <fcntl.h>
#include <errno.h>
@ -10,30 +10,33 @@
#include "base/logging.h"
#include "base/string_util.h"
namespace disk_cache {
namespace base {
OSFile CreateOSFile(const std::wstring& name, int flags, bool* created) {
// TODO(erikkay): does it make sense to support PLATFORM_FILE_EXCLUSIVE_* here?
PlatformFile CreatePlatformFile(const std::wstring& name,
int flags,
bool* created) {
int open_flags = 0;
if (flags & OS_FILE_CREATE)
if (flags & PLATFORM_FILE_CREATE)
open_flags = O_CREAT | O_EXCL;
if (flags & OS_FILE_CREATE_ALWAYS) {
if (flags & PLATFORM_FILE_CREATE_ALWAYS) {
DCHECK(!open_flags);
open_flags = O_CREAT | O_TRUNC;
}
if (!open_flags && !(flags & OS_FILE_OPEN) &&
!(flags & OS_FILE_OPEN_ALWAYS)) {
if (!open_flags && !(flags & PLATFORM_FILE_OPEN) &&
!(flags & PLATFORM_FILE_OPEN_ALWAYS)) {
NOTREACHED();
errno = ENOTSUP;
return INVALID_HANDLE_VALUE;
}
if (flags & OS_FILE_WRITE && flags & OS_FILE_READ) {
if (flags & PLATFORM_FILE_WRITE && flags & PLATFORM_FILE_READ) {
open_flags |= O_RDWR;
} else if (flags & OS_FILE_WRITE) {
} else if (flags & PLATFORM_FILE_WRITE) {
open_flags |= O_WRONLY;
} else if (!(flags & OS_FILE_READ)) {
} else if (!(flags & PLATFORM_FILE_READ)) {
NOTREACHED();
}
@ -42,7 +45,7 @@ OSFile CreateOSFile(const std::wstring& name, int flags, bool* created) {
int descriptor = open(WideToUTF8(name).c_str(), open_flags,
S_IRUSR | S_IWUSR);
if (flags & OS_FILE_OPEN_ALWAYS) {
if (flags & PLATFORM_FILE_OPEN_ALWAYS) {
if (descriptor > 0) {
if (created)
*created = false;
@ -58,4 +61,4 @@ OSFile CreateOSFile(const std::wstring& name, int flags, bool* created) {
return descriptor;
}
} // namespace disk_cache
} // namespace base

63
base/platform_file_win.cc Normal file

@ -0,0 +1,63 @@
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/platform_file.h"
#include "base/logging.h"
namespace base {
PlatformFile CreatePlatformFile(const std::wstring& name,
int flags,
bool* created) {
DWORD disposition = 0;
if (flags & PLATFORM_FILE_OPEN)
disposition = OPEN_EXISTING;
if (flags & PLATFORM_FILE_CREATE) {
DCHECK(!disposition);
disposition = CREATE_NEW;
}
if (flags & PLATFORM_FILE_OPEN_ALWAYS) {
DCHECK(!disposition);
disposition = OPEN_ALWAYS;
}
if (flags & PLATFORM_FILE_CREATE_ALWAYS) {
DCHECK(!disposition);
disposition = CREATE_ALWAYS;
}
if (!disposition) {
NOTREACHED();
return NULL;
}
DWORD access = (flags & PLATFORM_FILE_READ) ? GENERIC_READ : 0;
if (flags & PLATFORM_FILE_WRITE)
access |= GENERIC_WRITE;
DWORD sharing = (flags & PLATFORM_FILE_EXCLUSIVE_READ) ? 0 : FILE_SHARE_READ;
if (!(flags & PLATFORM_FILE_EXCLUSIVE_WRITE))
sharing |= FILE_SHARE_WRITE;
DWORD create_flags = 0;
if (flags & PLATFORM_FILE_ASYNC)
create_flags |= FILE_FLAG_OVERLAPPED;
HANDLE file = CreateFile(name.c_str(), access, sharing, NULL, disposition,
create_flags, NULL);
if ((flags & PLATFORM_FILE_OPEN_ALWAYS) && created &&
INVALID_HANDLE_VALUE != file) {
*created = (ERROR_ALREADY_EXISTS != GetLastError());
}
return file;
}
} // namespace disk_cache

@ -1,205 +0,0 @@
// Copyright (c) 2008 The Chromium Authors. All rights reserved. Use of this
// source code is governed by a BSD-style license that can be found in the
// LICENSE file.
#include "base/file_util.h"
#include "base/path_service.h"
#include "base/platform_test.h"
#include "net/base/file_input_stream.h"
#include "net/base/net_errors.h"
#include "net/base/test_completion_callback.h"
#include "testing/gtest/include/gtest/gtest.h"
static const char kTestData[] = "0123456789";
class FileInputStreamTest : public PlatformTest {
public:
virtual void SetUp() {
PlatformTest::SetUp();
file_util::CreateTemporaryFileName(&temp_file_path_);
file_util::WriteFile(temp_file_path_, kTestData, arraysize(kTestData)-1);
}
virtual void TearDown() {
file_util::Delete(temp_file_path_, false);
PlatformTest::TearDown();
}
const std::wstring temp_file_path() const { return temp_file_path_; }
private:
std::wstring temp_file_path_;
};
TEST_F(FileInputStreamTest, BasicOpenClose) {
net::FileInputStream stream;
int rv = stream.Open(temp_file_path(), false);
EXPECT_EQ(net::OK, rv);
}
TEST_F(FileInputStreamTest, UseClosedStream) {
net::FileInputStream stream;
EXPECT_FALSE(stream.IsOpen());
// Try seeking...
int64 new_offset = stream.Seek(net::FROM_BEGIN, 5);
EXPECT_EQ(net::ERR_UNEXPECTED, new_offset);
// Try available...
int64 avail = stream.Available();
EXPECT_EQ(net::ERR_UNEXPECTED, avail);
// Try reading...
char buf[10];
int rv = stream.Read(buf, sizeof(buf), NULL);
EXPECT_EQ(net::ERR_UNEXPECTED, rv);
}
TEST_F(FileInputStreamTest, BasicRead) {
int64 file_size;
bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
EXPECT_TRUE(ok);
net::FileInputStream stream;
int rv = stream.Open(temp_file_path(), false);
EXPECT_EQ(net::OK, rv);
int64 total_bytes_avail = stream.Available();
EXPECT_EQ(file_size, total_bytes_avail);
int64 total_bytes_read = 0;
std::string data_read;
for (;;) {
char buf[4];
rv = stream.Read(buf, sizeof(buf), NULL);
EXPECT_LE(0, rv);
if (rv <= 0)
break;
total_bytes_read += rv;
data_read.append(buf, rv);
}
EXPECT_EQ(file_size, total_bytes_read);
EXPECT_TRUE(data_read == kTestData);
}
TEST_F(FileInputStreamTest, AsyncRead) {
int64 file_size;
bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
EXPECT_TRUE(ok);
net::FileInputStream stream;
int rv = stream.Open(temp_file_path(), true);
EXPECT_EQ(net::OK, rv);
int64 total_bytes_avail = stream.Available();
EXPECT_EQ(file_size, total_bytes_avail);
TestCompletionCallback callback;
int64 total_bytes_read = 0;
std::string data_read;
for (;;) {
char buf[4];
rv = stream.Read(buf, sizeof(buf), &callback);
if (rv == net::ERR_IO_PENDING)
rv = callback.WaitForResult();
EXPECT_LE(0, rv);
if (rv <= 0)
break;
total_bytes_read += rv;
data_read.append(buf, rv);
}
EXPECT_EQ(file_size, total_bytes_read);
EXPECT_TRUE(data_read == kTestData);
}
TEST_F(FileInputStreamTest, BasicRead_FromOffset) {
int64 file_size;
bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
EXPECT_TRUE(ok);
net::FileInputStream stream;
int rv = stream.Open(temp_file_path(), false);
EXPECT_EQ(net::OK, rv);
const int64 kOffset = 3;
int64 new_offset = stream.Seek(net::FROM_BEGIN, kOffset);
EXPECT_EQ(kOffset, new_offset);
int64 total_bytes_avail = stream.Available();
EXPECT_EQ(file_size - kOffset, total_bytes_avail);
int64 total_bytes_read = 0;
std::string data_read;
for (;;) {
char buf[4];
rv = stream.Read(buf, sizeof(buf), NULL);
EXPECT_LE(0, rv);
if (rv <= 0)
break;
total_bytes_read += rv;
data_read.append(buf, rv);
}
EXPECT_EQ(file_size - kOffset, total_bytes_read);
EXPECT_TRUE(data_read == kTestData + kOffset);
}
TEST_F(FileInputStreamTest, AsyncRead_FromOffset) {
int64 file_size;
bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
EXPECT_TRUE(ok);
net::FileInputStream stream;
int rv = stream.Open(temp_file_path(), true);
EXPECT_EQ(net::OK, rv);
const int64 kOffset = 3;
int64 new_offset = stream.Seek(net::FROM_BEGIN, kOffset);
EXPECT_EQ(kOffset, new_offset);
int64 total_bytes_avail = stream.Available();
EXPECT_EQ(file_size - kOffset, total_bytes_avail);
TestCompletionCallback callback;
int64 total_bytes_read = 0;
std::string data_read;
for (;;) {
char buf[4];
rv = stream.Read(buf, sizeof(buf), &callback);
if (rv == net::ERR_IO_PENDING)
rv = callback.WaitForResult();
EXPECT_LE(0, rv);
if (rv <= 0)
break;
total_bytes_read += rv;
data_read.append(buf, rv);
}
EXPECT_EQ(file_size - kOffset, total_bytes_read);
EXPECT_TRUE(data_read == kTestData + kOffset);
}
TEST_F(FileInputStreamTest, SeekAround) {
net::FileInputStream stream;
int rv = stream.Open(temp_file_path(), true);
EXPECT_EQ(net::OK, rv);
const int64 kOffset = 3;
int64 new_offset = stream.Seek(net::FROM_BEGIN, kOffset);
EXPECT_EQ(kOffset, new_offset);
new_offset = stream.Seek(net::FROM_CURRENT, kOffset);
EXPECT_EQ(2 * kOffset, new_offset);
new_offset = stream.Seek(net::FROM_CURRENT, -kOffset);
EXPECT_EQ(kOffset, new_offset);
const int kTestDataLen = arraysize(kTestData) - 1;
new_offset = stream.Seek(net::FROM_END, -kTestDataLen);
EXPECT_EQ(0, new_offset);
}

@ -2,18 +2,17 @@
// source code is governed by a BSD-style license that can be found in the
// LICENSE file.
// This file defines FileInputStream, a basic interface for reading files
// This file defines FileStream, a basic interface for reading and writing files
// synchronously or asynchronously with support for seeking to an offset.
// Note that even when used asynchronously, only one operation is supported at
// a time.
#ifndef NET_BASE_FILE_INPUT_STREAM_H_
#define NET_BASE_FILE_INPUT_STREAM_H_
#ifndef NET_BASE_FILE_STREAM_H_
#define NET_BASE_FILE_STREAM_H_
#include "base/platform_file.h"
#include "net/base/completion_callback.h"
#if defined(OS_WIN)
typedef void* HANDLE;
#endif
namespace net {
// TODO(darin): Move this to a more generic location.
@ -24,20 +23,21 @@ enum Whence {
FROM_END = 2
};
class FileInputStream {
class FileStream {
public:
FileInputStream();
~FileInputStream();
FileStream();
~FileStream();
// Call this method to close the FileInputStream. It is OK to call Close
// Call this method to close the FileStream. It is OK to call Close
// multiple times. Redundant calls are ignored.
// Note that if there are any pending async operations, they'll be aborted.
void Close();
// Call this method to open the FileInputStream. The remaining methods
// Call this method to open the FileStream. 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 underlying file is opened with non-exclusive access.
int Open(const std::wstring& path, bool asynchronous_mode);
// open_flags is a bitfield of base::PlatformFileFlags
int Open(const std::wstring& path, int open_flags);
// Returns true if Open succeeded and Close has not been called.
bool IsOpen() const;
@ -57,7 +57,7 @@ class FileInputStream {
// allowed.) Returns the number of bytes copied, 0 if at end-of-file, or an
// error code if the operation could not be performed.
//
// If opened with |asynchronous_mode| set to true, then a non-null callback
// If opened with PLATFORM_FILE_ASYNC, then a non-null callback
// must be passed to this method. In asynchronous mode, if the read could
// not complete synchronously, then ERR_IO_PENDING is returned, and the
// callback will be notified on the current thread (via the MessageLoop) when
@ -68,25 +68,42 @@ class FileInputStream {
// destroy or close the file stream while there is an asynchronous read in
// progress. That will cancel the read and allow the buffer to be freed.
//
// This method should not be called if the stream was opened WRITE_ONLY.
int Read(char* buf, int buf_len, CompletionCallback* callback);
// Call this method to write data at the current stream position. Up to
// buf_len bytes will be written from buf. (In other words, partial writes are
// allowed.) Returns the number of bytes written, or an error code if the
// operation could not be performed.
//
// If opened with PLATFORM_FILE_ASYNC, then a non-null callback
// must be passed to this method. In asynchronous mode, if the write could
// not complete synchronously, then ERR_IO_PENDING is returned, and the
// callback will be notified on the current thread (via the MessageLoop) when
// the write has completed.
//
// In the case of an asychronous write, the memory pointed to by |buf| must
// remain valid until the callback is notified. However, it is valid to
// destroy or close the file stream while there is an asynchronous write in
// progress. That will cancel the write and allow the buffer to be freed.
//
// This method should not be called if the stream was opened READ_ONLY.
int Write(const char* buf, int buf_len, CompletionCallback* callback);
private:
class AsyncContext;
friend class AsyncContext;
// This member is used to support asynchronous reads. It is non-null when
// the FileInputStream was opened with asynchronous_mode set to true.
// the FileStream was opened with PLATFORM_FILE_ASYNC.
scoped_ptr<AsyncContext> async_context_;
#if defined(OS_WIN)
HANDLE handle_;
#elif defined(OS_POSIX)
int fd_;
#endif
base::PlatformFile file_;
int open_flags_;
DISALLOW_COPY_AND_ASSIGN(FileInputStream);
DISALLOW_COPY_AND_ASSIGN(FileStream);
};
} // namespace net
#endif // NET_BASE_FILE_INPUT_STREAM_H_
#endif // NET_BASE_FILE_STREAM_H_

@ -5,7 +5,7 @@
// For 64-bit file access (off_t = off64_t, lseek64, etc).
#define _FILE_OFFSET_BITS 64
#include "net/base/file_input_stream.h"
#include "net/base/file_stream.h"
#include <sys/types.h>
#include <sys/stat.h>
@ -29,10 +29,10 @@ COMPILE_ASSERT(net::FROM_BEGIN == SEEK_SET &&
namespace net {
// FileInputStream::AsyncContext ----------------------------------------------
// FileStream::AsyncContext ----------------------------------------------
// TODO(deanm): Figure out how to best do async IO.
class FileInputStream::AsyncContext {
class FileStream::AsyncContext {
public:
CompletionCallback* callback() const { return NULL; }
@ -41,22 +41,22 @@ class FileInputStream::AsyncContext {
DISALLOW_COPY_AND_ASSIGN(AsyncContext);
};
// FileInputStream ------------------------------------------------------------
// FileStream ------------------------------------------------------------
FileInputStream::FileInputStream() : fd_(-1) {
FileStream::FileStream() : file_(base::kInvalidPlatformFileValue) {
DCHECK(!IsOpen());
}
FileInputStream::~FileInputStream() {
FileStream::~FileStream() {
Close();
}
void FileInputStream::Close() {
if (fd_ != -1) {
if (close(fd_) != 0) {
void FileStream::Close() {
if (file_ != base::kInvalidPlatformFileValue) {
if (close(file_) != 0) {
NOTREACHED();
}
fd_ = -1;
file_ = base::kInvalidPlatformFileValue;
}
async_context_.reset();
}
@ -74,34 +74,42 @@ static int64 MapErrorCode(int err) {
}
}
int FileInputStream::Open(const std::wstring& path, bool asynchronous_mode) {
// 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)
int FileStream::Open(const std::wstring& path, int open_flags) {
if (IsOpen()) {
DLOG(FATAL) << "File is already open!";
return ERR_UNEXPECTED;
}
open_flags_ = open_flags;
file_ = base::CreatePlatformFile(path, open_flags_, NULL);
if (file_ == base::kInvalidPlatformFileValue) {
LOG(WARNING) << "Failed to open file: " << errno;
return MapErrorCode(errno);
}
return OK;
}
bool FileInputStream::IsOpen() const {
return fd_ != -1;
bool FileStream::IsOpen() const {
return file_ != base::kInvalidPlatformFileValue;
}
int64 FileInputStream::Seek(Whence whence, int64 offset) {
int64 FileStream::Seek(Whence whence, int64 offset) {
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));
off_t res = lseek(file_, static_cast<off_t>(offset),
static_cast<int>(whence));
if (res == static_cast<off_t>(-1))
return MapErrorCode(errno);
return res;
}
int64 FileInputStream::Available() {
int64 FileStream::Available() {
if (!IsOpen())
return ERR_UNEXPECTED;
@ -110,7 +118,7 @@ int64 FileInputStream::Available() {
return cur_pos;
struct stat info;
if (fstat(fd_, &info) != 0)
if (fstat(file_, &info) != 0)
return MapErrorCode(errno);
int64 size = static_cast<int64>(info.st_size);
@ -120,7 +128,7 @@ int64 FileInputStream::Available() {
}
// TODO(deanm): async.
int FileInputStream::Read(
int FileStream::Read(
char* buf, int buf_len, CompletionCallback* callback) {
// read(..., 0) will return 0, which indicates end-of-file.
DCHECK(buf_len > 0 && buf_len <= SSIZE_MAX);
@ -130,7 +138,7 @@ int FileInputStream::Read(
// Loop in the case of getting interrupted by a signal.
for (;;) {
ssize_t res = read(fd_, buf, static_cast<size_t>(buf_len));
ssize_t res = read(file_, buf, static_cast<size_t>(buf_len));
if (res == static_cast<ssize_t>(-1)) {
if (errno == EINTR)
continue;
@ -140,4 +148,30 @@ int FileInputStream::Read(
}
}
// TODO(deanm): async.
int FileStream::Write(
const char* buf, int buf_len, CompletionCallback* callback) {
// read(..., 0) will return 0, which indicates end-of-file.
DCHECK(buf_len > 0 && buf_len <= SSIZE_MAX);
if (!IsOpen())
return ERR_UNEXPECTED;
int total_bytes_written = 0;
size_t len = static_cast<size_t>(buf_len);
while (total_bytes_written < buf_len) {
ssize_t res = write(file_, buf, len);
if (res == static_cast<ssize_t>(-1)) {
if (errno == EINTR)
continue;
return MapErrorCode(errno);
}
total_bytes_written += res;
buf += res;
len -= res;
}
return total_bytes_written;
}
} // namespace net

@ -0,0 +1,369 @@
// Copyright (c) 2008 The Chromium Authors. All rights reserved. Use of this
// source code is governed by a BSD-style license that can be found in the
// LICENSE file.
#include "base/file_util.h"
#include "base/path_service.h"
#include "base/platform_test.h"
#include "net/base/file_stream.h"
#include "net/base/net_errors.h"
#include "net/base/test_completion_callback.h"
#include "testing/gtest/include/gtest/gtest.h"
static const char kTestData[] = "0123456789";
static const int kTestDataSize = arraysize(kTestData) - 1;
class FileStreamTest : public PlatformTest {
public:
virtual void SetUp() {
PlatformTest::SetUp();
file_util::CreateTemporaryFileName(&temp_file_path_);
file_util::WriteFile(temp_file_path_, kTestData, kTestDataSize);
}
virtual void TearDown() {
file_util::Delete(temp_file_path_, false);
PlatformTest::TearDown();
}
const std::wstring temp_file_path() const { return temp_file_path_; }
private:
std::wstring temp_file_path_;
};
TEST_F(FileStreamTest, BasicOpenClose) {
net::FileStream stream;
int rv = stream.Open(temp_file_path(),
base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ);
EXPECT_EQ(net::OK, rv);
}
TEST_F(FileStreamTest, UseClosedStream) {
net::FileStream stream;
EXPECT_FALSE(stream.IsOpen());
// Try seeking...
int64 new_offset = stream.Seek(net::FROM_BEGIN, 5);
EXPECT_EQ(net::ERR_UNEXPECTED, new_offset);
// Try available...
int64 avail = stream.Available();
EXPECT_EQ(net::ERR_UNEXPECTED, avail);
// Try reading...
char buf[10];
int rv = stream.Read(buf, sizeof(buf), NULL);
EXPECT_EQ(net::ERR_UNEXPECTED, rv);
}
TEST_F(FileStreamTest, BasicRead) {
int64 file_size;
bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
EXPECT_TRUE(ok);
net::FileStream stream;
int flags = base::PLATFORM_FILE_OPEN |
base::PLATFORM_FILE_READ;
int rv = stream.Open(temp_file_path(), flags);
EXPECT_EQ(net::OK, rv);
int64 total_bytes_avail = stream.Available();
EXPECT_EQ(file_size, total_bytes_avail);
int64 total_bytes_read = 0;
std::string data_read;
for (;;) {
char buf[4];
rv = stream.Read(buf, sizeof(buf), NULL);
EXPECT_LE(0, rv);
if (rv <= 0)
break;
total_bytes_read += rv;
data_read.append(buf, rv);
}
EXPECT_EQ(file_size, total_bytes_read);
EXPECT_TRUE(data_read == kTestData);
}
TEST_F(FileStreamTest, AsyncRead) {
int64 file_size;
bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
EXPECT_TRUE(ok);
net::FileStream stream;
int flags = base::PLATFORM_FILE_OPEN |
base::PLATFORM_FILE_READ |
base::PLATFORM_FILE_ASYNC;
int rv = stream.Open(temp_file_path(), flags);
EXPECT_EQ(net::OK, rv);
int64 total_bytes_avail = stream.Available();
EXPECT_EQ(file_size, total_bytes_avail);
TestCompletionCallback callback;
int64 total_bytes_read = 0;
std::string data_read;
for (;;) {
char buf[4];
rv = stream.Read(buf, sizeof(buf), &callback);
if (rv == net::ERR_IO_PENDING)
rv = callback.WaitForResult();
EXPECT_LE(0, rv);
if (rv <= 0)
break;
total_bytes_read += rv;
data_read.append(buf, rv);
}
EXPECT_EQ(file_size, total_bytes_read);
EXPECT_TRUE(data_read == kTestData);
}
TEST_F(FileStreamTest, BasicRead_FromOffset) {
int64 file_size;
bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
EXPECT_TRUE(ok);
net::FileStream stream;
int flags = base::PLATFORM_FILE_OPEN |
base::PLATFORM_FILE_READ;
int rv = stream.Open(temp_file_path(), flags);
EXPECT_EQ(net::OK, rv);
const int64 kOffset = 3;
int64 new_offset = stream.Seek(net::FROM_BEGIN, kOffset);
EXPECT_EQ(kOffset, new_offset);
int64 total_bytes_avail = stream.Available();
EXPECT_EQ(file_size - kOffset, total_bytes_avail);
int64 total_bytes_read = 0;
std::string data_read;
for (;;) {
char buf[4];
rv = stream.Read(buf, sizeof(buf), NULL);
EXPECT_LE(0, rv);
if (rv <= 0)
break;
total_bytes_read += rv;
data_read.append(buf, rv);
}
EXPECT_EQ(file_size - kOffset, total_bytes_read);
EXPECT_TRUE(data_read == kTestData + kOffset);
}
TEST_F(FileStreamTest, AsyncRead_FromOffset) {
int64 file_size;
bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
EXPECT_TRUE(ok);
net::FileStream stream;
int flags = base::PLATFORM_FILE_OPEN |
base::PLATFORM_FILE_READ |
base::PLATFORM_FILE_ASYNC;
int rv = stream.Open(temp_file_path(), flags);
EXPECT_EQ(net::OK, rv);
const int64 kOffset = 3;
int64 new_offset = stream.Seek(net::FROM_BEGIN, kOffset);
EXPECT_EQ(kOffset, new_offset);
int64 total_bytes_avail = stream.Available();
EXPECT_EQ(file_size - kOffset, total_bytes_avail);
TestCompletionCallback callback;
int64 total_bytes_read = 0;
std::string data_read;
for (;;) {
char buf[4];
rv = stream.Read(buf, sizeof(buf), &callback);
if (rv == net::ERR_IO_PENDING)
rv = callback.WaitForResult();
EXPECT_LE(0, rv);
if (rv <= 0)
break;
total_bytes_read += rv;
data_read.append(buf, rv);
}
EXPECT_EQ(file_size - kOffset, total_bytes_read);
EXPECT_TRUE(data_read == kTestData + kOffset);
}
TEST_F(FileStreamTest, SeekAround) {
net::FileStream stream;
int flags = base::PLATFORM_FILE_OPEN |
base::PLATFORM_FILE_READ;
int rv = stream.Open(temp_file_path(), flags);
EXPECT_EQ(net::OK, rv);
const int64 kOffset = 3;
int64 new_offset = stream.Seek(net::FROM_BEGIN, kOffset);
EXPECT_EQ(kOffset, new_offset);
new_offset = stream.Seek(net::FROM_CURRENT, kOffset);
EXPECT_EQ(2 * kOffset, new_offset);
new_offset = stream.Seek(net::FROM_CURRENT, -kOffset);
EXPECT_EQ(kOffset, new_offset);
const int kTestDataLen = arraysize(kTestData) - 1;
new_offset = stream.Seek(net::FROM_END, -kTestDataLen);
EXPECT_EQ(0, new_offset);
}
TEST_F(FileStreamTest, BasicWrite) {
net::FileStream stream;
int flags = base::PLATFORM_FILE_CREATE_ALWAYS |
base::PLATFORM_FILE_WRITE;
int rv = stream.Open(temp_file_path(), flags);
EXPECT_EQ(net::OK, rv);
int64 file_size;
bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
EXPECT_TRUE(ok);
EXPECT_EQ(0, file_size);
rv = stream.Write(kTestData, kTestDataSize, NULL);
EXPECT_EQ(kTestDataSize, rv);
stream.Close();
ok = file_util::GetFileSize(temp_file_path(), &file_size);
EXPECT_TRUE(ok);
EXPECT_EQ(kTestDataSize, file_size);
}
TEST_F(FileStreamTest, AsyncWrite) {
net::FileStream stream;
int flags = base::PLATFORM_FILE_CREATE_ALWAYS |
base::PLATFORM_FILE_WRITE |
base::PLATFORM_FILE_ASYNC;
int rv = stream.Open(temp_file_path(), flags);
EXPECT_EQ(net::OK, rv);
int64 file_size;
bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
EXPECT_TRUE(ok);
EXPECT_EQ(0, file_size);
TestCompletionCallback callback;
int64 total_bytes_written = 0;
while (total_bytes_written != kTestDataSize) {
rv = stream.Write(kTestData, kTestDataSize, &callback);
if (rv == net::ERR_IO_PENDING)
rv = callback.WaitForResult();
EXPECT_LT(0, rv);
if (rv <= 0)
break;
total_bytes_written += rv;
}
ok = file_util::GetFileSize(temp_file_path(), &file_size);
EXPECT_TRUE(ok);
EXPECT_EQ(file_size, total_bytes_written);
}
TEST_F(FileStreamTest, BasicWrite_FromOffset) {
net::FileStream stream;
int flags = base::PLATFORM_FILE_OPEN |
base::PLATFORM_FILE_WRITE;
int rv = stream.Open(temp_file_path(), flags);
EXPECT_EQ(net::OK, rv);
int64 file_size;
bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
EXPECT_TRUE(ok);
EXPECT_EQ(kTestDataSize, file_size);
const int64 kOffset = 0;
int64 new_offset = stream.Seek(net::FROM_END, kOffset);
EXPECT_EQ(kTestDataSize, new_offset);
rv = stream.Write(kTestData, kTestDataSize, NULL);
EXPECT_EQ(kTestDataSize, rv);
stream.Close();
ok = file_util::GetFileSize(temp_file_path(), &file_size);
EXPECT_TRUE(ok);
EXPECT_EQ(kTestDataSize * 2, file_size);
}
TEST_F(FileStreamTest, AsyncWrite_FromOffset) {
int64 file_size;
bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
EXPECT_TRUE(ok);
net::FileStream stream;
int flags = base::PLATFORM_FILE_OPEN |
base::PLATFORM_FILE_WRITE |
base::PLATFORM_FILE_ASYNC;
int rv = stream.Open(temp_file_path(), flags);
EXPECT_EQ(net::OK, rv);
const int64 kOffset = 0;
int64 new_offset = stream.Seek(net::FROM_END, kOffset);
EXPECT_EQ(kTestDataSize, new_offset);
TestCompletionCallback callback;
int64 total_bytes_written = 0;
while (total_bytes_written != kTestDataSize) {
rv = stream.Write(kTestData, kTestDataSize, &callback);
if (rv == net::ERR_IO_PENDING)
rv = callback.WaitForResult();
EXPECT_LT(0, rv);
if (rv <= 0)
break;
total_bytes_written += rv;
}
ok = file_util::GetFileSize(temp_file_path(), &file_size);
EXPECT_TRUE(ok);
EXPECT_EQ(file_size, kTestDataSize * 2);
}
TEST_F(FileStreamTest, BasicReadWrite) {
int64 file_size;
bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
EXPECT_TRUE(ok);
net::FileStream stream;
int flags = base::PLATFORM_FILE_OPEN |
base::PLATFORM_FILE_READ |
base::PLATFORM_FILE_WRITE;
int rv = stream.Open(temp_file_path(), flags);
EXPECT_EQ(net::OK, rv);
int64 total_bytes_avail = stream.Available();
EXPECT_EQ(file_size, total_bytes_avail);
int64 total_bytes_read = 0;
std::string data_read;
for (;;) {
char buf[4];
rv = stream.Read(buf, sizeof(buf), NULL);
EXPECT_LE(0, rv);
if (rv <= 0)
break;
total_bytes_read += rv;
data_read.append(buf, rv);
}
EXPECT_EQ(file_size, total_bytes_read);
EXPECT_TRUE(data_read == kTestData);
rv = stream.Write(kTestData, kTestDataSize, NULL);
EXPECT_EQ(kTestDataSize, rv);
stream.Close();
ok = file_util::GetFileSize(temp_file_path(), &file_size);
EXPECT_TRUE(ok);
EXPECT_EQ(kTestDataSize * 2, file_size);
}
// TODO(erikkay): more READ_WRITE tests?

@ -2,7 +2,7 @@
// source code is governed by a BSD-style license that can be found in the
// LICENSE file.
#include "net/base/file_input_stream.h"
#include "net/base/file_stream.h"
#include <windows.h>
@ -45,11 +45,11 @@ static int MapErrorCode(DWORD err) {
}
}
// FileInputStream::AsyncContext ----------------------------------------------
// FileStream::AsyncContext ----------------------------------------------
class FileInputStream::AsyncContext : public MessageLoopForIO::IOHandler {
class FileStream::AsyncContext : public MessageLoopForIO::IOHandler {
public:
AsyncContext(FileInputStream* owner)
AsyncContext(FileStream* owner)
: owner_(owner), overlapped_(), callback_(NULL) {
overlapped_.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
}
@ -67,15 +67,15 @@ class FileInputStream::AsyncContext : public MessageLoopForIO::IOHandler {
private:
// MessageLoopForIO::IOHandler implementation:
virtual void OnIOCompleted(OVERLAPPED* context, DWORD bytes_read,
virtual void OnIOCompleted(OVERLAPPED* context, DWORD num_bytes,
DWORD error);
FileInputStream* owner_;
FileStream* owner_;
OVERLAPPED overlapped_;
CompletionCallback* callback_;
};
void FileInputStream::AsyncContext::IOCompletionIsPending(
void FileStream::AsyncContext::IOCompletionIsPending(
CompletionCallback* callback) {
DCHECK(!callback_);
callback_ = callback;
@ -83,82 +83,73 @@ void FileInputStream::AsyncContext::IOCompletionIsPending(
MessageLoopForIO::current()->RegisterIOContext(&overlapped_, this);
}
void FileInputStream::AsyncContext::OnIOCompleted(OVERLAPPED* context,
DWORD bytes_read,
void FileStream::AsyncContext::OnIOCompleted(OVERLAPPED* context,
DWORD num_bytes,
DWORD error) {
DCHECK(&overlapped_ == context);
DCHECK(callback_);
MessageLoopForIO::current()->RegisterIOContext(&overlapped_, NULL);
HANDLE handle = owner_->handle_;
HANDLE handle = owner_->file_;
int result = static_cast<int>(bytes_read);
int result = static_cast<int>(num_bytes);
if (error && error != ERROR_HANDLE_EOF)
result = MapErrorCode(error);
if (bytes_read)
IncrementOffset(&overlapped_, bytes_read);
if (num_bytes)
IncrementOffset(&overlapped_, num_bytes);
CompletionCallback* temp = NULL;
std::swap(temp, callback_);
temp->Run(result);
}
// FileInputStream ------------------------------------------------------------
// FileStream ------------------------------------------------------------
FileInputStream::FileInputStream() : handle_(INVALID_HANDLE_VALUE) {
FileStream::FileStream() : file_(INVALID_HANDLE_VALUE) {
}
FileInputStream::~FileInputStream() {
FileStream::~FileStream() {
Close();
}
void FileInputStream::Close() {
if (handle_ != INVALID_HANDLE_VALUE) {
CloseHandle(handle_);
handle_ = INVALID_HANDLE_VALUE;
void FileStream::Close() {
if (file_ != INVALID_HANDLE_VALUE) {
CloseHandle(file_);
file_ = INVALID_HANDLE_VALUE;
}
async_context_.reset();
}
int FileInputStream::Open(const std::wstring& path, bool asynchronous_mode) {
int FileStream::Open(const std::wstring& path, int open_flags) {
if (IsOpen()) {
DLOG(FATAL) << "File is already open!";
return ERR_UNEXPECTED;
}
// Optimize for streaming, not seeking. If someone does a lot of random
// access operations, then we should consider revising this.
DWORD create_file_flags = FILE_FLAG_SEQUENTIAL_SCAN;
if (asynchronous_mode)
create_file_flags |= FILE_FLAG_OVERLAPPED;
handle_ =
CreateFile(path.c_str(), GENERIC_READ | SYNCHRONIZE,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL, OPEN_EXISTING, create_file_flags, NULL);
if (handle_ == INVALID_HANDLE_VALUE) {
open_flags_ = open_flags;
file_ = base::CreatePlatformFile(path, open_flags_, NULL);
if (file_ == INVALID_HANDLE_VALUE) {
DWORD error = GetLastError();
LOG(WARNING) << "Failed to open file: " << error;
return MapErrorCode(error);
}
if (asynchronous_mode) {
if (open_flags_ & base::PLATFORM_FILE_ASYNC) {
async_context_.reset(new AsyncContext(this));
MessageLoopForIO::current()->RegisterIOHandler(handle_,
MessageLoopForIO::current()->RegisterIOHandler(file_,
async_context_.get());
}
return OK;
}
bool FileInputStream::IsOpen() const {
return handle_ != INVALID_HANDLE_VALUE;
bool FileStream::IsOpen() const {
return file_ != INVALID_HANDLE_VALUE;
}
int64 FileInputStream::Seek(Whence whence, int64 offset) {
int64 FileStream::Seek(Whence whence, int64 offset) {
if (!IsOpen())
return ERR_UNEXPECTED;
DCHECK(!async_context_.get() || !async_context_->callback());
@ -166,7 +157,7 @@ int64 FileInputStream::Seek(Whence whence, int64 offset) {
LARGE_INTEGER distance, result;
distance.QuadPart = offset;
DWORD move_method = static_cast<DWORD>(whence);
if (!SetFilePointerEx(handle_, distance, &result, move_method)) {
if (!SetFilePointerEx(file_, distance, &result, move_method)) {
DWORD error = GetLastError();
LOG(WARNING) << "SetFilePointerEx failed: " << error;
return MapErrorCode(error);
@ -176,7 +167,7 @@ int64 FileInputStream::Seek(Whence whence, int64 offset) {
return result.QuadPart;
}
int64 FileInputStream::Available() {
int64 FileStream::Available() {
if (!IsOpen())
return ERR_UNEXPECTED;
@ -185,7 +176,7 @@ int64 FileInputStream::Available() {
return cur_pos;
LARGE_INTEGER file_size;
if (!GetFileSizeEx(handle_, &file_size)) {
if (!GetFileSizeEx(file_, &file_size)) {
DWORD error = GetLastError();
LOG(WARNING) << "GetFileSizeEx failed: " << error;
return MapErrorCode(error);
@ -194,10 +185,11 @@ int64 FileInputStream::Available() {
return file_size.QuadPart - cur_pos;
}
int FileInputStream::Read(
int FileStream::Read(
char* buf, int buf_len, CompletionCallback* callback) {
if (!IsOpen())
return ERR_UNEXPECTED;
DCHECK(open_flags_ & base::PLATFORM_FILE_READ);
OVERLAPPED* overlapped = NULL;
if (async_context_.get()) {
@ -208,7 +200,7 @@ int FileInputStream::Read(
int rv;
DWORD bytes_read;
if (!ReadFile(handle_, buf, buf_len, &bytes_read, overlapped)) {
if (!ReadFile(file_, buf, buf_len, &bytes_read, overlapped)) {
DWORD error = GetLastError();
if (async_context_.get() && error == ERROR_IO_PENDING) {
async_context_->IOCompletionIsPending(callback);
@ -227,4 +219,36 @@ int FileInputStream::Read(
return rv;
}
int FileStream::Write(
const char* buf, int buf_len, CompletionCallback* callback) {
if (!IsOpen())
return ERR_UNEXPECTED;
DCHECK(open_flags_ & base::PLATFORM_FILE_READ);
OVERLAPPED* overlapped = NULL;
if (async_context_.get()) {
DCHECK(!async_context_->callback());
overlapped = async_context_->overlapped();
}
int rv;
DWORD bytes_written;
if (!WriteFile(file_, buf, buf_len, &bytes_written, overlapped)) {
DWORD error = GetLastError();
if (async_context_.get() && error == ERROR_IO_PENDING) {
async_context_->IOCompletionIsPending(callback);
rv = ERR_IO_PENDING;
} else {
LOG(WARNING) << "WriteFile failed: " << error;
rv = MapErrorCode(error);
}
} else {
if (overlapped)
IncrementOffset(overlapped, bytes_written);
rv = static_cast<int>(bytes_written);
}
return rv;
}
} // namespace net

@ -68,7 +68,9 @@ void UploadDataStream::FillBuf() {
DCHECK(element.type() == UploadData::TYPE_FILE);
if (!next_element_stream_.IsOpen()) {
int rv = next_element_stream_.Open(element.file_path(), false);
int flags = base::PLATFORM_FILE_OPEN |
base::PLATFORM_FILE_READ;
int rv = next_element_stream_.Open(element.file_path(), flags);
// If the file does not exist, that's technically okay.. we'll just
// upload an empty file. This is for consistency with Mozilla.
DLOG_IF(WARNING, rv != OK) << "Failed to open \"" <<

@ -5,7 +5,7 @@
#ifndef NET_BASE_UPLOAD_DATA_STREAM_H_
#define NET_BASE_UPLOAD_DATA_STREAM_H_
#include "net/base/file_input_stream.h"
#include "net/base/file_stream.h"
#include "net/base/upload_data.h"
namespace net {
@ -53,7 +53,7 @@ class UploadDataStream {
// A stream to the currently open file, for next_element_ if the next element
// is a TYPE_FILE element.
FileInputStream next_element_stream_;
FileStream next_element_stream_;
// The number of bytes remaining to be read from the currently open file
// if the next element is of TYPE_FILE.

@ -269,11 +269,11 @@
>
</File>
<File
RelativePath="..\base\file_input_stream.h"
RelativePath="..\base\file_stream.h"
>
</File>
<File
RelativePath="..\base\file_input_stream_win.cc"
RelativePath="..\base\file_stream_win.cc"
>
</File>
<File
@ -952,14 +952,6 @@
RelativePath="..\disk_cache\mem_rankings.h"
>
</File>
<File
RelativePath="..\disk_cache\os_file.h"
>
</File>
<File
RelativePath="..\disk_cache\os_file_win.cc"
>
</File>
<File
RelativePath="..\disk_cache\rankings.cc"
>

@ -323,7 +323,7 @@
>
</File>
<File
RelativePath="..\base\file_input_stream_unittest.cc"
RelativePath="..\base\file_stream_unittest.cc"
>
</File>
<File

@ -550,9 +550,12 @@ bool BackendImpl::CreateExternalFile(Addr* address) {
continue;
}
std::wstring name = GetFileName(file_address);
scoped_refptr<disk_cache::File> file(
new disk_cache::File(CreateOSFile(name.c_str(), OS_FILE_READ |
OS_FILE_WRITE |OS_FILE_SHARE_READ | OS_FILE_CREATE, NULL)));
int flags = base::PLATFORM_FILE_READ |
base::PLATFORM_FILE_WRITE |
base::PLATFORM_FILE_CREATE |
base::PLATFORM_FILE_EXCLUSIVE_WRITE;
scoped_refptr<disk_cache::File> file(new disk_cache::File(
base::CreatePlatformFile(name.c_str(), flags, NULL)));
if (!file->IsValid())
continue;
@ -748,9 +751,12 @@ bool BackendImpl::InitBackingStore(bool* file_created) {
std::wstring index_name(path_);
file_util::AppendToPath(&index_name, kIndexName);
int flags = base::PLATFORM_FILE_READ |
base::PLATFORM_FILE_WRITE |
base::PLATFORM_FILE_OPEN_ALWAYS |
base::PLATFORM_FILE_EXCLUSIVE_WRITE;
scoped_refptr<disk_cache::File> file(new disk_cache::File(
CreateOSFile(index_name.c_str(), OS_FILE_READ | OS_FILE_WRITE |
OS_FILE_SHARE_READ | OS_FILE_OPEN_ALWAYS, file_created)));
base::CreatePlatformFile(index_name.c_str(), flags, file_created)));
if (!file->IsValid())
return false;

@ -196,10 +196,12 @@ std::wstring BlockFiles::Name(int index) {
bool BlockFiles::CreateBlockFile(int index, FileType file_type, bool force) {
std::wstring name = Name(index);
int flags = force ? OS_FILE_CREATE_ALWAYS : OS_FILE_CREATE;
flags |= OS_FILE_WRITE | OS_FILE_SHARE_READ;
int flags =
force ? base::PLATFORM_FILE_CREATE_ALWAYS : base::PLATFORM_FILE_CREATE;
flags |= base::PLATFORM_FILE_WRITE | base::PLATFORM_FILE_EXCLUSIVE_WRITE;
scoped_refptr<File> file(new File(CreateOSFile(name.c_str(), flags, NULL)));
scoped_refptr<File> file(new File(
base::CreatePlatformFile(name.c_str(), flags, NULL)));
if (!file->IsValid())
return false;

@ -50,10 +50,12 @@ std::wstring GetCachePath() {
bool CreateCacheTestFile(const wchar_t* name) {
using namespace disk_cache;
int flags = OS_FILE_CREATE_ALWAYS | OS_FILE_READ | OS_FILE_WRITE |
OS_FILE_SHARE_READ | OS_FILE_SHARE_WRITE;
int flags = base::PLATFORM_FILE_CREATE_ALWAYS |
base::PLATFORM_FILE_READ |
base::PLATFORM_FILE_WRITE;
scoped_refptr<File> file(new File(CreateOSFile(name, flags, NULL)));
scoped_refptr<File> file(new File(
base::CreatePlatformFile(name, flags, NULL)));
if (!file->IsValid())
return false;

@ -9,8 +9,8 @@
#include <string>
#include "base/platform_file.h"
#include "base/ref_counted.h"
#include "net/disk_cache/os_file.h"
namespace disk_cache {
@ -35,14 +35,14 @@ class File : public base::RefCounted<File> {
// Initializes the object to use the passed in file instead of opening it with
// the Init() call. No asynchronous operations can be performed with this
// object.
explicit File(OSFile file);
explicit File(base::PlatformFile file);
// Initializes the object to point to a given file. The file must aready exist
// on disk, and allow shared read and write.
bool Init(const std::wstring& name);
// Returns the handle or file descriptor.
OSFile os_file() const;
base::PlatformFile platform_file() const;
// Returns true if the file was opened properly.
bool IsValid() const;
@ -78,8 +78,8 @@ class File : public base::RefCounted<File> {
private:
bool init_;
bool mixed_;
OSFile os_file_; // Regular, asynchronous IO handle.
OSFile sync_os_file_; // Synchronous IO hanlde.
base::PlatformFile platform_file_; // Regular, asynchronous IO handle.
base::PlatformFile sync_platform_file_; // Synchronous IO handle.
DISALLOW_COPY_AND_ASSIGN(File);
};

@ -11,18 +11,20 @@
namespace disk_cache {
File::File(OSFile file)
: init_(true), os_file_(file) {
File::File(base::PlatformFile file)
: init_(true), platform_file_(file) {
}
bool File::Init(const std::wstring& name) {
if (init_)
return false;
os_file_ = CreateOSFile(name, OS_FILE_OPEN | OS_FILE_READ | OS_FILE_WRITE,
NULL);
if (os_file_ < 0) {
os_file_ = 0;
int flags = base::PLATFORM_FILE_OPEN |
base::PLATFORM_FILE_READ |
base::PLATFORM_FILE_WRITE;
platform_file_ = base::CreatePlatformFile(name, flags, NULL);
if (platform_file_ < 0) {
platform_file_ = 0;
return false;
}
@ -31,18 +33,18 @@ bool File::Init(const std::wstring& name) {
}
File::~File() {
if (os_file_)
close(os_file_);
if (platform_file_)
close(platform_file_);
}
OSFile File::os_file() const {
return os_file_;
base::PlatformFile File::platform_file() const {
return platform_file_;
}
bool File::IsValid() const {
if (!init_)
return false;
return (INVALID_HANDLE_VALUE != os_file_);
return (base::kInvalidPlatformFileValue != platform_file_);
}
bool File::Read(void* buffer, size_t buffer_len, size_t offset) {
@ -50,7 +52,7 @@ bool File::Read(void* buffer, size_t buffer_len, size_t offset) {
if (buffer_len > ULONG_MAX || offset > LONG_MAX)
return false;
int ret = pread(os_file_, buffer, buffer_len, offset);
int ret = pread(platform_file_, buffer, buffer_len, offset);
return (static_cast<size_t>(ret) == buffer_len);
}
@ -59,7 +61,7 @@ bool File::Write(const void* buffer, size_t buffer_len, size_t offset) {
if (buffer_len > ULONG_MAX || offset > ULONG_MAX)
return false;
int ret = pwrite(os_file_, buffer, buffer_len, offset);
int ret = pwrite(platform_file_, buffer, buffer_len, offset);
return (static_cast<size_t>(ret) == buffer_len);
}
@ -114,12 +116,12 @@ bool File::SetLength(size_t length) {
if (length > ULONG_MAX)
return false;
return 0 == ftruncate(os_file_, length);
return 0 == ftruncate(platform_file_, length);
}
size_t File::GetLength() {
DCHECK(init_);
size_t ret = lseek(os_file_, 0, SEEK_END);
size_t ret = lseek(platform_file_, 0, SEEK_END);
return ret;
}

@ -88,9 +88,9 @@ void CALLBACK IoCompletion(DWORD error, DWORD actual_bytes,
}
}
File::File(OSFile file)
: init_(true), mixed_(true), os_file_(INVALID_HANDLE_VALUE),
sync_os_file_(file) {
File::File(base::PlatformFile file)
: init_(true), mixed_(true), platform_file_(INVALID_HANDLE_VALUE),
sync_platform_file_(file) {
}
bool File::Init(const std::wstring& name) {
@ -98,23 +98,23 @@ bool File::Init(const std::wstring& name) {
if (init_)
return false;
os_file_ = CreateFile(name.c_str(), GENERIC_READ | GENERIC_WRITE,
platform_file_ = CreateFile(name.c_str(), GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
FILE_FLAG_OVERLAPPED, NULL);
if (INVALID_HANDLE_VALUE == os_file_)
if (INVALID_HANDLE_VALUE == platform_file_)
return false;
init_ = true;
if (mixed_) {
sync_os_file_ = CreateFile(name.c_str(), GENERIC_READ | GENERIC_WRITE,
sync_platform_file_ = CreateFile(name.c_str(), GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, 0, NULL);
if (INVALID_HANDLE_VALUE == sync_os_file_)
if (INVALID_HANDLE_VALUE == sync_platform_file_)
return false;
} else {
sync_os_file_ = INVALID_HANDLE_VALUE;
sync_platform_file_ = INVALID_HANDLE_VALUE;
}
return true;
@ -124,22 +124,23 @@ File::~File() {
if (!init_)
return;
if (INVALID_HANDLE_VALUE != os_file_)
CloseHandle(os_file_);
if (mixed_ && INVALID_HANDLE_VALUE != sync_os_file_)
CloseHandle(sync_os_file_);
if (INVALID_HANDLE_VALUE != platform_file_)
CloseHandle(platform_file_);
if (mixed_ && INVALID_HANDLE_VALUE != sync_platform_file_)
CloseHandle(sync_platform_file_);
}
OSFile File::os_file() const {
base::PlatformFile File::platform_file() const {
DCHECK(init_);
return (INVALID_HANDLE_VALUE == os_file_) ? sync_os_file_ : os_file_;
return (INVALID_HANDLE_VALUE == platform_file_) ? sync_platform_file_ :
platform_file_;
}
bool File::IsValid() const {
if (!init_)
return false;
return (INVALID_HANDLE_VALUE != os_file_ ||
INVALID_HANDLE_VALUE != sync_os_file_);
return (INVALID_HANDLE_VALUE != platform_file_ ||
INVALID_HANDLE_VALUE != sync_platform_file_);
}
bool File::Read(void* buffer, size_t buffer_len, size_t offset) {
@ -147,14 +148,16 @@ bool File::Read(void* buffer, size_t buffer_len, size_t offset) {
if (!mixed_ || buffer_len > ULONG_MAX || offset > LONG_MAX)
return false;
DWORD ret = SetFilePointer(sync_os_file_, static_cast<LONG>(offset), NULL,
DWORD ret = SetFilePointer(sync_platform_file_,
static_cast<LONG>(offset),
NULL,
FILE_BEGIN);
if (INVALID_SET_FILE_POINTER == ret)
return false;
DWORD actual;
DWORD size = static_cast<DWORD>(buffer_len);
if (!ReadFile(sync_os_file_, buffer, size, &actual, NULL))
if (!ReadFile(sync_platform_file_, buffer, size, &actual, NULL))
return false;
return actual == size;
}
@ -164,14 +167,16 @@ bool File::Write(const void* buffer, size_t buffer_len, size_t offset) {
if (!mixed_ || buffer_len > ULONG_MAX || offset > ULONG_MAX)
return false;
DWORD ret = SetFilePointer(sync_os_file_, static_cast<LONG>(offset), NULL,
DWORD ret = SetFilePointer(sync_platform_file_,
static_cast<LONG>(offset),
NULL,
FILE_BEGIN);
if (INVALID_SET_FILE_POINTER == ret)
return false;
DWORD actual;
DWORD size = static_cast<DWORD>(buffer_len);
if (!WriteFile(sync_os_file_, buffer, size, &actual, NULL))
if (!WriteFile(sync_platform_file_, buffer, size, &actual, NULL))
return false;
return actual == size;
}
@ -196,7 +201,8 @@ bool File::Read(void* buffer, size_t buffer_len, size_t offset,
DWORD size = static_cast<DWORD>(buffer_len);
AddRef();
if (!ReadFileEx(os_file_, buffer, size, &data->overlapped, &IoCompletion)) {
if (!ReadFileEx(platform_file_, buffer, size, &data->overlapped,
&IoCompletion)) {
Release();
delete data;
return false;
@ -260,7 +266,8 @@ bool File::AsyncWrite(const void* buffer, size_t buffer_len, size_t offset,
DWORD size = static_cast<DWORD>(buffer_len);
AddRef();
if (!WriteFileEx(os_file_, buffer, size, &data->overlapped, &IoCompletion)) {
if (!WriteFileEx(platform_file_, buffer, size, &data->overlapped,
&IoCompletion)) {
Release();
delete data;
return false;
@ -295,7 +302,7 @@ bool File::SetLength(size_t length) {
return false;
DWORD size = static_cast<DWORD>(length);
HANDLE file = os_file();
HANDLE file = platform_file();
if (INVALID_SET_FILE_POINTER == SetFilePointer(file, size, NULL, FILE_BEGIN))
return false;
@ -305,7 +312,7 @@ bool File::SetLength(size_t length) {
size_t File::GetLength() {
DCHECK(init_);
LARGE_INTEGER size;
HANDLE file = os_file();
HANDLE file = platform_file();
if (!GetFileSizeEx(file, &size))
return 0;
if (size.HighPart)

@ -20,7 +20,7 @@ void* MappedFile::Init(const std::wstring name, size_t size) {
size = GetLength();
buffer_ = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED,
os_file(), 0);
platform_file(), 0);
init_ = true;
DCHECK(reinterpret_cast<int>(buffer_) != -1);
if (reinterpret_cast<int>(buffer_) == -1)

@ -15,7 +15,7 @@ void* MappedFile::Init(const std::wstring name, size_t size) {
buffer_ = NULL;
init_ = true;
section_ = CreateFileMapping(os_file(), NULL, PAGE_READWRITE, 0,
section_ = CreateFileMapping(platform_file(), NULL, PAGE_READWRITE, 0,
static_cast<DWORD>(size), NULL);
if (!section_)
return NULL;

@ -1,40 +0,0 @@
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef NET_DISK_CACHE_OS_FILE_H_
#define NET_DISK_CACHE_OS_FILE_H_
#include <string>
#include "build/build_config.h"
namespace disk_cache {
#if defined(OS_WIN)
#include <windows.h>
typedef HANDLE OSFile;
#elif defined(OS_POSIX)
typedef int OSFile;
const OSFile INVALID_HANDLE_VALUE = -1;
#endif
enum OSFileFlags {
OS_FILE_OPEN = 1,
OS_FILE_CREATE = 2,
OS_FILE_OPEN_ALWAYS = 4, // May create a new file.
OS_FILE_CREATE_ALWAYS = 8, // May overwrite an old file.
OS_FILE_READ = 16,
OS_FILE_WRITE = 32,
OS_FILE_SHARE_READ = 64,
OS_FILE_SHARE_WRITE = 128
};
// Creates or open the given file. If OS_FILE_OPEN_ALWAYS is used, and |created|
// is provided, |created| will be set to true if the file was created or to
// false in case the file was just opened.
OSFile CreateOSFile(const std::wstring& name, int flags, bool* created);
} // namespace disk_cache
#endif // NET_DISK_CACHE_OS_FILE_H_

@ -1,57 +0,0 @@
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "net/disk_cache/os_file.h"
#include "base/logging.h"
namespace disk_cache {
OSFile CreateOSFile(const std::wstring& name, int flags, bool* created) {
DWORD disposition = 0;
if (flags & OS_FILE_OPEN)
disposition = OPEN_EXISTING;
if (flags & OS_FILE_CREATE) {
DCHECK(!disposition);
disposition = CREATE_NEW;
}
if (flags & OS_FILE_OPEN_ALWAYS) {
DCHECK(!disposition);
disposition = OPEN_ALWAYS;
}
if (flags & OS_FILE_CREATE_ALWAYS) {
DCHECK(!disposition);
disposition = CREATE_ALWAYS;
}
if (!disposition) {
NOTREACHED();
return NULL;
}
DWORD access = (flags & OS_FILE_READ) ? GENERIC_READ : 0;
if (flags & OS_FILE_WRITE)
access |= GENERIC_WRITE;
DWORD sharing = (flags & OS_FILE_SHARE_READ) ? FILE_SHARE_READ : 0;
if (flags & OS_FILE_SHARE_WRITE)
access |= FILE_SHARE_WRITE;
HANDLE file = CreateFile(name.c_str(), access, sharing, NULL, disposition, 0,
NULL);
if ((flags & OS_FILE_OPEN_ALWAYS) && created &&
INVALID_HANDLE_VALUE != file) {
*created = (ERROR_ALREADY_EXISTS != GetLastError());
}
return file;
}
} // namespace disk_cache

@ -80,7 +80,6 @@
7B8504340E5B2E4900730B43 /* mem_entry_impl.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7BED32E50E5A190600A747DB /* mem_entry_impl.cc */; };
7B8504350E5B2E4900730B43 /* mem_rankings.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7BED32F00E5A190600A747DB /* mem_rankings.cc */; };
7B8504390E5B2E5700730B43 /* net_module.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7BED32A50E5A181C00A747DB /* net_module.cc */; };
7B85043B0E5B2E6400730B43 /* os_file_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7BED32DE0E5A190600A747DB /* os_file_posix.cc */; };
7B85043C0E5B2E6400730B43 /* platform_mime_util_mac.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7BED329D0E5A181C00A747DB /* platform_mime_util_mac.cc */; };
7B85043D0E5B2E6400730B43 /* rankings.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7BED32DC0E5A190600A747DB /* rankings.cc */; };
7B8504410E5B2E9600730B43 /* stats.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7BED32DA0E5A190600A747DB /* stats.cc */; };
@ -150,7 +149,8 @@
825C2FCC0E5C968B00FDEAB7 /* ev_root_ca_metadata.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7BED32BE0E5A181C00A747DB /* ev_root_ca_metadata.cc */; };
827E139D0E81611D00183614 /* x509_certificate_mac.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7BED32800E5A181C00A747DB /* x509_certificate_mac.cc */; };
82ECB3090E5B651D00A913E3 /* mime_sniffer.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7BED32AD0E5A181C00A747DB /* mime_sniffer.cc */; };
93D11DCE0E91463000C36437 /* file_input_stream_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = 93D11DCD0E91463000C36437 /* file_input_stream_posix.cc */; };
93D11DCE0E91463000C36437 /* file_stream_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = 93D11DCD0E91463000C36437 /* file_stream_posix.cc */; };
A5AB7BFC0EB7DBA10070A7D3 /* file_stream_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = A5AB7BFB0EB7DBA10070A7D3 /* file_stream_unittest.cc */; };
B5F622260E805FC40076681A /* url_request_job_manager.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7BED33A30E5A198600A747DB /* url_request_job_manager.cc */; };
BAA46E3B0E5CE99A00E77460 /* net_util_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7BED329F0E5A181C00A747DB /* net_util_unittest.cc */; };
DFEE18270E882E3600666107 /* stats_histogram.cc in Sources */ = {isa = PBXBuildFile; fileRef = DFEE18250E882E3600666107 /* stats_histogram.cc */; };
@ -546,8 +546,6 @@
7BED32DA0E5A190600A747DB /* stats.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = stats.cc; sourceTree = "<group>"; };
7BED32DB0E5A190600A747DB /* rankings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rankings.h; sourceTree = "<group>"; };
7BED32DC0E5A190600A747DB /* rankings.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = rankings.cc; sourceTree = "<group>"; };
7BED32DE0E5A190600A747DB /* os_file_posix.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = os_file_posix.cc; sourceTree = "<group>"; };
7BED32DF0E5A190600A747DB /* os_file.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = os_file.h; sourceTree = "<group>"; };
7BED32E00E5A190600A747DB /* block_files.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = block_files.h; sourceTree = "<group>"; };
7BED32E10E5A190600A747DB /* file_block.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = file_block.h; sourceTree = "<group>"; };
7BED32E20E5A190600A747DB /* file.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = file.h; sourceTree = "<group>"; };
@ -664,8 +662,9 @@
82113A270E84360200E3848F /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = "<group>"; };
82113BBC0E892E5800E3848F /* x509_certificate.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = x509_certificate.cc; sourceTree = "<group>"; };
8249C4920EA786B100A4A54B /* ssl_client_socket_mac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ssl_client_socket_mac.h; sourceTree = "<group>"; };
936882DC0E9154E200043405 /* file_input_stream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = file_input_stream.h; sourceTree = "<group>"; };
93D11DCD0E91463000C36437 /* file_input_stream_posix.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = file_input_stream_posix.cc; sourceTree = "<group>"; };
936882DC0E9154E200043405 /* file_stream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = file_stream.h; sourceTree = "<group>"; };
93D11DCD0E91463000C36437 /* file_stream_posix.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = file_stream_posix.cc; sourceTree = "<group>"; };
A5AB7BFB0EB7DBA10070A7D3 /* file_stream_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = file_stream_unittest.cc; sourceTree = "<group>"; };
DFEE18250E882E3600666107 /* stats_histogram.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = stats_histogram.cc; sourceTree = "<group>"; };
DFEE18260E882E3600666107 /* stats_histogram.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = stats_histogram.h; sourceTree = "<group>"; };
E47E933E0E8924DC00CA613E /* tcp_client_socket_libevent.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = tcp_client_socket_libevent.cc; sourceTree = "<group>"; };
@ -911,8 +910,9 @@
7BED32BF0E5A181C00A747DB /* escape_unittest.cc */,
7BED32BE0E5A181C00A747DB /* ev_root_ca_metadata.cc */,
7BED32BD0E5A181C00A747DB /* ev_root_ca_metadata.h */,
936882DC0E9154E200043405 /* file_input_stream.h */,
93D11DCD0E91463000C36437 /* file_input_stream_posix.cc */,
936882DC0E9154E200043405 /* file_stream.h */,
93D11DCD0E91463000C36437 /* file_stream_posix.cc */,
A5AB7BFB0EB7DBA10070A7D3 /* file_stream_unittest.cc */,
7BED32BC0E5A181C00A747DB /* filter.cc */,
7BED32BB0E5A181C00A747DB /* filter.h */,
7BED32BA0E5A181C00A747DB /* gzip_filter.cc */,
@ -1026,8 +1026,6 @@
7BED32F10E5A190600A747DB /* mem_entry_impl.h */,
7BED32F00E5A190600A747DB /* mem_rankings.cc */,
7BED32EF0E5A190600A747DB /* mem_rankings.h */,
7BED32DF0E5A190600A747DB /* os_file.h */,
7BED32DE0E5A190600A747DB /* os_file_posix.cc */,
7BED32DC0E5A190600A747DB /* rankings.cc */,
7BED32DB0E5A190600A747DB /* rankings.h */,
7BED32DA0E5A190600A747DB /* stats.cc */,
@ -1444,7 +1442,7 @@
7B8504100E5B2DF000730B43 /* entry_impl.cc in Sources */,
7B8504120E5B2DF000730B43 /* escape.cc in Sources */,
825C2FCC0E5C968B00FDEAB7 /* ev_root_ca_metadata.cc in Sources */,
93D11DCE0E91463000C36437 /* file_input_stream_posix.cc in Sources */,
93D11DCE0E91463000C36437 /* file_stream_posix.cc in Sources */,
7B8504140E5B2DF000730B43 /* file_lock.cc in Sources */,
7B8504150E5B2DF000730B43 /* file_posix.cc in Sources */,
7BA0154C0E5A1C0400044150 /* filter.cc in Sources */,
@ -1474,7 +1472,6 @@
7B8504390E5B2E5700730B43 /* net_module.cc in Sources */,
7B8B5AE30E5CDC00002F9A97 /* net_util.cc in Sources */,
533102E70E5E3EBF00FF8E32 /* net_util_posix.cc in Sources */,
7B85043B0E5B2E6400730B43 /* os_file_posix.cc in Sources */,
7B85043C0E5B2E6400730B43 /* platform_mime_util_mac.cc in Sources */,
E49DD33C0E8933C0003C7A87 /* proxy_resolver_fixed.cc in Sources */,
820701040EB6611F005CD9E7 /* proxy_resolver_mac.cc in Sources */,
@ -1550,6 +1547,7 @@
E47E93430E8924EE00CA613E /* tcp_client_socket_unittest.cc in Sources */,
7BA361450E8C341F0023C8B9 /* test_completion_callback_unittest.cc in Sources */,
82113A1D0E8434EE00E3848F /* x509_certificate_unittest.cc in Sources */,
A5AB7BFC0EB7DBA10070A7D3 /* file_stream_unittest.cc in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

@ -131,7 +131,7 @@ if env['PLATFORM'] in ('posix', 'darwin'):
if env['PLATFORM'] == 'win32':
input_files.extend([
'base/file_input_stream_win.cc',
'base/file_stream_win.cc',
'base/net_util_win.cc',
'base/platform_mime_util_win.cc',
'base/ssl_client_socket_win.cc',
@ -139,7 +139,6 @@ if env['PLATFORM'] == 'win32':
'disk_cache/cache_util_win.cc',
'disk_cache/file_win.cc',
'disk_cache/mapped_file_win.cc',
'disk_cache/os_file_win.cc',
'proxy/proxy_resolver_winhttp.cc',
])
@ -162,13 +161,12 @@ if env['PLATFORM'] == 'posix':
if env['PLATFORM'] in ('darwin', 'posix'):
input_files.extend([
'base/file_input_stream_posix.cc',
'base/file_stream_posix.cc',
'base/net_util_posix.cc',
'base/tcp_client_socket_libevent.cc',
'disk_cache/cache_util_posix.cc',
'disk_cache/file_posix.cc',
'disk_cache/mapped_file_posix.cc',
'disk_cache/os_file_posix.cc',
])
if env['PLATFORM'] == 'win32':

@ -70,7 +70,7 @@ input_files = [
'base/cookie_policy_unittest.cc',
'base/data_url_unittest.cc',
'base/escape_unittest.cc',
'base/file_input_stream_unittest.cc',
'base/file_stream_unittest.cc',
'base/gzip_filter_unittest.cc',
'base/host_resolver_unittest.cc',
'base/mime_sniffer_unittest.cc',

@ -177,7 +177,10 @@ void URLRequestFileJob::DidResolve(
if (!exists) {
rv = net::ERR_FILE_NOT_FOUND;
} else if (!is_directory_) {
rv = stream_.Open(file_path_, true);
int flags = base::PLATFORM_FILE_OPEN |
base::PLATFORM_FILE_READ |
base::PLATFORM_FILE_ASYNC;
rv = stream_.Open(file_path_, flags);
}
if (rv == net::OK) {

@ -7,7 +7,7 @@
#include "base/file_util.h"
#include "net/base/completion_callback.h"
#include "net/base/file_input_stream.h"
#include "net/base/file_stream.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_job.h"
@ -34,7 +34,7 @@ class URLRequestFileJob : public URLRequestJob {
void DidRead(int result);
net::CompletionCallbackImpl<URLRequestFileJob> io_callback_;
net::FileInputStream stream_;
net::FileStream stream_;
bool is_directory_;
#if defined(OS_WIN)