1*598139dcSAndroid Build Coastguard Worker /*
2*598139dcSAndroid Build Coastguard Worker * Copyright (C) 2007-2016 The Android Open Source Project
3*598139dcSAndroid Build Coastguard Worker *
4*598139dcSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*598139dcSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*598139dcSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*598139dcSAndroid Build Coastguard Worker *
8*598139dcSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*598139dcSAndroid Build Coastguard Worker *
10*598139dcSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*598139dcSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*598139dcSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*598139dcSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*598139dcSAndroid Build Coastguard Worker * limitations under the License.
15*598139dcSAndroid Build Coastguard Worker */
16*598139dcSAndroid Build Coastguard Worker
17*598139dcSAndroid Build Coastguard Worker #include "pmsg_reader.h"
18*598139dcSAndroid Build Coastguard Worker
19*598139dcSAndroid Build Coastguard Worker #include <ctype.h>
20*598139dcSAndroid Build Coastguard Worker #include <errno.h>
21*598139dcSAndroid Build Coastguard Worker #include <fcntl.h>
22*598139dcSAndroid Build Coastguard Worker #include <stdlib.h>
23*598139dcSAndroid Build Coastguard Worker #include <string.h>
24*598139dcSAndroid Build Coastguard Worker #include <sys/types.h>
25*598139dcSAndroid Build Coastguard Worker
26*598139dcSAndroid Build Coastguard Worker #include <cutils/list.h>
27*598139dcSAndroid Build Coastguard Worker #include <private/android_logger.h>
28*598139dcSAndroid Build Coastguard Worker
29*598139dcSAndroid Build Coastguard Worker #include "logger.h"
30*598139dcSAndroid Build Coastguard Worker
PmsgRead(struct logger_list * logger_list,struct log_msg * log_msg)31*598139dcSAndroid Build Coastguard Worker int PmsgRead(struct logger_list* logger_list, struct log_msg* log_msg) {
32*598139dcSAndroid Build Coastguard Worker ssize_t ret;
33*598139dcSAndroid Build Coastguard Worker off_t current, next;
34*598139dcSAndroid Build Coastguard Worker struct __attribute__((__packed__)) {
35*598139dcSAndroid Build Coastguard Worker android_pmsg_log_header_t p;
36*598139dcSAndroid Build Coastguard Worker android_log_header_t l;
37*598139dcSAndroid Build Coastguard Worker uint8_t prio;
38*598139dcSAndroid Build Coastguard Worker } buf;
39*598139dcSAndroid Build Coastguard Worker static uint8_t preread_count;
40*598139dcSAndroid Build Coastguard Worker
41*598139dcSAndroid Build Coastguard Worker memset(log_msg, 0, sizeof(*log_msg));
42*598139dcSAndroid Build Coastguard Worker
43*598139dcSAndroid Build Coastguard Worker if (atomic_load(&logger_list->fd) <= 0) {
44*598139dcSAndroid Build Coastguard Worker int i, fd = open("/sys/fs/pstore/pmsg-ramoops-0", O_RDONLY | O_CLOEXEC);
45*598139dcSAndroid Build Coastguard Worker
46*598139dcSAndroid Build Coastguard Worker if (fd < 0) {
47*598139dcSAndroid Build Coastguard Worker return -errno;
48*598139dcSAndroid Build Coastguard Worker }
49*598139dcSAndroid Build Coastguard Worker if (fd == 0) { /* Argggg */
50*598139dcSAndroid Build Coastguard Worker fd = open("/sys/fs/pstore/pmsg-ramoops-0", O_RDONLY | O_CLOEXEC);
51*598139dcSAndroid Build Coastguard Worker close(0);
52*598139dcSAndroid Build Coastguard Worker if (fd < 0) {
53*598139dcSAndroid Build Coastguard Worker return -errno;
54*598139dcSAndroid Build Coastguard Worker }
55*598139dcSAndroid Build Coastguard Worker }
56*598139dcSAndroid Build Coastguard Worker i = atomic_exchange(&logger_list->fd, fd);
57*598139dcSAndroid Build Coastguard Worker if ((i > 0) && (i != fd)) {
58*598139dcSAndroid Build Coastguard Worker close(i);
59*598139dcSAndroid Build Coastguard Worker }
60*598139dcSAndroid Build Coastguard Worker preread_count = 0;
61*598139dcSAndroid Build Coastguard Worker }
62*598139dcSAndroid Build Coastguard Worker
63*598139dcSAndroid Build Coastguard Worker while (1) {
64*598139dcSAndroid Build Coastguard Worker int fd;
65*598139dcSAndroid Build Coastguard Worker
66*598139dcSAndroid Build Coastguard Worker if (preread_count < sizeof(buf)) {
67*598139dcSAndroid Build Coastguard Worker fd = atomic_load(&logger_list->fd);
68*598139dcSAndroid Build Coastguard Worker if (fd <= 0) {
69*598139dcSAndroid Build Coastguard Worker return -EBADF;
70*598139dcSAndroid Build Coastguard Worker }
71*598139dcSAndroid Build Coastguard Worker ret = TEMP_FAILURE_RETRY(read(fd, &buf.p.magic + preread_count, sizeof(buf) - preread_count));
72*598139dcSAndroid Build Coastguard Worker if (ret < 0) {
73*598139dcSAndroid Build Coastguard Worker return -errno;
74*598139dcSAndroid Build Coastguard Worker }
75*598139dcSAndroid Build Coastguard Worker preread_count += ret;
76*598139dcSAndroid Build Coastguard Worker }
77*598139dcSAndroid Build Coastguard Worker if (preread_count != sizeof(buf)) {
78*598139dcSAndroid Build Coastguard Worker return preread_count ? -EIO : -EAGAIN;
79*598139dcSAndroid Build Coastguard Worker }
80*598139dcSAndroid Build Coastguard Worker if ((buf.p.magic != LOGGER_MAGIC) || (buf.p.len <= sizeof(buf)) ||
81*598139dcSAndroid Build Coastguard Worker (buf.p.len > (sizeof(buf) + LOGGER_ENTRY_MAX_PAYLOAD)) ||
82*598139dcSAndroid Build Coastguard Worker !__android_log_id_is_valid(static_cast<log_id_t>(buf.l.id)) ||
83*598139dcSAndroid Build Coastguard Worker (buf.l.realtime.tv_nsec >= NS_PER_SEC) ||
84*598139dcSAndroid Build Coastguard Worker ((buf.l.id != LOG_ID_EVENTS) && (buf.l.id != LOG_ID_SECURITY) &&
85*598139dcSAndroid Build Coastguard Worker ((buf.prio == ANDROID_LOG_UNKNOWN) || (buf.prio == ANDROID_LOG_DEFAULT) ||
86*598139dcSAndroid Build Coastguard Worker (buf.prio >= ANDROID_LOG_SILENT)))) {
87*598139dcSAndroid Build Coastguard Worker do {
88*598139dcSAndroid Build Coastguard Worker memmove(&buf.p.magic, &buf.p.magic + 1, --preread_count);
89*598139dcSAndroid Build Coastguard Worker } while (preread_count && (buf.p.magic != LOGGER_MAGIC));
90*598139dcSAndroid Build Coastguard Worker continue;
91*598139dcSAndroid Build Coastguard Worker }
92*598139dcSAndroid Build Coastguard Worker preread_count = 0;
93*598139dcSAndroid Build Coastguard Worker
94*598139dcSAndroid Build Coastguard Worker if ((logger_list->log_mask & (1 << buf.l.id)) &&
95*598139dcSAndroid Build Coastguard Worker ((!logger_list->start.tv_sec && !logger_list->start.tv_nsec) ||
96*598139dcSAndroid Build Coastguard Worker ((logger_list->start.tv_sec <= buf.l.realtime.tv_sec) &&
97*598139dcSAndroid Build Coastguard Worker ((logger_list->start.tv_sec != buf.l.realtime.tv_sec) ||
98*598139dcSAndroid Build Coastguard Worker (logger_list->start.tv_nsec <= buf.l.realtime.tv_nsec)))) &&
99*598139dcSAndroid Build Coastguard Worker (!logger_list->pid || (logger_list->pid == buf.p.pid))) {
100*598139dcSAndroid Build Coastguard Worker char* msg = reinterpret_cast<char*>(&log_msg->entry) + sizeof(log_msg->entry);
101*598139dcSAndroid Build Coastguard Worker *msg = buf.prio;
102*598139dcSAndroid Build Coastguard Worker fd = atomic_load(&logger_list->fd);
103*598139dcSAndroid Build Coastguard Worker if (fd <= 0) {
104*598139dcSAndroid Build Coastguard Worker return -EBADF;
105*598139dcSAndroid Build Coastguard Worker }
106*598139dcSAndroid Build Coastguard Worker ret = TEMP_FAILURE_RETRY(read(fd, msg + sizeof(buf.prio), buf.p.len - sizeof(buf)));
107*598139dcSAndroid Build Coastguard Worker if (ret < 0) {
108*598139dcSAndroid Build Coastguard Worker return -errno;
109*598139dcSAndroid Build Coastguard Worker }
110*598139dcSAndroid Build Coastguard Worker if (ret != (ssize_t)(buf.p.len - sizeof(buf))) {
111*598139dcSAndroid Build Coastguard Worker return -EIO;
112*598139dcSAndroid Build Coastguard Worker }
113*598139dcSAndroid Build Coastguard Worker
114*598139dcSAndroid Build Coastguard Worker log_msg->entry.len = buf.p.len - sizeof(buf) + sizeof(buf.prio);
115*598139dcSAndroid Build Coastguard Worker log_msg->entry.hdr_size = sizeof(log_msg->entry);
116*598139dcSAndroid Build Coastguard Worker log_msg->entry.pid = buf.p.pid;
117*598139dcSAndroid Build Coastguard Worker log_msg->entry.tid = buf.l.tid;
118*598139dcSAndroid Build Coastguard Worker log_msg->entry.sec = buf.l.realtime.tv_sec;
119*598139dcSAndroid Build Coastguard Worker log_msg->entry.nsec = buf.l.realtime.tv_nsec;
120*598139dcSAndroid Build Coastguard Worker log_msg->entry.lid = buf.l.id;
121*598139dcSAndroid Build Coastguard Worker log_msg->entry.uid = buf.p.uid;
122*598139dcSAndroid Build Coastguard Worker
123*598139dcSAndroid Build Coastguard Worker return ret + sizeof(buf.prio) + log_msg->entry.hdr_size;
124*598139dcSAndroid Build Coastguard Worker }
125*598139dcSAndroid Build Coastguard Worker
126*598139dcSAndroid Build Coastguard Worker fd = atomic_load(&logger_list->fd);
127*598139dcSAndroid Build Coastguard Worker if (fd <= 0) {
128*598139dcSAndroid Build Coastguard Worker return -EBADF;
129*598139dcSAndroid Build Coastguard Worker }
130*598139dcSAndroid Build Coastguard Worker current = TEMP_FAILURE_RETRY(lseek(fd, (off_t)0, SEEK_CUR));
131*598139dcSAndroid Build Coastguard Worker if (current < 0) {
132*598139dcSAndroid Build Coastguard Worker return -errno;
133*598139dcSAndroid Build Coastguard Worker }
134*598139dcSAndroid Build Coastguard Worker fd = atomic_load(&logger_list->fd);
135*598139dcSAndroid Build Coastguard Worker if (fd <= 0) {
136*598139dcSAndroid Build Coastguard Worker return -EBADF;
137*598139dcSAndroid Build Coastguard Worker }
138*598139dcSAndroid Build Coastguard Worker next = TEMP_FAILURE_RETRY(lseek(fd, (off_t)(buf.p.len - sizeof(buf)), SEEK_CUR));
139*598139dcSAndroid Build Coastguard Worker if (next < 0) {
140*598139dcSAndroid Build Coastguard Worker return -errno;
141*598139dcSAndroid Build Coastguard Worker }
142*598139dcSAndroid Build Coastguard Worker if ((next - current) != (ssize_t)(buf.p.len - sizeof(buf))) {
143*598139dcSAndroid Build Coastguard Worker return -EIO;
144*598139dcSAndroid Build Coastguard Worker }
145*598139dcSAndroid Build Coastguard Worker }
146*598139dcSAndroid Build Coastguard Worker }
147*598139dcSAndroid Build Coastguard Worker
PmsgClose(struct logger_list * logger_list)148*598139dcSAndroid Build Coastguard Worker void PmsgClose(struct logger_list* logger_list) {
149*598139dcSAndroid Build Coastguard Worker int fd = atomic_exchange(&logger_list->fd, 0);
150*598139dcSAndroid Build Coastguard Worker if (fd > 0) {
151*598139dcSAndroid Build Coastguard Worker close(fd);
152*598139dcSAndroid Build Coastguard Worker }
153*598139dcSAndroid Build Coastguard Worker }
154*598139dcSAndroid Build Coastguard Worker
realloc_or_free(void * ptr,size_t new_size)155*598139dcSAndroid Build Coastguard Worker static void* realloc_or_free(void* ptr, size_t new_size) {
156*598139dcSAndroid Build Coastguard Worker void* result = realloc(ptr, new_size);
157*598139dcSAndroid Build Coastguard Worker if (!result) {
158*598139dcSAndroid Build Coastguard Worker free(ptr);
159*598139dcSAndroid Build Coastguard Worker }
160*598139dcSAndroid Build Coastguard Worker return result;
161*598139dcSAndroid Build Coastguard Worker }
162*598139dcSAndroid Build Coastguard Worker
__android_log_pmsg_file_read(log_id_t logId,char prio,const char * prefix,__android_log_pmsg_file_read_fn fn,void * arg)163*598139dcSAndroid Build Coastguard Worker ssize_t __android_log_pmsg_file_read(log_id_t logId, char prio, const char* prefix,
164*598139dcSAndroid Build Coastguard Worker __android_log_pmsg_file_read_fn fn, void* arg) {
165*598139dcSAndroid Build Coastguard Worker ssize_t ret;
166*598139dcSAndroid Build Coastguard Worker struct content {
167*598139dcSAndroid Build Coastguard Worker struct listnode node;
168*598139dcSAndroid Build Coastguard Worker struct logger_entry entry;
169*598139dcSAndroid Build Coastguard Worker } * content;
170*598139dcSAndroid Build Coastguard Worker struct names {
171*598139dcSAndroid Build Coastguard Worker struct listnode node;
172*598139dcSAndroid Build Coastguard Worker struct listnode content;
173*598139dcSAndroid Build Coastguard Worker log_id_t id;
174*598139dcSAndroid Build Coastguard Worker char prio;
175*598139dcSAndroid Build Coastguard Worker char name[];
176*598139dcSAndroid Build Coastguard Worker } * names;
177*598139dcSAndroid Build Coastguard Worker struct listnode name_list;
178*598139dcSAndroid Build Coastguard Worker struct listnode *node, *n;
179*598139dcSAndroid Build Coastguard Worker size_t len, prefix_len;
180*598139dcSAndroid Build Coastguard Worker
181*598139dcSAndroid Build Coastguard Worker if (!fn) {
182*598139dcSAndroid Build Coastguard Worker return -EINVAL;
183*598139dcSAndroid Build Coastguard Worker }
184*598139dcSAndroid Build Coastguard Worker
185*598139dcSAndroid Build Coastguard Worker /* Add just enough clues in logger_list and transp to make API function */
186*598139dcSAndroid Build Coastguard Worker struct logger_list logger_list = {
187*598139dcSAndroid Build Coastguard Worker .mode = static_cast<int>(ANDROID_LOG_PSTORE | ANDROID_LOG_NONBLOCK),
188*598139dcSAndroid Build Coastguard Worker .log_mask = (unsigned)-1};
189*598139dcSAndroid Build Coastguard Worker logger_list.log_mask = (1 << logId);
190*598139dcSAndroid Build Coastguard Worker logger_list.log_mask &= ~((1 << LOG_ID_KERNEL) | (1 << LOG_ID_EVENTS) | (1 << LOG_ID_SECURITY));
191*598139dcSAndroid Build Coastguard Worker if (!logger_list.log_mask) {
192*598139dcSAndroid Build Coastguard Worker return -EINVAL;
193*598139dcSAndroid Build Coastguard Worker }
194*598139dcSAndroid Build Coastguard Worker
195*598139dcSAndroid Build Coastguard Worker /* Initialize name list */
196*598139dcSAndroid Build Coastguard Worker list_init(&name_list);
197*598139dcSAndroid Build Coastguard Worker
198*598139dcSAndroid Build Coastguard Worker ret = SSIZE_MAX;
199*598139dcSAndroid Build Coastguard Worker
200*598139dcSAndroid Build Coastguard Worker /* Validate incoming prefix, shift until it contains only 0 or 1 : or / */
201*598139dcSAndroid Build Coastguard Worker prefix_len = 0;
202*598139dcSAndroid Build Coastguard Worker if (prefix) {
203*598139dcSAndroid Build Coastguard Worker const char *prev = NULL, *last = NULL, *cp = prefix;
204*598139dcSAndroid Build Coastguard Worker while ((cp = strpbrk(cp, "/:"))) {
205*598139dcSAndroid Build Coastguard Worker prev = last;
206*598139dcSAndroid Build Coastguard Worker last = cp;
207*598139dcSAndroid Build Coastguard Worker cp = cp + 1;
208*598139dcSAndroid Build Coastguard Worker }
209*598139dcSAndroid Build Coastguard Worker if (prev) {
210*598139dcSAndroid Build Coastguard Worker prefix = prev + 1;
211*598139dcSAndroid Build Coastguard Worker }
212*598139dcSAndroid Build Coastguard Worker prefix_len = strlen(prefix);
213*598139dcSAndroid Build Coastguard Worker }
214*598139dcSAndroid Build Coastguard Worker
215*598139dcSAndroid Build Coastguard Worker /* Read the file content */
216*598139dcSAndroid Build Coastguard Worker log_msg log_msg;
217*598139dcSAndroid Build Coastguard Worker while (PmsgRead(&logger_list, &log_msg) > 0) {
218*598139dcSAndroid Build Coastguard Worker const char* cp;
219*598139dcSAndroid Build Coastguard Worker size_t hdr_size = log_msg.entry.hdr_size;
220*598139dcSAndroid Build Coastguard Worker
221*598139dcSAndroid Build Coastguard Worker char* msg = (char*)&log_msg + hdr_size;
222*598139dcSAndroid Build Coastguard Worker const char* split = NULL;
223*598139dcSAndroid Build Coastguard Worker
224*598139dcSAndroid Build Coastguard Worker if (hdr_size != sizeof(log_msg.entry)) {
225*598139dcSAndroid Build Coastguard Worker continue;
226*598139dcSAndroid Build Coastguard Worker }
227*598139dcSAndroid Build Coastguard Worker /* Check for invalid sequence number */
228*598139dcSAndroid Build Coastguard Worker if (log_msg.entry.nsec % ANDROID_LOG_PMSG_FILE_SEQUENCE ||
229*598139dcSAndroid Build Coastguard Worker (log_msg.entry.nsec / ANDROID_LOG_PMSG_FILE_SEQUENCE) >=
230*598139dcSAndroid Build Coastguard Worker ANDROID_LOG_PMSG_FILE_MAX_SEQUENCE) {
231*598139dcSAndroid Build Coastguard Worker continue;
232*598139dcSAndroid Build Coastguard Worker }
233*598139dcSAndroid Build Coastguard Worker
234*598139dcSAndroid Build Coastguard Worker /* Determine if it has <dirbase>:<filebase> format for tag */
235*598139dcSAndroid Build Coastguard Worker len = log_msg.entry.len - sizeof(prio);
236*598139dcSAndroid Build Coastguard Worker for (cp = msg + sizeof(prio); *cp && isprint(*cp) && !isspace(*cp) && --len; ++cp) {
237*598139dcSAndroid Build Coastguard Worker if (*cp == ':') {
238*598139dcSAndroid Build Coastguard Worker if (split) {
239*598139dcSAndroid Build Coastguard Worker break;
240*598139dcSAndroid Build Coastguard Worker }
241*598139dcSAndroid Build Coastguard Worker split = cp;
242*598139dcSAndroid Build Coastguard Worker }
243*598139dcSAndroid Build Coastguard Worker }
244*598139dcSAndroid Build Coastguard Worker if (*cp || !split) {
245*598139dcSAndroid Build Coastguard Worker continue;
246*598139dcSAndroid Build Coastguard Worker }
247*598139dcSAndroid Build Coastguard Worker
248*598139dcSAndroid Build Coastguard Worker /* Filters */
249*598139dcSAndroid Build Coastguard Worker if (prefix_len && strncmp(msg + sizeof(prio), prefix, prefix_len)) {
250*598139dcSAndroid Build Coastguard Worker size_t offset;
251*598139dcSAndroid Build Coastguard Worker /*
252*598139dcSAndroid Build Coastguard Worker * Allow : to be a synonym for /
253*598139dcSAndroid Build Coastguard Worker * Things we do dealing with const char * and do not alloc
254*598139dcSAndroid Build Coastguard Worker */
255*598139dcSAndroid Build Coastguard Worker split = strchr(prefix, ':');
256*598139dcSAndroid Build Coastguard Worker if (split) {
257*598139dcSAndroid Build Coastguard Worker continue;
258*598139dcSAndroid Build Coastguard Worker }
259*598139dcSAndroid Build Coastguard Worker split = strchr(prefix, '/');
260*598139dcSAndroid Build Coastguard Worker if (!split) {
261*598139dcSAndroid Build Coastguard Worker continue;
262*598139dcSAndroid Build Coastguard Worker }
263*598139dcSAndroid Build Coastguard Worker offset = split - prefix;
264*598139dcSAndroid Build Coastguard Worker if ((msg[offset + sizeof(prio)] != ':') || strncmp(msg + sizeof(prio), prefix, offset)) {
265*598139dcSAndroid Build Coastguard Worker continue;
266*598139dcSAndroid Build Coastguard Worker }
267*598139dcSAndroid Build Coastguard Worker ++offset;
268*598139dcSAndroid Build Coastguard Worker if ((prefix_len > offset) &&
269*598139dcSAndroid Build Coastguard Worker strncmp(&msg[offset + sizeof(prio)], split + 1, prefix_len - offset)) {
270*598139dcSAndroid Build Coastguard Worker continue;
271*598139dcSAndroid Build Coastguard Worker }
272*598139dcSAndroid Build Coastguard Worker }
273*598139dcSAndroid Build Coastguard Worker
274*598139dcSAndroid Build Coastguard Worker if ((prio != ANDROID_LOG_ANY) && (*msg < prio)) {
275*598139dcSAndroid Build Coastguard Worker continue;
276*598139dcSAndroid Build Coastguard Worker }
277*598139dcSAndroid Build Coastguard Worker
278*598139dcSAndroid Build Coastguard Worker /* check if there is an existing entry */
279*598139dcSAndroid Build Coastguard Worker list_for_each(node, &name_list) {
280*598139dcSAndroid Build Coastguard Worker names = node_to_item(node, struct names, node);
281*598139dcSAndroid Build Coastguard Worker if (!strcmp(names->name, msg + sizeof(prio)) && names->id == log_msg.entry.lid &&
282*598139dcSAndroid Build Coastguard Worker names->prio == *msg) {
283*598139dcSAndroid Build Coastguard Worker break;
284*598139dcSAndroid Build Coastguard Worker }
285*598139dcSAndroid Build Coastguard Worker }
286*598139dcSAndroid Build Coastguard Worker
287*598139dcSAndroid Build Coastguard Worker /* We do not have an existing entry, create and add one */
288*598139dcSAndroid Build Coastguard Worker if (node == &name_list) {
289*598139dcSAndroid Build Coastguard Worker static const char numbers[] = "0123456789";
290*598139dcSAndroid Build Coastguard Worker unsigned long long nl;
291*598139dcSAndroid Build Coastguard Worker
292*598139dcSAndroid Build Coastguard Worker len = strlen(msg + sizeof(prio)) + 1;
293*598139dcSAndroid Build Coastguard Worker names = static_cast<struct names*>(calloc(1, sizeof(*names) + len));
294*598139dcSAndroid Build Coastguard Worker if (!names) {
295*598139dcSAndroid Build Coastguard Worker ret = -ENOMEM;
296*598139dcSAndroid Build Coastguard Worker break;
297*598139dcSAndroid Build Coastguard Worker }
298*598139dcSAndroid Build Coastguard Worker strcpy(names->name, msg + sizeof(prio));
299*598139dcSAndroid Build Coastguard Worker names->id = static_cast<log_id_t>(log_msg.entry.lid);
300*598139dcSAndroid Build Coastguard Worker names->prio = *msg;
301*598139dcSAndroid Build Coastguard Worker list_init(&names->content);
302*598139dcSAndroid Build Coastguard Worker /*
303*598139dcSAndroid Build Coastguard Worker * Insert in reverse numeric _then_ alpha sorted order as
304*598139dcSAndroid Build Coastguard Worker * representative of log rotation:
305*598139dcSAndroid Build Coastguard Worker *
306*598139dcSAndroid Build Coastguard Worker * log.10
307*598139dcSAndroid Build Coastguard Worker * klog.10
308*598139dcSAndroid Build Coastguard Worker * . . .
309*598139dcSAndroid Build Coastguard Worker * log.2
310*598139dcSAndroid Build Coastguard Worker * klog.2
311*598139dcSAndroid Build Coastguard Worker * log.1
312*598139dcSAndroid Build Coastguard Worker * klog.1
313*598139dcSAndroid Build Coastguard Worker * log
314*598139dcSAndroid Build Coastguard Worker * klog
315*598139dcSAndroid Build Coastguard Worker *
316*598139dcSAndroid Build Coastguard Worker * thus when we present the content, we are provided the oldest
317*598139dcSAndroid Build Coastguard Worker * first, which when 'refreshed' could spill off the end of the
318*598139dcSAndroid Build Coastguard Worker * pmsg FIFO but retaining the newest data for last with best
319*598139dcSAndroid Build Coastguard Worker * chances to survive.
320*598139dcSAndroid Build Coastguard Worker */
321*598139dcSAndroid Build Coastguard Worker nl = 0;
322*598139dcSAndroid Build Coastguard Worker cp = strpbrk(names->name, numbers);
323*598139dcSAndroid Build Coastguard Worker if (cp) {
324*598139dcSAndroid Build Coastguard Worker nl = strtoull(cp, NULL, 10);
325*598139dcSAndroid Build Coastguard Worker }
326*598139dcSAndroid Build Coastguard Worker list_for_each_reverse(node, &name_list) {
327*598139dcSAndroid Build Coastguard Worker struct names* a_name = node_to_item(node, struct names, node);
328*598139dcSAndroid Build Coastguard Worker const char* r = a_name->name;
329*598139dcSAndroid Build Coastguard Worker int compare = 0;
330*598139dcSAndroid Build Coastguard Worker
331*598139dcSAndroid Build Coastguard Worker unsigned long long nr = 0;
332*598139dcSAndroid Build Coastguard Worker cp = strpbrk(r, numbers);
333*598139dcSAndroid Build Coastguard Worker if (cp) {
334*598139dcSAndroid Build Coastguard Worker nr = strtoull(cp, NULL, 10);
335*598139dcSAndroid Build Coastguard Worker }
336*598139dcSAndroid Build Coastguard Worker if (nr != nl) {
337*598139dcSAndroid Build Coastguard Worker compare = (nl > nr) ? 1 : -1;
338*598139dcSAndroid Build Coastguard Worker }
339*598139dcSAndroid Build Coastguard Worker if (compare == 0) {
340*598139dcSAndroid Build Coastguard Worker compare = strcmp(names->name, r);
341*598139dcSAndroid Build Coastguard Worker }
342*598139dcSAndroid Build Coastguard Worker if (compare <= 0) {
343*598139dcSAndroid Build Coastguard Worker break;
344*598139dcSAndroid Build Coastguard Worker }
345*598139dcSAndroid Build Coastguard Worker }
346*598139dcSAndroid Build Coastguard Worker list_add_head(node, &names->node);
347*598139dcSAndroid Build Coastguard Worker }
348*598139dcSAndroid Build Coastguard Worker
349*598139dcSAndroid Build Coastguard Worker /* Remove any file fragments that match our sequence number */
350*598139dcSAndroid Build Coastguard Worker list_for_each_safe(node, n, &names->content) {
351*598139dcSAndroid Build Coastguard Worker content = node_to_item(node, struct content, node);
352*598139dcSAndroid Build Coastguard Worker if (log_msg.entry.nsec == content->entry.nsec) {
353*598139dcSAndroid Build Coastguard Worker list_remove(&content->node);
354*598139dcSAndroid Build Coastguard Worker free(content);
355*598139dcSAndroid Build Coastguard Worker }
356*598139dcSAndroid Build Coastguard Worker }
357*598139dcSAndroid Build Coastguard Worker
358*598139dcSAndroid Build Coastguard Worker /* Add content */
359*598139dcSAndroid Build Coastguard Worker content = static_cast<struct content*>(
360*598139dcSAndroid Build Coastguard Worker calloc(1, sizeof(content->node) + hdr_size + log_msg.entry.len));
361*598139dcSAndroid Build Coastguard Worker if (!content) {
362*598139dcSAndroid Build Coastguard Worker ret = -ENOMEM;
363*598139dcSAndroid Build Coastguard Worker break;
364*598139dcSAndroid Build Coastguard Worker }
365*598139dcSAndroid Build Coastguard Worker memcpy(&content->entry, &log_msg.entry, hdr_size + log_msg.entry.len);
366*598139dcSAndroid Build Coastguard Worker
367*598139dcSAndroid Build Coastguard Worker /* Insert in sequence number sorted order, to ease reconstruction */
368*598139dcSAndroid Build Coastguard Worker list_for_each_reverse(node, &names->content) {
369*598139dcSAndroid Build Coastguard Worker if ((node_to_item(node, struct content, node))->entry.nsec < log_msg.entry.nsec) {
370*598139dcSAndroid Build Coastguard Worker break;
371*598139dcSAndroid Build Coastguard Worker }
372*598139dcSAndroid Build Coastguard Worker }
373*598139dcSAndroid Build Coastguard Worker list_add_head(node, &content->node);
374*598139dcSAndroid Build Coastguard Worker }
375*598139dcSAndroid Build Coastguard Worker PmsgClose(&logger_list);
376*598139dcSAndroid Build Coastguard Worker
377*598139dcSAndroid Build Coastguard Worker /* Progress through all the collected files */
378*598139dcSAndroid Build Coastguard Worker list_for_each_safe(node, n, &name_list) {
379*598139dcSAndroid Build Coastguard Worker struct listnode *content_node, *m;
380*598139dcSAndroid Build Coastguard Worker char* buf;
381*598139dcSAndroid Build Coastguard Worker size_t sequence, tag_len;
382*598139dcSAndroid Build Coastguard Worker
383*598139dcSAndroid Build Coastguard Worker names = node_to_item(node, struct names, node);
384*598139dcSAndroid Build Coastguard Worker
385*598139dcSAndroid Build Coastguard Worker /* Construct content into a linear buffer */
386*598139dcSAndroid Build Coastguard Worker buf = NULL;
387*598139dcSAndroid Build Coastguard Worker len = 0;
388*598139dcSAndroid Build Coastguard Worker sequence = 0;
389*598139dcSAndroid Build Coastguard Worker tag_len = strlen(names->name) + sizeof(char); /* tag + nul */
390*598139dcSAndroid Build Coastguard Worker list_for_each_safe(content_node, m, &names->content) {
391*598139dcSAndroid Build Coastguard Worker ssize_t add_len;
392*598139dcSAndroid Build Coastguard Worker
393*598139dcSAndroid Build Coastguard Worker content = node_to_item(content_node, struct content, node);
394*598139dcSAndroid Build Coastguard Worker add_len = content->entry.len - tag_len - sizeof(prio);
395*598139dcSAndroid Build Coastguard Worker if (add_len <= 0) {
396*598139dcSAndroid Build Coastguard Worker list_remove(content_node);
397*598139dcSAndroid Build Coastguard Worker free(content);
398*598139dcSAndroid Build Coastguard Worker continue;
399*598139dcSAndroid Build Coastguard Worker }
400*598139dcSAndroid Build Coastguard Worker
401*598139dcSAndroid Build Coastguard Worker if (!buf) {
402*598139dcSAndroid Build Coastguard Worker buf = static_cast<char*>(malloc(sizeof(char)));
403*598139dcSAndroid Build Coastguard Worker if (!buf) {
404*598139dcSAndroid Build Coastguard Worker ret = -ENOMEM;
405*598139dcSAndroid Build Coastguard Worker list_remove(content_node);
406*598139dcSAndroid Build Coastguard Worker free(content);
407*598139dcSAndroid Build Coastguard Worker continue;
408*598139dcSAndroid Build Coastguard Worker }
409*598139dcSAndroid Build Coastguard Worker *buf = '\0';
410*598139dcSAndroid Build Coastguard Worker }
411*598139dcSAndroid Build Coastguard Worker
412*598139dcSAndroid Build Coastguard Worker /* Missing sequence numbers */
413*598139dcSAndroid Build Coastguard Worker while (sequence < content->entry.nsec) {
414*598139dcSAndroid Build Coastguard Worker /* plus space for enforced nul */
415*598139dcSAndroid Build Coastguard Worker buf = static_cast<char*>(realloc_or_free(buf, len + sizeof(char) + sizeof(char)));
416*598139dcSAndroid Build Coastguard Worker if (!buf) {
417*598139dcSAndroid Build Coastguard Worker break;
418*598139dcSAndroid Build Coastguard Worker }
419*598139dcSAndroid Build Coastguard Worker buf[len] = '\f'; /* Mark missing content with a form feed */
420*598139dcSAndroid Build Coastguard Worker buf[++len] = '\0';
421*598139dcSAndroid Build Coastguard Worker sequence += ANDROID_LOG_PMSG_FILE_SEQUENCE;
422*598139dcSAndroid Build Coastguard Worker }
423*598139dcSAndroid Build Coastguard Worker if (!buf) {
424*598139dcSAndroid Build Coastguard Worker ret = -ENOMEM;
425*598139dcSAndroid Build Coastguard Worker list_remove(content_node);
426*598139dcSAndroid Build Coastguard Worker free(content);
427*598139dcSAndroid Build Coastguard Worker continue;
428*598139dcSAndroid Build Coastguard Worker }
429*598139dcSAndroid Build Coastguard Worker /* plus space for enforced nul */
430*598139dcSAndroid Build Coastguard Worker buf = static_cast<char*>(realloc_or_free(buf, len + add_len + sizeof(char)));
431*598139dcSAndroid Build Coastguard Worker if (!buf) {
432*598139dcSAndroid Build Coastguard Worker ret = -ENOMEM;
433*598139dcSAndroid Build Coastguard Worker list_remove(content_node);
434*598139dcSAndroid Build Coastguard Worker free(content);
435*598139dcSAndroid Build Coastguard Worker continue;
436*598139dcSAndroid Build Coastguard Worker }
437*598139dcSAndroid Build Coastguard Worker memcpy(buf + len, (char*)&content->entry + content->entry.hdr_size + tag_len + sizeof(prio),
438*598139dcSAndroid Build Coastguard Worker add_len);
439*598139dcSAndroid Build Coastguard Worker len += add_len;
440*598139dcSAndroid Build Coastguard Worker buf[len] = '\0'; /* enforce trailing hidden nul */
441*598139dcSAndroid Build Coastguard Worker sequence = content->entry.nsec + ANDROID_LOG_PMSG_FILE_SEQUENCE;
442*598139dcSAndroid Build Coastguard Worker
443*598139dcSAndroid Build Coastguard Worker list_remove(content_node);
444*598139dcSAndroid Build Coastguard Worker free(content);
445*598139dcSAndroid Build Coastguard Worker }
446*598139dcSAndroid Build Coastguard Worker if (buf) {
447*598139dcSAndroid Build Coastguard Worker if (len) {
448*598139dcSAndroid Build Coastguard Worker /* Buffer contains enforced trailing nul just beyond length */
449*598139dcSAndroid Build Coastguard Worker ssize_t r;
450*598139dcSAndroid Build Coastguard Worker *strchr(names->name, ':') = '/'; /* Convert back to filename */
451*598139dcSAndroid Build Coastguard Worker r = (*fn)(names->id, names->prio, names->name, buf, len, arg);
452*598139dcSAndroid Build Coastguard Worker if ((ret >= 0) && (r > 0)) {
453*598139dcSAndroid Build Coastguard Worker if (ret == SSIZE_MAX) {
454*598139dcSAndroid Build Coastguard Worker ret = r;
455*598139dcSAndroid Build Coastguard Worker } else {
456*598139dcSAndroid Build Coastguard Worker ret += r;
457*598139dcSAndroid Build Coastguard Worker }
458*598139dcSAndroid Build Coastguard Worker } else if (r < ret) {
459*598139dcSAndroid Build Coastguard Worker ret = r;
460*598139dcSAndroid Build Coastguard Worker }
461*598139dcSAndroid Build Coastguard Worker }
462*598139dcSAndroid Build Coastguard Worker free(buf);
463*598139dcSAndroid Build Coastguard Worker }
464*598139dcSAndroid Build Coastguard Worker list_remove(node);
465*598139dcSAndroid Build Coastguard Worker free(names);
466*598139dcSAndroid Build Coastguard Worker }
467*598139dcSAndroid Build Coastguard Worker return (ret == SSIZE_MAX) ? -ENOENT : ret;
468*598139dcSAndroid Build Coastguard Worker }
469