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