1154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn/* 2154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn** Copyright 2013-2014, The Android Open Source Project 3154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn** 4154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn** Licensed under the Apache License, Version 2.0 (the "License"); 5154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn** you may not use this file except in compliance with the License. 6154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn** You may obtain a copy of the License at 7154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn** 8154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn** http://www.apache.org/licenses/LICENSE-2.0 9154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn** 10154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn** Unless required by applicable law or agreed to in writing, software 11154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn** distributed under the License is distributed on an "AS IS" BASIS, 12154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn** See the License for the specific language governing permissions and 14154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn** limitations under the License. 15154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn*/ 16154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 17154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn#define _GNU_SOURCE /* asprintf for x86 host */ 18154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn#include <errno.h> 19154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn#include <fcntl.h> 20154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn#include <poll.h> 21154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn#include <string.h> 22154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn#include <stdio.h> 23154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn#include <stdlib.h> 24a04464adaf5b95ae953f8577632d3cf8aa2c80a3Mark Salyzyn#include <sys/cdefs.h> 25a04464adaf5b95ae953f8577632d3cf8aa2c80a3Mark Salyzyn#include <sys/ioctl.h> 26a04464adaf5b95ae953f8577632d3cf8aa2c80a3Mark Salyzyn 27154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn#include <cutils/list.h> 28154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn#include <log/log.h> 29154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn#include <log/logger.h> 30154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 31154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn#define __LOGGERIO 0xAE 32154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 33154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn#define LOGGER_GET_LOG_BUF_SIZE _IO(__LOGGERIO, 1) /* size of log */ 34154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn#define LOGGER_GET_LOG_LEN _IO(__LOGGERIO, 2) /* used log len */ 35154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn#define LOGGER_GET_NEXT_ENTRY_LEN _IO(__LOGGERIO, 3) /* next entry len */ 36154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn#define LOGGER_FLUSH_LOG _IO(__LOGGERIO, 4) /* flush log */ 37154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn#define LOGGER_GET_VERSION _IO(__LOGGERIO, 5) /* abi version */ 38154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn#define LOGGER_SET_VERSION _IO(__LOGGERIO, 6) /* abi version */ 39154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 40154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyntypedef char bool; 41154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn#define false (const bool)0 42154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn#define true (const bool)1 43154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 44154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn#define LOG_FILE_DIR "/dev/log/" 45154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 46154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn/* timeout in milliseconds */ 47154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn#define LOG_TIMEOUT_FLUSH 5 48154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn#define LOG_TIMEOUT_NEVER -1 49154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 50154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn#define logger_for_each(logger, logger_list) \ 51154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn for (logger = node_to_item((logger_list)->node.next, struct logger, node); \ 52154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn logger != node_to_item(&(logger_list)->node, struct logger, node); \ 53154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn logger = node_to_item((logger)->node.next, struct logger, node)) 54154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 55a04464adaf5b95ae953f8577632d3cf8aa2c80a3Mark Salyzyn#ifndef __unused 56a04464adaf5b95ae953f8577632d3cf8aa2c80a3Mark Salyzyn#define __unused __attribute__((unused)) 57a04464adaf5b95ae953f8577632d3cf8aa2c80a3Mark Salyzyn#endif 5834facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn 59154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn/* In the future, we would like to make this list extensible */ 60154f4608aac6218af0e25c98b71d0803278c047eMark Salyzynstatic const char *LOG_NAME[LOG_ID_MAX] = { 61154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn [LOG_ID_MAIN] = "main", 62154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn [LOG_ID_RADIO] = "radio", 63154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn [LOG_ID_EVENTS] = "events", 6499f47a9e7c4374f2bbfc18e4a97aa7848245ea33Mark Salyzyn [LOG_ID_SYSTEM] = "system", 6599f47a9e7c4374f2bbfc18e4a97aa7848245ea33Mark Salyzyn [LOG_ID_CRASH] = "crash" 66154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn}; 67154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 68154f4608aac6218af0e25c98b71d0803278c047eMark Salyzynconst char *android_log_id_to_name(log_id_t log_id) 69154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn{ 70154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (log_id >= LOG_ID_MAX) { 71154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn log_id = LOG_ID_MAIN; 72154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 73154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn return LOG_NAME[log_id]; 74154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn} 75154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 76154f4608aac6218af0e25c98b71d0803278c047eMark Salyzynstatic int accessmode(int mode) 77154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn{ 78154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if ((mode & O_ACCMODE) == O_WRONLY) { 79154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn return W_OK; 80154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 81154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if ((mode & O_ACCMODE) == O_RDWR) { 82154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn return R_OK | W_OK; 83154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 84154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn return R_OK; 85154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn} 86154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 87154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn/* repeated fragment */ 88154f4608aac6218af0e25c98b71d0803278c047eMark Salyzynstatic int check_allocate_accessible(char **n, const char *b, int mode) 89154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn{ 90154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn *n = NULL; 91154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 92154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (!b) { 93154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn return -EINVAL; 94154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 95154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 96154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn asprintf(n, LOG_FILE_DIR "%s", b); 97154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (!*n) { 98154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn return -1; 99154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 100154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 101154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn return access(*n, accessmode(mode)); 102154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn} 103154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 104154f4608aac6218af0e25c98b71d0803278c047eMark Salyzynlog_id_t android_name_to_log_id(const char *logName) 105154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn{ 106154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn const char *b; 107154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn char *n; 108154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn int ret; 109154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 110154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (!logName) { 111154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn return -1; /* NB: log_id_t is unsigned */ 112154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 113154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn b = strrchr(logName, '/'); 114154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (!b) { 115154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn b = logName; 116154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } else { 117154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn ++b; 118154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 119154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 120154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn ret = check_allocate_accessible(&n, b, O_RDONLY); 121154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn free(n); 122154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (ret) { 123154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn return ret; 124154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 125154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 126154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn for(ret = LOG_ID_MIN; ret < LOG_ID_MAX; ++ret) { 127154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn const char *l = LOG_NAME[ret]; 128154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (l && !strcmp(b, l)) { 129154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn return ret; 130154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 131154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 132154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn return -1; /* should never happen */ 133154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn} 134154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 135154f4608aac6218af0e25c98b71d0803278c047eMark Salyzynstruct logger_list { 136154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn struct listnode node; 137154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn int mode; 138154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn unsigned int tail; 139154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn pid_t pid; 140154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn unsigned int queued_lines; 141154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn int timeout_ms; 142154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn int error; 143154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn bool flush; 144154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn bool valid_entry; /* valiant(?) effort to deal with memory starvation */ 145154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn struct log_msg entry; 146154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn}; 147154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 148154f4608aac6218af0e25c98b71d0803278c047eMark Salyzynstruct log_list { 149154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn struct listnode node; 150154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn struct log_msg entry; /* Truncated to event->len() + 1 to save space */ 151154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn}; 152154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 153154f4608aac6218af0e25c98b71d0803278c047eMark Salyzynstruct logger { 154154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn struct listnode node; 155154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn struct logger_list *top; 156154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn int fd; 157154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn log_id_t id; 158154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn short *revents; 159154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn struct listnode log_list; 160154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn}; 161154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 162154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn/* android_logger_alloc unimplemented, no use case */ 163154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn/* android_logger_free not exported */ 164154f4608aac6218af0e25c98b71d0803278c047eMark Salyzynstatic void android_logger_free(struct logger *logger) 165154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn{ 166154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (!logger) { 167154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn return; 168154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 169154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 170154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn while (!list_empty(&logger->log_list)) { 171154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn struct log_list *entry = node_to_item( 172154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn list_head(&logger->log_list), struct log_list, node); 173154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn list_remove(&entry->node); 174154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn free(entry); 175154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (logger->top->queued_lines) { 176154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn logger->top->queued_lines--; 177154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 178154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 179154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 180154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (logger->fd >= 0) { 181154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn close(logger->fd); 182154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 183154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 184154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn list_remove(&logger->node); 185154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 186154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn free(logger); 187154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn} 188154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 189154f4608aac6218af0e25c98b71d0803278c047eMark Salyzynlog_id_t android_logger_get_id(struct logger *logger) 190154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn{ 191154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn return logger->id; 192154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn} 193154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 194154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn/* worker for sending the command to the logger */ 195154f4608aac6218af0e25c98b71d0803278c047eMark Salyzynstatic int logger_ioctl(struct logger *logger, int cmd, int mode) 196154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn{ 197154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn char *n; 198154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn int f, ret; 199154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 200154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (!logger || !logger->top) { 201154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn return -EFAULT; 202154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 203154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 204154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (((mode & O_ACCMODE) == O_RDWR) 205154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn || (((mode ^ logger->top->mode) & O_ACCMODE) == 0)) { 206154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn return ioctl(logger->fd, cmd); 207154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 208154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 209154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn /* We go here if android_logger_list_open got mode wrong for this ioctl */ 210154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn ret = check_allocate_accessible(&n, android_log_id_to_name(logger->id), mode); 211154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (ret) { 212154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn free(n); 213154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn return ret; 214154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 215154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 216154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn f = open(n, mode); 217154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn free(n); 218154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (f < 0) { 219154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn return f; 220154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 221154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 222154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn ret = ioctl(f, cmd); 223154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn close (f); 224154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 225154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn return ret; 226154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn} 227154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 228154f4608aac6218af0e25c98b71d0803278c047eMark Salyzynint android_logger_clear(struct logger *logger) 229154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn{ 230154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn return logger_ioctl(logger, LOGGER_FLUSH_LOG, O_WRONLY); 231154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn} 232154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 233154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn/* returns the total size of the log's ring buffer */ 234dfa7a07f5be656cfafdb4e75916bc9dcd9e592e7Mark Salyzynlong android_logger_get_log_size(struct logger *logger) 235154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn{ 236154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn return logger_ioctl(logger, LOGGER_GET_LOG_BUF_SIZE, O_RDWR); 237154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn} 238154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 239a04464adaf5b95ae953f8577632d3cf8aa2c80a3Mark Salyzynint android_logger_set_log_size(struct logger *logger __unused, 240a04464adaf5b95ae953f8577632d3cf8aa2c80a3Mark Salyzyn unsigned long size __unused) 241dfa7a07f5be656cfafdb4e75916bc9dcd9e592e7Mark Salyzyn{ 242dfa7a07f5be656cfafdb4e75916bc9dcd9e592e7Mark Salyzyn return -ENOTSUP; 243dfa7a07f5be656cfafdb4e75916bc9dcd9e592e7Mark Salyzyn} 244dfa7a07f5be656cfafdb4e75916bc9dcd9e592e7Mark Salyzyn 245154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn/* 246154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn * returns the readable size of the log's ring buffer (that is, amount of the 247154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn * log consumed) 248154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn */ 249dfa7a07f5be656cfafdb4e75916bc9dcd9e592e7Mark Salyzynlong android_logger_get_log_readable_size(struct logger *logger) 250154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn{ 251154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn return logger_ioctl(logger, LOGGER_GET_LOG_LEN, O_RDONLY); 252154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn} 253154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 254154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn/* 255154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn * returns the logger version 256154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn */ 257154f4608aac6218af0e25c98b71d0803278c047eMark Salyzynint android_logger_get_log_version(struct logger *logger) 258154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn{ 259154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn int ret = logger_ioctl(logger, LOGGER_GET_VERSION, O_RDWR); 260154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn return (ret < 0) ? 1 : ret; 261154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn} 262154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 26334facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn/* 26434facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn * returns statistics 26534facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn */ 266dfa7a07f5be656cfafdb4e75916bc9dcd9e592e7Mark Salyzynstatic const char unsupported[] = "18\nNot Supported\n\f"; 26734facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn 268a04464adaf5b95ae953f8577632d3cf8aa2c80a3Mark Salyzynssize_t android_logger_get_statistics(struct logger_list *logger_list __unused, 26934facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn char *buf, size_t len) 27034facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn{ 27134facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn strncpy(buf, unsupported, len); 27234facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn return -ENOTSUP; 27334facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn} 27434facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn 275a04464adaf5b95ae953f8577632d3cf8aa2c80a3Mark Salyzynssize_t android_logger_get_prune_list(struct logger_list *logger_list __unused, 276dfa7a07f5be656cfafdb4e75916bc9dcd9e592e7Mark Salyzyn char *buf, size_t len) 277dfa7a07f5be656cfafdb4e75916bc9dcd9e592e7Mark Salyzyn{ 278dfa7a07f5be656cfafdb4e75916bc9dcd9e592e7Mark Salyzyn strncpy(buf, unsupported, len); 279dfa7a07f5be656cfafdb4e75916bc9dcd9e592e7Mark Salyzyn return -ENOTSUP; 280dfa7a07f5be656cfafdb4e75916bc9dcd9e592e7Mark Salyzyn} 281dfa7a07f5be656cfafdb4e75916bc9dcd9e592e7Mark Salyzyn 282a04464adaf5b95ae953f8577632d3cf8aa2c80a3Mark Salyzynint android_logger_set_prune_list(struct logger_list *logger_list __unused, 283dfa7a07f5be656cfafdb4e75916bc9dcd9e592e7Mark Salyzyn char *buf, size_t len) 284dfa7a07f5be656cfafdb4e75916bc9dcd9e592e7Mark Salyzyn{ 285dfa7a07f5be656cfafdb4e75916bc9dcd9e592e7Mark Salyzyn static const char unsupported_error[] = "Unsupported"; 286dfa7a07f5be656cfafdb4e75916bc9dcd9e592e7Mark Salyzyn strncpy(buf, unsupported, len); 287dfa7a07f5be656cfafdb4e75916bc9dcd9e592e7Mark Salyzyn return -ENOTSUP; 288dfa7a07f5be656cfafdb4e75916bc9dcd9e592e7Mark Salyzyn} 289dfa7a07f5be656cfafdb4e75916bc9dcd9e592e7Mark Salyzyn 290154f4608aac6218af0e25c98b71d0803278c047eMark Salyzynstruct logger_list *android_logger_list_alloc(int mode, 291154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn unsigned int tail, 292154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn pid_t pid) 293154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn{ 294154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn struct logger_list *logger_list; 295154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 296154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn logger_list = calloc(1, sizeof(*logger_list)); 297154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (!logger_list) { 298154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn return NULL; 299154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 300154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn list_init(&logger_list->node); 301154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn logger_list->mode = mode; 302154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn logger_list->tail = tail; 303154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn logger_list->pid = pid; 304154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn return logger_list; 305154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn} 306154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 307fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzynstruct logger_list *android_logger_list_alloc_time(int mode, 308a04464adaf5b95ae953f8577632d3cf8aa2c80a3Mark Salyzyn log_time start __unused, 309fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn pid_t pid) 310fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn{ 311fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn return android_logger_list_alloc(mode, 0, pid); 312fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn} 313fa3716b2501ccddc8e0cd30f6343692b8deb7639Mark Salyzyn 314154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn/* android_logger_list_register unimplemented, no use case */ 315154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn/* android_logger_list_unregister unimplemented, no use case */ 316154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 317154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn/* Open the named log and add it to the logger list */ 318154f4608aac6218af0e25c98b71d0803278c047eMark Salyzynstruct logger *android_logger_open(struct logger_list *logger_list, 319154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn log_id_t id) 320154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn{ 321154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn struct listnode *node; 322154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn struct logger *logger; 323154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn char *n; 324154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 325154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (!logger_list || (id >= LOG_ID_MAX)) { 326154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn goto err; 327154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 328154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 329154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn logger_for_each(logger, logger_list) { 330154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (logger->id == id) { 331154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn goto ok; 332154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 333154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 334154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 335154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn logger = calloc(1, sizeof(*logger)); 336154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (!logger) { 337154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn goto err; 338154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 339154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 340154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (check_allocate_accessible(&n, android_log_id_to_name(id), 341154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn logger_list->mode)) { 342154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn goto err_name; 343154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 344154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 345154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn logger->fd = open(n, logger_list->mode); 346154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (logger->fd < 0) { 347154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn goto err_name; 348154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 349154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 350154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn free(n); 351154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn logger->id = id; 352154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn list_init(&logger->log_list); 353154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn list_add_tail(&logger_list->node, &logger->node); 354154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn logger->top = logger_list; 355154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn logger_list->timeout_ms = LOG_TIMEOUT_FLUSH; 356154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn goto ok; 357154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 358154f4608aac6218af0e25c98b71d0803278c047eMark Salyzynerr_name: 359154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn free(n); 360154f4608aac6218af0e25c98b71d0803278c047eMark Salyzynerr_logger: 361154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn free(logger); 362154f4608aac6218af0e25c98b71d0803278c047eMark Salyzynerr: 363154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn logger = NULL; 364154f4608aac6218af0e25c98b71d0803278c047eMark Salyzynok: 365154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn return logger; 366154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn} 367154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 368154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn/* Open the single named log and make it part of a new logger list */ 369154f4608aac6218af0e25c98b71d0803278c047eMark Salyzynstruct logger_list *android_logger_list_open(log_id_t id, 370154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn int mode, 371154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn unsigned int tail, 372154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn pid_t pid) 373154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn{ 374154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn struct logger_list *logger_list = android_logger_list_alloc(mode, tail, pid); 375154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (!logger_list) { 376154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn return NULL; 377154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 378154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 379154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (!android_logger_open(logger_list, id)) { 380154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn android_logger_list_free(logger_list); 381154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn return NULL; 382154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 383154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 384154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn return logger_list; 385154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn} 386154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 387154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn/* prevent memory starvation when backfilling */ 388154f4608aac6218af0e25c98b71d0803278c047eMark Salyzynstatic unsigned int queue_threshold(struct logger_list *logger_list) 389154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn{ 390154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn return (logger_list->tail < 64) ? 64 : logger_list->tail; 391154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn} 392154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 393154f4608aac6218af0e25c98b71d0803278c047eMark Salyzynstatic bool low_queue(struct listnode *node) 394154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn{ 395154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn /* low is considered less than 2 */ 396154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn return list_head(node) == list_tail(node); 397154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn} 398154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 399154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn/* Flush queues in sequential order, one at a time */ 400154f4608aac6218af0e25c98b71d0803278c047eMark Salyzynstatic int android_logger_list_flush(struct logger_list *logger_list, 401154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn struct log_msg *log_msg) 402154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn{ 403154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn int ret = 0; 404154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn struct log_list *firstentry = NULL; 405154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 406154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn while ((ret == 0) 407154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn && (logger_list->flush 408154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn || (logger_list->queued_lines > logger_list->tail))) { 409154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn struct logger *logger; 410154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 411154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn /* Merge sort */ 412154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn bool at_least_one_is_low = false; 413154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn struct logger *firstlogger = NULL; 414154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn firstentry = NULL; 415154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 416154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn logger_for_each(logger, logger_list) { 417154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn struct listnode *node; 418154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn struct log_list *oldest = NULL; 419154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 420154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn /* kernel logger channels not necessarily time-sort order */ 421154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn list_for_each(node, &logger->log_list) { 422154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn struct log_list *entry = node_to_item(node, 423154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn struct log_list, node); 424154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (!oldest 425154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn || (entry->entry.entry.sec < oldest->entry.entry.sec) 426154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn || ((entry->entry.entry.sec == oldest->entry.entry.sec) 427154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn && (entry->entry.entry.nsec < oldest->entry.entry.nsec))) { 428154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn oldest = entry; 429154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 430154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 431154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 432154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (!oldest) { 433154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn at_least_one_is_low = true; 434154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn continue; 435154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } else if (low_queue(&logger->log_list)) { 436154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn at_least_one_is_low = true; 437154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 438154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 439154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (!firstentry 440154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn || (oldest->entry.entry.sec < firstentry->entry.entry.sec) 441154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn || ((oldest->entry.entry.sec == firstentry->entry.entry.sec) 442154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn && (oldest->entry.entry.nsec < firstentry->entry.entry.nsec))) { 443154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn firstentry = oldest; 444154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn firstlogger = logger; 445154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 446154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 447154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 448154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (!firstentry) { 449154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn break; 450154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 451154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 452154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn /* when trimming list, tries to keep one entry behind in each bucket */ 453154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (!logger_list->flush 454154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn && at_least_one_is_low 455154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn && (logger_list->queued_lines < queue_threshold(logger_list))) { 456154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn break; 457154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 458154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 459154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn /* within tail?, send! */ 460154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if ((logger_list->tail == 0) 461154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn || (logger_list->queued_lines <= logger_list->tail)) { 462154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn int diff; 463154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn ret = firstentry->entry.entry.hdr_size; 464154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (!ret) { 465154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn ret = sizeof(firstentry->entry.entry_v1); 466154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 467154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 468154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn /* Promote entry to v3 format */ 469154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn memcpy(log_msg->buf, firstentry->entry.buf, ret); 470154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn diff = sizeof(firstentry->entry.entry_v3) - ret; 471154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (diff < 0) { 472154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn diff = 0; 473154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } else if (diff > 0) { 474154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn memset(log_msg->buf + ret, 0, diff); 475154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 476154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn memcpy(log_msg->buf + ret + diff, firstentry->entry.buf + ret, 477154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn firstentry->entry.entry.len + 1); 478154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn ret += diff; 479154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn log_msg->entry.hdr_size = ret; 480154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn log_msg->entry.lid = firstlogger->id; 481154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 482154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn ret += firstentry->entry.entry.len; 483154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 484154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 485154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn /* next entry */ 486154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn list_remove(&firstentry->node); 487154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn free(firstentry); 488154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (logger_list->queued_lines) { 489154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn logger_list->queued_lines--; 490154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 491154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 492154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 493154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn /* Flushed the list, no longer in tail mode for continuing content */ 494154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (logger_list->flush && !firstentry) { 495154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn logger_list->tail = 0; 496154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 497154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn return ret; 498154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn} 499154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 500154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn/* Read from the selected logs */ 501154f4608aac6218af0e25c98b71d0803278c047eMark Salyzynint android_logger_list_read(struct logger_list *logger_list, 502154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn struct log_msg *log_msg) 503154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn{ 504154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn struct logger *logger; 505154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn nfds_t nfds; 506154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn struct pollfd *p, *pollfds = NULL; 507154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn int error = 0, ret = 0; 508154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 509154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn memset(log_msg, 0, sizeof(struct log_msg)); 510154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 511154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (!logger_list) { 512154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn return -ENODEV; 513154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 514154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 515154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (!(accessmode(logger_list->mode) & R_OK)) { 516154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn logger_list->error = EPERM; 517154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn goto done; 518154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 519154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 520154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn nfds = 0; 521154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn logger_for_each(logger, logger_list) { 522154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn ++nfds; 523154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 524154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (nfds <= 0) { 525154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn error = ENODEV; 526154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn goto done; 527154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 528154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 529154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn /* Do we have anything to offer from the buffer or state? */ 530154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (logger_list->valid_entry) { /* implies we are also in a flush state */ 531154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn goto flush; 532154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 533154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 534154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn ret = android_logger_list_flush(logger_list, log_msg); 535154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (ret) { 536154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn goto done; 537154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 538154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 539154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (logger_list->error) { /* implies we are also in a flush state */ 540154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn goto done; 541154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 542154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 543154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn /* Lets start grinding on metal */ 544154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn pollfds = calloc(nfds, sizeof(struct pollfd)); 545154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (!pollfds) { 546154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn error = ENOMEM; 547154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn goto flush; 548154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 549154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 550154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn p = pollfds; 551154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn logger_for_each(logger, logger_list) { 552154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn p->fd = logger->fd; 553154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn p->events = POLLIN; 554154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn logger->revents = &p->revents; 555154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn ++p; 556154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 557154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 558154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn while (!ret && !error) { 559154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn int result; 560154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 561154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn /* If we oversleep it's ok, i.e. ignore EINTR. */ 562154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn result = TEMP_FAILURE_RETRY( 563154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn poll(pollfds, nfds, logger_list->timeout_ms)); 564154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 565154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (result <= 0) { 566154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (result) { 567154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn error = errno; 568154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } else if (logger_list->mode & O_NDELAY) { 569154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn error = EAGAIN; 570154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } else { 571154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn logger_list->timeout_ms = LOG_TIMEOUT_NEVER; 572154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 573154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 574154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn logger_list->flush = true; 575154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn goto try_flush; 576154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 577154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 578154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn logger_list->timeout_ms = LOG_TIMEOUT_FLUSH; 579154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 580154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn /* Anti starvation */ 581154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (!logger_list->flush 582154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn && (logger_list->queued_lines > (queue_threshold(logger_list) / 2))) { 583154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn /* Any queues with input pending that is low? */ 584154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn bool starving = false; 585154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn logger_for_each(logger, logger_list) { 586154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if ((*(logger->revents) & POLLIN) 587154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn && low_queue(&logger->log_list)) { 588154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn starving = true; 589154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn break; 590154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 591154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 592154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 593154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn /* pushback on any queues that are not low */ 594154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (starving) { 595154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn logger_for_each(logger, logger_list) { 596154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if ((*(logger->revents) & POLLIN) 597154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn && !low_queue(&logger->log_list)) { 598154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn *(logger->revents) &= ~POLLIN; 599154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 600154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 601154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 602154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 603154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 604154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn logger_for_each(logger, logger_list) { 605154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn unsigned int hdr_size; 606154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn struct log_list *entry; 607154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn int diff; 608154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 609154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (!(*(logger->revents) & POLLIN)) { 610154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn continue; 611154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 612154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 613154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn memset(logger_list->entry.buf, 0, sizeof(struct log_msg)); 614154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn /* NOTE: driver guarantees we read exactly one full entry */ 615154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn result = read(logger->fd, logger_list->entry.buf, 616154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn LOGGER_ENTRY_MAX_LEN); 617154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (result <= 0) { 618154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (!result) { 619154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn error = EIO; 620154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } else if (errno != EINTR) { 621154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn error = errno; 622154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 623154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn continue; 624154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 625154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 626154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (logger_list->pid 627154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn && (logger_list->pid != logger_list->entry.entry.pid)) { 628154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn continue; 629154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 630154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 631154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn hdr_size = logger_list->entry.entry.hdr_size; 632154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (!hdr_size) { 633154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn hdr_size = sizeof(logger_list->entry.entry_v1); 634154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 635154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 636154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if ((hdr_size > sizeof(struct log_msg)) 637154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn || (logger_list->entry.entry.len 638154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn > sizeof(logger_list->entry.buf) - hdr_size) 639154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn || (logger_list->entry.entry.len != result - hdr_size)) { 640154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn error = EINVAL; 641154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn continue; 642154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 643154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 644154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn /* Promote entry to v3 format */ 645154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn diff = sizeof(logger_list->entry.entry_v3) - hdr_size; 646154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (diff > 0) { 647154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (logger_list->entry.entry.len 648154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn > sizeof(logger_list->entry.buf) - hdr_size - diff) { 649154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn error = EINVAL; 650154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn continue; 651154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 652154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn result += diff; 653154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn memmove(logger_list->entry.buf + hdr_size + diff, 654154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn logger_list->entry.buf + hdr_size, 655154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn logger_list->entry.entry.len + 1); 656154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn memset(logger_list->entry.buf + hdr_size, 0, diff); 657154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn logger_list->entry.entry.hdr_size = hdr_size + diff; 658154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 659154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn logger_list->entry.entry.lid = logger->id; 660154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 661154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn /* speedup: If not tail, and only one list, send directly */ 662154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (!logger_list->tail 663154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn && (list_head(&logger_list->node) 664154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn == list_tail(&logger_list->node))) { 665154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn ret = result; 666154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn memcpy(log_msg->buf, logger_list->entry.buf, result + 1); 667154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn break; 668154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 669154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 670154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn entry = malloc(sizeof(*entry) - sizeof(entry->entry) + result + 1); 671154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 672154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (!entry) { 673154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn logger_list->valid_entry = true; 674154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn error = ENOMEM; 675154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn break; 676154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 677154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 678154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn logger_list->queued_lines++; 679154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 680154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn memcpy(entry->entry.buf, logger_list->entry.buf, result); 681154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn entry->entry.buf[result] = '\0'; 682154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn list_add_tail(&logger->log_list, &entry->node); 683154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 684154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 685154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (ret <= 0) { 686154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyntry_flush: 687154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn ret = android_logger_list_flush(logger_list, log_msg); 688154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 689154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 690154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 691154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn free(pollfds); 692154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 693154f4608aac6218af0e25c98b71d0803278c047eMark Salyzynflush: 694154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (error) { 695154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn logger_list->flush = true; 696154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 697154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 698154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (ret <= 0) { 699154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn ret = android_logger_list_flush(logger_list, log_msg); 700154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 701154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (!ret && logger_list->valid_entry) { 702154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn ret = logger_list->entry.entry.hdr_size; 703154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (!ret) { 704154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn ret = sizeof(logger_list->entry.entry_v1); 705154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 706154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn ret += logger_list->entry.entry.len; 707154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 708154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn memcpy(log_msg->buf, logger_list->entry.buf, 709154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn sizeof(struct log_msg)); 710154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn logger_list->valid_entry = false; 711154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 712154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 713154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 714154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyndone: 715154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (logger_list->error) { 716154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn error = logger_list->error; 717154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 718154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (error) { 719154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn logger_list->error = error; 720154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (!ret) { 721154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn ret = -error; 722154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 723154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 724154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn return ret; 725154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn} 726154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 727154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn/* Close all the logs */ 728154f4608aac6218af0e25c98b71d0803278c047eMark Salyzynvoid android_logger_list_free(struct logger_list *logger_list) 729154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn{ 730154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn if (logger_list == NULL) { 731154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn return; 732154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 733154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 734154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn while (!list_empty(&logger_list->node)) { 735154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn struct listnode *node = list_head(&logger_list->node); 736154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn struct logger *logger = node_to_item(node, struct logger, node); 737154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn android_logger_free(logger); 738154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn } 739154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn 740154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn free(logger_list); 741154f4608aac6218af0e25c98b71d0803278c047eMark Salyzyn} 742