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 16 namespace mojo { 17 namespace common { 18 19 bool 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 55 void CompleteBlockingCopyToFile(const base::Callback<void(bool)>& callback, 56 bool result) { 57 callback.Run(result); 58 } 59 60 void 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