• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #include "host/commands/process_sandboxer/logs.h"
17 
18 #include <fcntl.h>
19 #include <unistd.h>
20 
21 #include <cerrno>
22 #include <cstring>
23 #include <iostream>
24 #include <memory>
25 #include <sstream>
26 #include <string>
27 #include <vector>
28 
29 #include <absl/log/log.h>
30 #include <absl/log/log_entry.h>
31 #include <absl/log/log_sink.h>
32 #include <absl/log/log_sink_registry.h>
33 #include <absl/status/status.h>
34 #include <absl/status/statusor.h>
35 
36 namespace cuttlefish::process_sandboxer {
37 namespace {
38 
39 // Implementation based on absl::log_internal::StderrLogSink
40 class FileLogSink final : absl::LogSink {
41  public:
FromPath(const std::string & path)42   static absl::StatusOr<std::unique_ptr<FileLogSink>> FromPath(
43       const std::string& path) {
44     std::unique_ptr<FileLogSink> sink(new FileLogSink());
45     sink->fd_ = open(path.c_str(), O_APPEND | O_CREAT | O_WRONLY, 0666);
46     if (sink->fd_ < 0) {
47       return absl::ErrnoToStatus(errno, "open failed");
48     }
49     absl::AddLogSink(sink.get());
50     return sink;
51   }
52   FileLogSink(FileLogSink&) = delete;
~FileLogSink()53   ~FileLogSink() {
54     absl::RemoveLogSink(this);
55     if (fd_ >= 0 && close(fd_) < 0) {
56       PLOG(ERROR) << "Failed to close fd '" << fd_ << "'";
57     }
58   }
59 
Send(const absl::LogEntry & entry)60   void Send(const absl::LogEntry& entry) override {
61     std::stringstream message_stream;
62     if (!entry.stacktrace().empty()) {
63       message_stream << entry.stacktrace();
64     }
65     message_stream << entry.text_message_with_prefix_and_newline();
66     auto message = message_stream.str();
67     auto written = write(fd_, message.c_str(), message.size());
68     if (written < 0) {
69       // LOG calls inside here would recurse infinitely because of AddLogSink
70       std::cerr << "FileLogSink: write(" << fd_
71                 << ") failed: " << strerror(errno) << '\n';
72     }
73   }
74 
75  private:
76   FileLogSink() = default;
77 
78   int fd_ = -1;
79 };
80 
81 }  // namespace
82 
LogToFiles(const std::vector<std::string> & paths)83 absl::Status LogToFiles(const std::vector<std::string>& paths) {
84   for (const auto& path : paths) {
85     auto sink_status = FileLogSink::FromPath(path);
86     if (!sink_status.ok()) {
87       return sink_status.status();
88     }
89     sink_status->release();  // Deliberate leak so LOG always writes here
90   }
91   return absl::OkStatus();
92 }
93 
94 }  // namespace cuttlefish::process_sandboxer
95