/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "src/perfetto_cmd/perfetto_cmd.h"

#include <inttypes.h>
#include <sys/sendfile.h>

#include "perfetto/base/build_config.h"
#include "perfetto/base/logging.h"
#include "perfetto/tracing/core/trace_config.h"
#include "src/android_internal/dropbox_service.h"
#include "src/android_internal/incident_service.h"
#include "src/android_internal/lazy_library_loader.h"

namespace perfetto {

void PerfettoCmd::SaveTraceIntoDropboxAndIncidentOrCrash() {
  PERFETTO_CHECK(!dropbox_tag_.empty());

  // Otherwise, write to Dropbox unless there's a special override in the
  // incident report config.
  if (!trace_config_->incident_report_config().skip_dropbox()) {
    if (bytes_written_ == 0) {
      PERFETTO_LOG("Skipping write to dropbox. Empty trace.");
    } else {
      SaveOutputToDropboxOrCrash();
    }
  }

  // Optionally save the trace as an incident. This is either in addition to, or
  // instead of, the Dropbox write.
  if (!trace_config_->incident_report_config().destination_package().empty()) {
    if (bytes_written_ == 0) {
      PERFETTO_LOG("Skipping incident report. Empty trace.");
    } else {
      SaveOutputToIncidentTraceOrCrash();

      // Ask incidentd to create a report, which will read the file we just
      // wrote.
      const auto& cfg = trace_config_->incident_report_config();
      PERFETTO_LAZY_LOAD(android_internal::StartIncidentReport, incident_fn);
      PERFETTO_CHECK(incident_fn(cfg.destination_package().c_str(),
                                 cfg.destination_class().c_str(),
                                 cfg.privacy_level()));
    }
  }
}

void PerfettoCmd::SaveOutputToDropboxOrCrash() {
  PERFETTO_CHECK(fseek(*trace_out_stream_, 0, SEEK_SET) == 0);

  // DropBox takes ownership of the file descriptor, so give it a duplicate.
  // Also we need to give it a read-only copy of the fd or will hit a SELinux
  // violation (about system_server ending up with a writable FD to our dir).
  char fdpath[64];
  sprintf(fdpath, "/proc/self/fd/%d", fileno(*trace_out_stream_));
  base::ScopedFile read_only_fd(base::OpenFile(fdpath, O_RDONLY));
  PERFETTO_CHECK(read_only_fd);

  PERFETTO_LAZY_LOAD(android_internal::SaveIntoDropbox, dropbox_fn);
  if (dropbox_fn(dropbox_tag_.c_str(), read_only_fd.release())) {
    PERFETTO_LOG("Wrote %" PRIu64
                 " bytes (before compression) into DropBox with tag %s",
                 bytes_written_, dropbox_tag_.c_str());
  } else {
    PERFETTO_FATAL("DropBox upload failed");
  }
}

// Open a staging file (unlinking the previous instance), copy the trace
// contents over, then rename to a final hardcoded path (known to incidentd).
// Such tracing sessions should not normally overlap. We do not use unique
// unique filenames to avoid creating an unbounded amount of files in case of
// errors.
void PerfettoCmd::SaveOutputToIncidentTraceOrCrash() {
  char kIncidentTracePath[256];
  sprintf(kIncidentTracePath, "%s/incident-trace", kStateDir);

  char kTempIncidentTracePath[256];
  sprintf(kTempIncidentTracePath, "%s.temp", kIncidentTracePath);

  PERFETTO_CHECK(unlink(kTempIncidentTracePath) == 0 || errno == ENOENT);

  // SELinux constrains the set of readers.
  base::ScopedFile staging_fd =
      base::OpenFile(kTempIncidentTracePath, O_CREAT | O_RDWR, 0666);
  PERFETTO_CHECK(staging_fd);
  off_t offset = 0;
  auto wsize = sendfile(*staging_fd, fileno(*trace_out_stream_), &offset,
                        static_cast<size_t>(bytes_written_));
  PERFETTO_CHECK(wsize == static_cast<ssize_t>(bytes_written_));
  staging_fd.reset();
  PERFETTO_CHECK(rename(kTempIncidentTracePath, kIncidentTracePath) == 0);
  // Note: not calling fsync(2), as we're not interested in the file being
  // consistent in case of a crash.
}

// static
base::ScopedFile PerfettoCmd::OpenDropboxTmpFile() {
  // If we are tracing to DropBox, there's no need to make a
  // filesystem-visible temporary file.
  auto fd = base::OpenFile(kStateDir, O_TMPFILE | O_RDWR, 0600);
  if (!fd)
    PERFETTO_PLOG("Could not create a temporary trace file in %s", kStateDir);
  return fd;
}

}  // namespace perfetto
