blob: 1112044d12b3057640ec192bf0b67e22adaa376a [file] [log] [blame]
// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <mxio/io.h>
#include <stdatomic.h>
#include <stdlib.h>
#include <threads.h>
#include <magenta/syscalls.h>
#include <magenta/syscalls/log.h>
#include <magenta/processargs.h>
#include "private.h"
typedef struct mxio_log mxio_log_t;
struct mxio_log {
mxio_t io;
mx_handle_t handle;
};
#define LOGBUF_MAX (MX_LOG_RECORD_MAX - sizeof(mx_log_record_t))
static ssize_t log_write(mxio_t* io, const void* _data, size_t len) {
static thread_local struct {
unsigned next;
char data[LOGBUF_MAX];
}* logbuf = NULL;
mxio_log_t* log_io = (mxio_log_t*)io;
if (logbuf == NULL) {
if ((logbuf = calloc(1, sizeof(*logbuf))) == NULL) {
return len;
}
}
const char* data = _data;
size_t r = len;
while (len-- > 0) {
char c = *data++;
if (c == '\n') {
mx_log_write(log_io->handle, logbuf->next, logbuf->data, 0);
logbuf->next = 0;
continue;
}
if (c < ' ') {
continue;
}
logbuf->data[logbuf->next++] = c;
if (logbuf->next == LOGBUF_MAX) {
mx_log_write(log_io->handle, logbuf->next, logbuf->data, 0);
logbuf->next = 0;
continue;
}
}
return r;
}
static mx_status_t log_close(mxio_t* io) {
mxio_log_t* log_io = (mxio_log_t*)io;
mx_handle_t h = log_io->handle;
log_io->handle = 0;
mx_handle_close(h);
return MX_OK;
}
static mx_status_t log_clone(mxio_t* io, mx_handle_t* handles, uint32_t* types) {
mxio_log_t* log_io = (mxio_log_t*)io;
mx_status_t status = mx_handle_duplicate(log_io->handle, MX_RIGHT_SAME_RIGHTS, &handles[0]);
if (status < 0) {
return status;
}
types[0] = PA_MXIO_LOGGER;
return 1;
}
static mxio_ops_t log_io_ops = {
.read = mxio_default_read,
.read_at = mxio_default_read_at,
.write = log_write,
.write_at = mxio_default_write_at,
.recvfrom = mxio_default_recvfrom,
.sendto = mxio_default_sendto,
.recvmsg = mxio_default_recvmsg,
.sendmsg = mxio_default_sendmsg,
.seek = mxio_default_seek,
.misc = mxio_default_misc,
.close = log_close,
.open = mxio_default_open,
.clone = log_clone,
.ioctl = mxio_default_ioctl,
.wait_begin = mxio_default_wait_begin,
.wait_end = mxio_default_wait_end,
.unwrap = mxio_default_unwrap,
.shutdown = mxio_default_shutdown,
.posix_ioctl = mxio_default_posix_ioctl,
.get_vmo = mxio_default_get_vmo,
};
mxio_t* mxio_logger_create(mx_handle_t handle) {
mxio_log_t* log = calloc(1, sizeof(mxio_log_t));
if (log == NULL) {
return NULL;
}
log->io.ops = &log_io_ops;
log->io.magic = MXIO_MAGIC;
atomic_init(&log->io.refcount, 1);
log->handle = handle;
return &log->io;
}