1 // Copyright 2018 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <lib/zxio/inception.h>
6 #include <lib/zxio/null.h>
7 #include <lib/zxio/ops.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <zircon/syscalls.h>
11 #include <zircon/syscalls/log.h>
12
13 #define LOGBUF_MAX (ZX_LOG_RECORD_MAX - sizeof(zx_log_record_t))
14
15 struct zxio_debuglog_buffer {
16 unsigned next;
17 char pending[LOGBUF_MAX];
18 };
19
zxio_debuglog_close(zxio_t * io)20 static zx_status_t zxio_debuglog_close(zxio_t* io) {
21 zxio_debuglog_t* debuglog = reinterpret_cast<zxio_debuglog_t*>(io);
22 zx_handle_t handle = debuglog->handle;
23 debuglog->handle = ZX_HANDLE_INVALID;
24 zx_handle_close(handle);
25 if (debuglog->buffer != nullptr) {
26 free(debuglog->buffer);
27 debuglog->buffer = nullptr;
28 }
29 return ZX_OK;
30 }
31
zxio_debuglog_write(zxio_t * io,const void * buffer,size_t capacity,size_t * out_actual)32 static zx_status_t zxio_debuglog_write(zxio_t* io, const void* buffer, size_t capacity,
33 size_t* out_actual) {
34 zxio_debuglog_t* debuglog = reinterpret_cast<zxio_debuglog_t*>(io);
35
36 if (debuglog->buffer == nullptr) {
37 debuglog->buffer = static_cast<zxio_debuglog_buffer_t*>(
38 calloc(1, sizeof(*debuglog->buffer)));
39 if (debuglog->buffer == nullptr) {
40 *out_actual = capacity;
41 return ZX_OK;
42 }
43 }
44
45 zxio_debuglog_buffer_t* outgoing = debuglog->buffer;
46 const uint8_t* data = static_cast<const uint8_t*>(buffer);
47 size_t n = capacity;
48 while (n-- > 0u) {
49 char c = *data++;
50 if (c == '\n') {
51 zx_debuglog_write(debuglog->handle, 0u, outgoing->pending,
52 outgoing->next);
53 outgoing->next = 0u;
54 continue;
55 }
56 if (c < ' ') {
57 continue;
58 }
59 outgoing->pending[outgoing->next++] = c;
60 if (outgoing->next == LOGBUF_MAX) {
61 zx_debuglog_write(debuglog->handle, 0u, outgoing->pending,
62 outgoing->next);
63 outgoing->next = 0u;
64 continue;
65 }
66 }
67 *out_actual = capacity;
68 return ZX_OK;
69 }
70
__anon57eaef0d0102() 71 static constexpr zxio_ops_t zxio_debuglog_ops = ([]() {
72 zxio_ops_t ops = zxio_default_ops;
73 ops.close = zxio_debuglog_close;
74 ops.write = zxio_debuglog_write;
75 return ops;
76 })();
77
zxio_debuglog_init(zxio_storage_t * storage,zx_handle_t handle)78 zx_status_t zxio_debuglog_init(zxio_storage_t* storage, zx_handle_t handle) {
79 zxio_debuglog_t* debuglog = reinterpret_cast<zxio_debuglog_t*>(storage);
80 zxio_init(&debuglog->io, &zxio_debuglog_ops);
81 debuglog->handle = handle;
82 debuglog->buffer = nullptr;
83 return ZX_OK;
84 }
85