data_pipe_utils.cc revision 6e8cce623b6e4fe0c9e4af605d675dd9d0338c38
1// Copyright 2014 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#include "mojo/common/data_pipe_utils.h"
6
7#include <stdio.h>
8
9#include "base/file_util.h"
10#include "base/files/file_path.h"
11#include "base/files/scoped_file.h"
12#include "base/message_loop/message_loop.h"
13#include "base/task_runner_util.h"
14
15namespace mojo {
16namespace common {
17
18bool BlockingCopyToFile(ScopedDataPipeConsumerHandle source,
19                        const base::FilePath& destination) {
20  base::ScopedFILE fp(base::OpenFile(destination, "wb"));
21  if (!fp)
22    return false;
23
24  for (;;) {
25    const void* buffer;
26    uint32_t num_bytes;
27    MojoResult result = BeginReadDataRaw(source.get(), &buffer, &num_bytes,
28                                         MOJO_READ_DATA_FLAG_NONE);
29    if (result == MOJO_RESULT_OK) {
30      size_t bytes_written = fwrite(buffer, 1, num_bytes, fp.get());
31      result = EndReadDataRaw(source.get(), num_bytes);
32      if (bytes_written < num_bytes || result != MOJO_RESULT_OK)
33        return false;
34    } else if (result == MOJO_RESULT_SHOULD_WAIT) {
35      result = Wait(source.get(),
36                    MOJO_HANDLE_SIGNAL_READABLE,
37                    MOJO_DEADLINE_INDEFINITE);
38      if (result != MOJO_RESULT_OK) {
39        // If the producer handle was closed, then treat as EOF.
40        return result == MOJO_RESULT_FAILED_PRECONDITION;
41      }
42    } else if (result == MOJO_RESULT_FAILED_PRECONDITION) {
43      // If the producer handle was closed, then treat as EOF.
44      return true;
45    } else {
46      // Some other error occurred.
47      break;
48    }
49  }
50
51  return false;
52}
53
54void CompleteBlockingCopyToFile(const base::Callback<void(bool)>& callback,
55                                bool result) {
56  callback.Run(result);
57}
58
59void CopyToFile(ScopedDataPipeConsumerHandle source,
60                const base::FilePath& destination,
61                base::TaskRunner* task_runner,
62                const base::Callback<void(bool)>& callback) {
63  base::PostTaskAndReplyWithResult(
64      task_runner,
65      FROM_HERE,
66      base::Bind(&BlockingCopyToFile, base::Passed(&source), destination),
67      callback);
68}
69
70}  // namespace common
71}  // namespace mojo
72