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/files/file_path.h" 10 #include "base/files/file_util.h" 11 #include "base/files/scoped_file.h" 12 #include "base/message_loop/message_loop.h" 13 #include "base/task_runner_util.h" 14 15 namespace mojo { 16 namespace common { 17 namespace { 18 19 bool BlockingCopyHelper(ScopedDataPipeConsumerHandle source, 20 const base::Callback<size_t(const void*, uint32_t)>& write_bytes) { 21 for (;;) { 22 const void* buffer; 23 uint32_t num_bytes; 24 MojoResult result = BeginReadDataRaw( 25 source.get(), &buffer, &num_bytes, MOJO_READ_DATA_FLAG_NONE); 26 if (result == MOJO_RESULT_OK) { 27 size_t bytes_written = write_bytes.Run(buffer, num_bytes); 28 result = EndReadDataRaw(source.get(), num_bytes); 29 if (bytes_written < num_bytes || result != MOJO_RESULT_OK) 30 return false; 31 } else if (result == MOJO_RESULT_SHOULD_WAIT) { 32 result = Wait(source.get(), 33 MOJO_HANDLE_SIGNAL_READABLE, 34 MOJO_DEADLINE_INDEFINITE); 35 if (result != MOJO_RESULT_OK) { 36 // If the producer handle was closed, then treat as EOF. 37 return result == MOJO_RESULT_FAILED_PRECONDITION; 38 } 39 } else if (result == MOJO_RESULT_FAILED_PRECONDITION) { 40 // If the producer handle was closed, then treat as EOF. 41 return true; 42 } else { 43 // Some other error occurred. 44 break; 45 } 46 } 47 48 return false; 49 } 50 51 size_t CopyToStringHelper( 52 std::string* result, const void* buffer, uint32_t num_bytes) { 53 result->append(static_cast<const char*>(buffer), num_bytes); 54 return num_bytes; 55 } 56 57 size_t CopyToFileHelper(FILE* fp, const void* buffer, uint32_t num_bytes) { 58 return fwrite(buffer, 1, num_bytes, fp); 59 } 60 61 } // namespace 62 63 64 // TODO(hansmuller): Add a max_size parameter. 65 bool BlockingCopyToString(ScopedDataPipeConsumerHandle source, 66 std::string* result) { 67 CHECK(result); 68 result->clear(); 69 return BlockingCopyHelper( 70 source.Pass(), base::Bind(&CopyToStringHelper, result)); 71 } 72 73 bool BlockingCopyToFile(ScopedDataPipeConsumerHandle source, 74 const base::FilePath& destination) { 75 base::ScopedFILE fp(base::OpenFile(destination, "wb")); 76 if (!fp) 77 return false; 78 return BlockingCopyHelper( 79 source.Pass(), base::Bind(&CopyToFileHelper, fp.get())); 80 } 81 82 void CopyToFile(ScopedDataPipeConsumerHandle source, 83 const base::FilePath& destination, 84 base::TaskRunner* task_runner, 85 const base::Callback<void(bool)>& callback) { 86 base::PostTaskAndReplyWithResult( 87 task_runner, 88 FROM_HERE, 89 base::Bind(&BlockingCopyToFile, base::Passed(&source), destination), 90 callback); 91 } 92 93 } // namespace common 94 } // namespace mojo 95