Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / net / base / file_stream_context_posix.cc
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the 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_stream_context.h"
9
10 #include <errno.h>
11 #include <fcntl.h>
12 #include <sys/stat.h>
13 #include <sys/types.h>
14 #include <unistd.h>
15
16 #include "base/basictypes.h"
17 #include "base/bind.h"
18 #include "base/bind_helpers.h"
19 #include "base/callback.h"
20 #include "base/files/file_path.h"
21 #include "base/location.h"
22 #include "base/logging.h"
23 #include "base/metrics/histogram.h"
24 #include "base/posix/eintr_wrapper.h"
25 #include "base/task_runner.h"
26 #include "base/task_runner_util.h"
27 #include "net/base/io_buffer.h"
28 #include "net/base/net_errors.h"
29
30 #if defined(OS_ANDROID)
31 // Android's bionic libc only supports the LFS transitional API.
32 #define off_t off64_t
33 #define lseek lseek64
34 #define stat stat64
35 #define fstat fstat64
36 #endif
37
38 namespace net {
39
40 // We cast back and forth, so make sure it's the size we're expecting.
41 COMPILE_ASSERT(sizeof(int64) == sizeof(off_t), off_t_64_bit);
42
43 // Make sure our Whence mappings match the system headers.
44 COMPILE_ASSERT(FROM_BEGIN   == SEEK_SET &&
45                FROM_CURRENT == SEEK_CUR &&
46                FROM_END     == SEEK_END, whence_matches_system);
47
48 FileStream::Context::Context(const scoped_refptr<base::TaskRunner>& task_runner)
49     : async_in_progress_(false),
50       orphaned_(false),
51       task_runner_(task_runner) {
52 }
53
54 FileStream::Context::Context(base::File file,
55                              const scoped_refptr<base::TaskRunner>& task_runner)
56     : file_(file.Pass()),
57       async_in_progress_(false),
58       orphaned_(false),
59       task_runner_(task_runner) {
60 }
61
62 FileStream::Context::~Context() {
63 }
64
65 int FileStream::Context::ReadAsync(IOBuffer* in_buf,
66                                    int buf_len,
67                                    const CompletionCallback& callback) {
68   DCHECK(!async_in_progress_);
69
70   scoped_refptr<IOBuffer> buf = in_buf;
71   const bool posted = base::PostTaskAndReplyWithResult(
72       task_runner_.get(),
73       FROM_HERE,
74       base::Bind(&Context::ReadFileImpl, base::Unretained(this), buf, buf_len),
75       base::Bind(&Context::OnAsyncCompleted,
76                  base::Unretained(this),
77                  IntToInt64(callback)));
78   DCHECK(posted);
79
80   async_in_progress_ = true;
81   return ERR_IO_PENDING;
82 }
83
84 int FileStream::Context::WriteAsync(IOBuffer* in_buf,
85                                     int buf_len,
86                                     const CompletionCallback& callback) {
87   DCHECK(!async_in_progress_);
88
89   scoped_refptr<IOBuffer> buf = in_buf;
90   const bool posted = base::PostTaskAndReplyWithResult(
91       task_runner_.get(),
92       FROM_HERE,
93       base::Bind(&Context::WriteFileImpl, base::Unretained(this), buf, buf_len),
94       base::Bind(&Context::OnAsyncCompleted,
95                  base::Unretained(this),
96                  IntToInt64(callback)));
97   DCHECK(posted);
98
99   async_in_progress_ = true;
100   return ERR_IO_PENDING;
101 }
102
103 FileStream::Context::IOResult FileStream::Context::SeekFileImpl(Whence whence,
104                                                                 int64 offset) {
105   off_t res = lseek(file_.GetPlatformFile(), static_cast<off_t>(offset),
106                     static_cast<int>(whence));
107   if (res == static_cast<off_t>(-1))
108     return IOResult::FromOSError(errno);
109
110   return IOResult(res, 0);
111 }
112
113 FileStream::Context::IOResult FileStream::Context::FlushFileImpl() {
114   ssize_t res = HANDLE_EINTR(fsync(file_.GetPlatformFile()));
115   if (res == -1)
116     return IOResult::FromOSError(errno);
117
118   return IOResult(res, 0);
119 }
120
121 FileStream::Context::IOResult FileStream::Context::ReadFileImpl(
122     scoped_refptr<IOBuffer> buf,
123     int buf_len) {
124   // Loop in the case of getting interrupted by a signal.
125   ssize_t res = HANDLE_EINTR(read(file_.GetPlatformFile(), buf->data(),
126                                   static_cast<size_t>(buf_len)));
127   if (res == -1)
128     return IOResult::FromOSError(errno);
129
130   return IOResult(res, 0);
131 }
132
133 FileStream::Context::IOResult FileStream::Context::WriteFileImpl(
134     scoped_refptr<IOBuffer> buf,
135     int buf_len) {
136   ssize_t res = HANDLE_EINTR(write(file_.GetPlatformFile(), buf->data(),
137                                    buf_len));
138   if (res == -1)
139     return IOResult::FromOSError(errno);
140
141   return IOResult(res, 0);
142 }
143
144 }  // namespace net