/*
 * Copyright (C) 2007-2016 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 "pmsg_writer.h"

#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <time.h>

#include <shared_mutex>

#include <log/log_properties.h>
#include <private/android_logger.h>

#include "logger.h"
#include "rwlock.h"
#include "uio.h"

static int pmsg_fd;
static RwLock pmsg_fd_lock;

static void PmsgOpen() {
  auto lock = std::unique_lock{pmsg_fd_lock};
  if (pmsg_fd > 0) {
    // Someone raced us and opened the socket already.
    return;
  }

  pmsg_fd = TEMP_FAILURE_RETRY(open("/dev/pmsg0", O_WRONLY | O_CLOEXEC));
}

void PmsgClose() {
  auto lock = std::unique_lock{pmsg_fd_lock};
  if (pmsg_fd > 0) {
    close(pmsg_fd);
  }
  pmsg_fd = 0;
}

int PmsgWrite(log_id_t logId, struct timespec* ts, struct iovec* vec, size_t nr) {
  static const unsigned headerLength = 2;
  struct iovec newVec[nr + headerLength];
  android_log_header_t header;
  android_pmsg_log_header_t pmsgHeader;
  size_t i, payloadSize;
  ssize_t ret;

  if (!__android_log_is_debuggable()) {
    if (logId != LOG_ID_EVENTS && logId != LOG_ID_SECURITY) {
      return -1;
    }

    if (logId == LOG_ID_EVENTS) {
      if (vec[0].iov_len < 4) {
        return -EINVAL;
      }

      if (SNET_EVENT_LOG_TAG != *static_cast<uint32_t*>(vec[0].iov_base)) {
        return -EPERM;
      }
    }
  }

  auto lock = std::shared_lock{pmsg_fd_lock};

  if (pmsg_fd <= 0) {
    lock.unlock();
    PmsgOpen();
    lock.lock();
  }

  if (pmsg_fd <= 0) {
    return -EBADF;
  }

  /*
   *  struct {
   *      // what we provide to pstore
   *      android_pmsg_log_header_t pmsgHeader;
   *      // what we provide to file
   *      android_log_header_t header;
   *      // caller provides
   *      union {
   *          struct {
   *              char     prio;
   *              char     payload[];
   *          } string;
   *          struct {
   *              uint32_t tag
   *              char     payload[];
   *          } binary;
   *      };
   *  };
   */

  pmsgHeader.magic = LOGGER_MAGIC;
  pmsgHeader.len = sizeof(pmsgHeader) + sizeof(header);
  pmsgHeader.uid = getuid();
  pmsgHeader.pid = getpid();

  header.id = logId;
  header.tid = gettid();
  header.realtime.tv_sec = ts->tv_sec;
  header.realtime.tv_nsec = ts->tv_nsec;

  newVec[0].iov_base = (unsigned char*)&pmsgHeader;
  newVec[0].iov_len = sizeof(pmsgHeader);
  newVec[1].iov_base = (unsigned char*)&header;
  newVec[1].iov_len = sizeof(header);

  for (payloadSize = 0, i = headerLength; i < nr + headerLength; i++) {
    newVec[i].iov_base = vec[i - headerLength].iov_base;
    payloadSize += newVec[i].iov_len = vec[i - headerLength].iov_len;

    if (payloadSize > LOGGER_ENTRY_MAX_PAYLOAD) {
      newVec[i].iov_len -= payloadSize - LOGGER_ENTRY_MAX_PAYLOAD;
      if (newVec[i].iov_len) {
        ++i;
      }
      payloadSize = LOGGER_ENTRY_MAX_PAYLOAD;
      break;
    }
  }
  pmsgHeader.len += payloadSize;

  ret = TEMP_FAILURE_RETRY(writev(pmsg_fd, newVec, i));
  if (ret < 0) {
    ret = errno ? -errno : -ENOTCONN;
  }

  if (ret > (ssize_t)(sizeof(header) + sizeof(pmsgHeader))) {
    ret -= sizeof(header) - sizeof(pmsgHeader);
  }

  return ret;
}

/*
 * Virtual pmsg filesystem
 *
 * Payload will comprise the string "<basedir>:<basefile>\0<content>" to a
 * maximum of LOGGER_ENTRY_MAX_PAYLOAD, but scaled to the last newline in the
 * file.
 *
 * Will hijack the header.realtime.tv_nsec field for a sequence number in usec.
 */

static inline const char* strnrchr(const char* buf, size_t len, char c) {
  const char* cp = buf + len;
  while ((--cp > buf) && (*cp != c))
    ;
  if (cp <= buf) {
    return buf + len;
  }
  return cp;
}

/* Write a buffer as filename references (tag = <basedir>:<basename>) */
ssize_t __android_log_pmsg_file_write(log_id_t logId, char prio, const char* filename,
                                      const char* buf, size_t len) {
  size_t length, packet_len;
  const char* tag;
  char *cp, *slash;
  struct timespec ts;
  struct iovec vec[3];

  /* Make sure the logId value is not a bad idea */
  if ((logId == LOG_ID_KERNEL) ||   /* Verbotten */
      (logId == LOG_ID_EVENTS) ||   /* Do not support binary content */
      (logId == LOG_ID_SECURITY) || /* Bad idea to allow */
      ((unsigned)logId >= 32)) {    /* fit within logMask on arch32 */
    return -EINVAL;
  }

  clock_gettime(android_log_clockid(), &ts);

  cp = strdup(filename);
  if (!cp) {
    return -ENOMEM;
  }

  tag = cp;
  slash = strrchr(cp, '/');
  if (slash) {
    *slash = ':';
    slash = strrchr(cp, '/');
    if (slash) {
      tag = slash + 1;
    }
  }

  length = strlen(tag) + 1;
  packet_len = LOGGER_ENTRY_MAX_PAYLOAD - sizeof(char) - length;

  vec[0].iov_base = &prio;
  vec[0].iov_len = sizeof(char);
  vec[1].iov_base = (unsigned char*)tag;
  vec[1].iov_len = length;

  for (ts.tv_nsec = 0, length = len; length; ts.tv_nsec += ANDROID_LOG_PMSG_FILE_SEQUENCE) {
    ssize_t ret;
    size_t transfer;

    if ((ts.tv_nsec / ANDROID_LOG_PMSG_FILE_SEQUENCE) >= ANDROID_LOG_PMSG_FILE_MAX_SEQUENCE) {
      len -= length;
      break;
    }

    transfer = length;
    if (transfer > packet_len) {
      transfer = strnrchr(buf, packet_len - 1, '\n') - buf;
      if ((transfer < length) && (buf[transfer] == '\n')) {
        ++transfer;
      }
    }

    vec[2].iov_base = (unsigned char*)buf;
    vec[2].iov_len = transfer;

    ret = PmsgWrite(logId, &ts, vec, sizeof(vec) / sizeof(vec[0]));

    if (ret <= 0) {
      free(cp);
      return ret ? ret : (len - length);
    }
    length -= transfer;
    buf += transfer;
  }
  free(cp);
  return len;
}
