blob: 0b0bd6d74e32536c57254c63ea43797c690dfbdb [file] [log] [blame]
Andreas Gamped0aac252018-03-22 08:20:08 -07001/*
2**
3** Copyright 2015, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18#include "perfprofd_io.h"
19
20#include <fcntl.h>
21#include <unistd.h>
22
Andreas Gamped0aac252018-03-22 08:20:08 -070023#include <android-base/file.h>
24#include <android-base/logging.h>
Andreas Gampec9a2ab42018-03-22 19:42:30 -070025#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
Andreas Gamped0aac252018-03-22 08:20:08 -070026
27#include "perfprofd_record.pb.h"
28
29namespace android {
30namespace perfprofd {
31
Andreas Gampec9a2ab42018-03-22 19:42:30 -070032using android::base::unique_fd;
33using android::base::WriteFully;
Andreas Gamped0aac252018-03-22 08:20:08 -070034
Andreas Gampec9a2ab42018-03-22 19:42:30 -070035namespace {
36
37// Protobuf's file implementation is not available in protobuf-lite. :-(
38class FileCopyingOutputStream : public ::google::protobuf::io::CopyingOutputStream {
39 public:
40 explicit FileCopyingOutputStream(android::base::unique_fd&& fd_in) : fd_(std::move(fd_in)) {
41 };
42 bool Write(const void * buffer, int size) override {
43 return WriteFully(fd_.get(), buffer, size);
44 }
45
46 private:
47 android::base::unique_fd fd_;
48};
49
50} // namespace
51
52bool SerializeProtobuf(android::perfprofd::PerfprofdRecord* encodedProfile,
53 android::base::unique_fd&& fd) {
54 FileCopyingOutputStream fcos(std::move(fd));
55 google::protobuf::io::CopyingOutputStreamAdaptor cosa(&fcos);
56
57 bool serialized = encodedProfile->SerializeToZeroCopyStream(&cosa);
58 if (!serialized) {
59 LOG(WARNING) << "SerializeToZeroCopyStream failed";
60 return false;
61 }
62
63 cosa.Flush();
64 return true;
65}
66
67bool SerializeProtobuf(PerfprofdRecord* encodedProfile, const char* encoded_file_path) {
Andreas Gamped0aac252018-03-22 08:20:08 -070068 unlink(encoded_file_path); // Attempt to unlink for a clean slate.
69 constexpr int kFlags = O_CREAT | O_WRONLY | O_TRUNC | O_NOFOLLOW | O_CLOEXEC;
Andreas Gampec9a2ab42018-03-22 19:42:30 -070070 unique_fd fd(open(encoded_file_path, kFlags, 0664));
Andreas Gamped0aac252018-03-22 08:20:08 -070071 if (fd.get() == -1) {
72 PLOG(WARNING) << "Could not open " << encoded_file_path << " for serialization";
73 return false;
74 }
Andreas Gampec9a2ab42018-03-22 19:42:30 -070075 return SerializeProtobuf(encodedProfile, std::move(fd));
Andreas Gamped0aac252018-03-22 08:20:08 -070076}
77
78} // namespace perfprofd
79} // namespace android