1 /*
2 ** Copyright 2013-2014, 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
17 #include "log/log_read.h"
18
19 #include <errno.h>
20 #include <fcntl.h>
21 #include <pthread.h>
22 #include <sched.h>
23 #include <stddef.h>
24 #include <stdint.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <unistd.h>
28
29 #include <android/log.h>
30
31 #include "logd_reader.h"
32 #include "logger.h"
33 #include "pmsg_reader.h"
34
35 /* method for getting the associated sublog id */
android_logger_get_id(struct logger * logger)36 log_id_t android_logger_get_id(struct logger* logger) {
37 return static_cast<log_id_t>(reinterpret_cast<uintptr_t>(logger) & LOGGER_LOG_ID_MASK);
38 }
39
android_logger_list_alloc_internal(int mode,unsigned int tail,log_time start,pid_t pid)40 static struct logger_list* android_logger_list_alloc_internal(int mode, unsigned int tail,
41 log_time start, pid_t pid) {
42 auto* logger_list = static_cast<struct logger_list*>(calloc(1, sizeof(struct logger_list)));
43 if (!logger_list) {
44 return nullptr;
45 }
46
47 logger_list->mode = mode;
48 logger_list->start = start;
49 logger_list->tail = tail;
50 logger_list->pid = pid;
51
52 return logger_list;
53 }
54
android_logger_list_alloc(int mode,unsigned int tail,pid_t pid)55 struct logger_list* android_logger_list_alloc(int mode, unsigned int tail, pid_t pid) {
56 return android_logger_list_alloc_internal(mode, tail, log_time(0, 0), pid);
57 }
58
android_logger_list_alloc_time(int mode,log_time start,pid_t pid)59 struct logger_list* android_logger_list_alloc_time(int mode, log_time start, pid_t pid) {
60 return android_logger_list_alloc_internal(mode, 0, start, pid);
61 }
62
63 /* Open the named log and add it to the logger list */
android_logger_open(struct logger_list * logger_list,log_id_t logId)64 struct logger* android_logger_open(struct logger_list* logger_list, log_id_t logId) {
65 if (!logger_list || (logId >= LOG_ID_MAX)) {
66 return nullptr;
67 }
68
69 logger_list->log_mask |= 1 << logId;
70
71 uintptr_t logger = logId;
72 logger |= (logger_list->mode & ANDROID_LOG_PSTORE) ? LOGGER_PMSG : LOGGER_LOGD;
73 return reinterpret_cast<struct logger*>(logger);
74 }
75
76 /* Open the single named log and make it part of a new logger list */
android_logger_list_open(log_id_t logId,int mode,unsigned int tail,pid_t pid)77 struct logger_list* android_logger_list_open(log_id_t logId, int mode, unsigned int tail,
78 pid_t pid) {
79 struct logger_list* logger_list = android_logger_list_alloc(mode, tail, pid);
80
81 if (!logger_list) {
82 return NULL;
83 }
84
85 if (!android_logger_open(logger_list, logId)) {
86 android_logger_list_free(logger_list);
87 return NULL;
88 }
89
90 return logger_list;
91 }
92
android_logger_list_read(struct logger_list * logger_list,struct log_msg * log_msg)93 int android_logger_list_read(struct logger_list* logger_list, struct log_msg* log_msg) {
94 if (logger_list == nullptr || logger_list->log_mask == 0) {
95 return -EINVAL;
96 }
97
98 int ret = 0;
99
100 #ifdef __ANDROID__
101 if (logger_list->mode & ANDROID_LOG_PSTORE) {
102 ret = PmsgRead(logger_list, log_msg);
103 } else {
104 ret = LogdRead(logger_list, log_msg);
105 }
106 #endif
107
108 if (ret <= 0) {
109 return ret;
110 }
111
112 if (ret > LOGGER_ENTRY_MAX_LEN) {
113 ret = LOGGER_ENTRY_MAX_LEN;
114 }
115
116 if (ret < static_cast<int>(sizeof(log_msg->entry))) {
117 return -EINVAL;
118 }
119
120 if (log_msg->entry.hdr_size < sizeof(log_msg->entry) ||
121 log_msg->entry.hdr_size >= LOGGER_ENTRY_MAX_LEN - sizeof(log_msg->entry)) {
122 return -EINVAL;
123 }
124
125 if (log_msg->entry.len > ret - log_msg->entry.hdr_size) {
126 return -EINVAL;
127 }
128
129 log_msg->buf[log_msg->entry.len + log_msg->entry.hdr_size] = '\0';
130
131 return ret;
132 }
133
134 /* Close all the logs */
android_logger_list_free(struct logger_list * logger_list)135 void android_logger_list_free(struct logger_list* logger_list) {
136 if (logger_list == NULL) {
137 return;
138 }
139
140 #ifdef __ANDROID__
141 if (logger_list->mode & ANDROID_LOG_PSTORE) {
142 PmsgClose(logger_list);
143 } else {
144 LogdClose(logger_list);
145 }
146 #endif
147
148 free(logger_list);
149 }
150