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