1facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn/* 2facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn * Copyright (C) 2007-2016 The Android Open Source Project 3facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn * 4facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn * Licensed under the Apache License, Version 2.0 (the "License"); 5facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn * you may not use this file except in compliance with the License. 6facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn * You may obtain a copy of the License at 7facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn * 8facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn * http://www.apache.org/licenses/LICENSE-2.0 9facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn * 10facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn * Unless required by applicable law or agreed to in writing, software 11facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn * distributed under the License is distributed on an "AS IS" BASIS, 12facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn * See the License for the specific language governing permissions and 14facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn * limitations under the License. 15facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn */ 16facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn 172b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn#include <ctype.h> 18facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn#include <errno.h> 19facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn#include <fcntl.h> 20facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn#include <stdbool.h> 212b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn#include <stdlib.h> 22facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn#include <string.h> 23facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn#include <sys/types.h> 24facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn 25facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn#include <private/android_filesystem_config.h> 26facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn#include <private/android_logger.h> 27facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn 28facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn#include "config_read.h" 29facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn#include "logger.h" 30facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn 31facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzynstatic int pmsgAvailable(log_id_t logId); 32facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzynstatic int pmsgVersion(struct android_log_logger *logger, 33facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn struct android_log_transport_context *transp); 34facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzynstatic int pmsgRead(struct android_log_logger_list *logger_list, 35facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn struct android_log_transport_context *transp, 36facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn struct log_msg *log_msg); 37facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzynstatic void pmsgClose(struct android_log_logger_list *logger_list, 38facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn struct android_log_transport_context *transp); 39facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzynstatic int pmsgClear(struct android_log_logger *logger, 40facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn struct android_log_transport_context *transp); 41facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn 42facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark SalyzynLIBLOG_HIDDEN struct android_log_transport_read pmsgLoggerRead = { 43facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn .node = { &pmsgLoggerRead.node, &pmsgLoggerRead.node }, 44facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn .name = "pmsg", 45facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn .available = pmsgAvailable, 46facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn .version = pmsgVersion, 47facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn .read = pmsgRead, 48facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn .poll = NULL, 49facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn .close = pmsgClose, 50facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn .clear = pmsgClear, 51facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn .setSize = NULL, 52facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn .getSize = NULL, 53facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn .getReadableSize = NULL, 54facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn .getPrune = NULL, 55facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn .setPrune = NULL, 56facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn .getStats = NULL, 57facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn}; 58facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn 59facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzynstatic int pmsgAvailable(log_id_t logId) 60facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn{ 61facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn if (logId > LOG_ID_SECURITY) { 62facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn return -EINVAL; 63facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn } 64facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn if (access("/dev/pmsg0", W_OK) == 0) { 65facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn return 0; 66facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn } 67facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn return -EBADF; 68facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn} 69facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn 70facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn/* Determine the credentials of the caller */ 71facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzynstatic bool uid_has_log_permission(uid_t uid) 72facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn{ 73facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn return (uid == AID_SYSTEM) || (uid == AID_LOG) || (uid == AID_ROOT); 74facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn} 75facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn 76facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzynstatic uid_t get_best_effective_uid() 77facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn{ 78facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn uid_t euid; 79facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn uid_t uid; 80facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn gid_t gid; 81facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn ssize_t i; 82facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn static uid_t last_uid = (uid_t) -1; 83facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn 84facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn if (last_uid != (uid_t) -1) { 85facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn return last_uid; 86facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn } 87facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn uid = __android_log_uid(); 88facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn if (uid_has_log_permission(uid)) { 89facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn return last_uid = uid; 90facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn } 91facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn euid = geteuid(); 92facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn if (uid_has_log_permission(euid)) { 93facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn return last_uid = euid; 94facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn } 95facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn gid = getgid(); 96facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn if (uid_has_log_permission(gid)) { 97facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn return last_uid = gid; 98facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn } 99facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn gid = getegid(); 100facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn if (uid_has_log_permission(gid)) { 101facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn return last_uid = gid; 102facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn } 103facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn i = getgroups((size_t) 0, NULL); 104facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn if (i > 0) { 105facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn gid_t list[i]; 106facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn 107facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn getgroups(i, list); 108facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn while (--i >= 0) { 109facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn if (uid_has_log_permission(list[i])) { 110facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn return last_uid = list[i]; 111facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn } 112facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn } 113facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn } 114facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn return last_uid = uid; 115facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn} 116facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn 117facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzynstatic int pmsgClear(struct android_log_logger *logger __unused, 118facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn struct android_log_transport_context *transp __unused) 119facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn{ 120facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn if (uid_has_log_permission(get_best_effective_uid())) { 121facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn return unlink("/sys/fs/pstore/pmsg-ramoops-0"); 122facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn } 123facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn errno = EPERM; 124facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn return -1; 125facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn} 126facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn 127facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn/* 128facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn * returns the logger version 129facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn */ 130facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzynstatic int pmsgVersion(struct android_log_logger *logger __unused, 131facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn struct android_log_transport_context *transp __unused) 132facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn{ 133facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn return 4; 134facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn} 135facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn 136facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzynstatic int pmsgRead(struct android_log_logger_list *logger_list, 137facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn struct android_log_transport_context *transp, 138facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn struct log_msg *log_msg) 139facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn{ 140facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn ssize_t ret; 141facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn off_t current, next; 142facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn uid_t uid; 143facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn struct android_log_logger *logger; 144facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn struct __attribute__((__packed__)) { 145facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn android_pmsg_log_header_t p; 146facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn android_log_header_t l; 147facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn } buf; 148facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn static uint8_t preread_count; 149facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn bool is_system; 150facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn 151facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn memset(log_msg, 0, sizeof(*log_msg)); 152facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn 153facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn if (transp->context.fd <= 0) { 1542b409c9bc73a333373d58dd4f8a0fd77537da29cMark Salyzyn int fd = open("/sys/fs/pstore/pmsg-ramoops-0", O_RDONLY | O_CLOEXEC); 155facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn 156facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn if (fd < 0) { 157facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn return -errno; 158facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn } 159facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn if (fd == 0) { /* Argggg */ 1602b409c9bc73a333373d58dd4f8a0fd77537da29cMark Salyzyn fd = open("/sys/fs/pstore/pmsg-ramoops-0", O_RDONLY | O_CLOEXEC); 161facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn close(0); 162facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn if (fd < 0) { 163facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn return -errno; 164facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn } 165facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn } 166facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn transp->context.fd = fd; 167facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn preread_count = 0; 168facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn } 169facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn 170facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn while(1) { 171facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn if (preread_count < sizeof(buf)) { 172facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn ret = TEMP_FAILURE_RETRY(read(transp->context.fd, 173facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn &buf.p.magic + preread_count, 174facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn sizeof(buf) - preread_count)); 175facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn if (ret < 0) { 176facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn return -errno; 177facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn } 178facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn preread_count += ret; 179facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn } 180facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn if (preread_count != sizeof(buf)) { 181facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn return preread_count ? -EIO : -EAGAIN; 182facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn } 183facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn if ((buf.p.magic != LOGGER_MAGIC) 184facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn || (buf.p.len <= sizeof(buf)) 185facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn || (buf.p.len > (sizeof(buf) + LOGGER_ENTRY_MAX_PAYLOAD)) 186facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn || (buf.l.id >= LOG_ID_MAX) 187facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn || (buf.l.realtime.tv_nsec >= NS_PER_SEC)) { 188facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn do { 189facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn memmove(&buf.p.magic, &buf.p.magic + 1, --preread_count); 190facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn } while (preread_count && (buf.p.magic != LOGGER_MAGIC)); 191facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn continue; 192facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn } 193facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn preread_count = 0; 194facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn 195facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn if ((transp->logMask & (1 << buf.l.id)) && 196facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn ((!logger_list->start.tv_sec && !logger_list->start.tv_nsec) || 197facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn ((logger_list->start.tv_sec <= buf.l.realtime.tv_sec) && 198facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn ((logger_list->start.tv_sec != buf.l.realtime.tv_sec) || 199facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn (logger_list->start.tv_nsec <= 200facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn buf.l.realtime.tv_nsec)))) && 201facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn (!logger_list->pid || (logger_list->pid == buf.p.pid))) { 202facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn uid = get_best_effective_uid(); 203facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn is_system = uid_has_log_permission(uid); 204facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn if (is_system || (uid == buf.p.uid)) { 205facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn ret = TEMP_FAILURE_RETRY(read(transp->context.fd, 206facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn is_system ? 207facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn log_msg->entry_v4.msg : 208facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn log_msg->entry_v3.msg, 209facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn buf.p.len - sizeof(buf))); 210facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn if (ret < 0) { 211facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn return -errno; 212facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn } 213facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn if (ret != (ssize_t)(buf.p.len - sizeof(buf))) { 214facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn return -EIO; 215facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn } 216facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn 217facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn log_msg->entry_v4.len = buf.p.len - sizeof(buf); 218facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn log_msg->entry_v4.hdr_size = is_system ? 219facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn sizeof(log_msg->entry_v4) : 220facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn sizeof(log_msg->entry_v3); 221facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn log_msg->entry_v4.pid = buf.p.pid; 222facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn log_msg->entry_v4.tid = buf.l.tid; 223facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn log_msg->entry_v4.sec = buf.l.realtime.tv_sec; 224facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn log_msg->entry_v4.nsec = buf.l.realtime.tv_nsec; 225facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn log_msg->entry_v4.lid = buf.l.id; 226facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn if (is_system) { 227facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn log_msg->entry_v4.uid = buf.p.uid; 228facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn } 229facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn 23008660a811e078d3a6ce950a340a1b9071cfd7e8dRubin Xu return ret + log_msg->entry_v4.hdr_size; 231facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn } 232facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn } 233facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn 234facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn current = TEMP_FAILURE_RETRY(lseek(transp->context.fd, 235facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn (off_t)0, SEEK_CUR)); 236facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn if (current < 0) { 237facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn return -errno; 238facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn } 239facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn next = TEMP_FAILURE_RETRY(lseek(transp->context.fd, 240facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn (off_t)(buf.p.len - sizeof(buf)), 241facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn SEEK_CUR)); 242facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn if (next < 0) { 243facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn return -errno; 244facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn } 245facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn if ((next - current) != (ssize_t)(buf.p.len - sizeof(buf))) { 246facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn return -EIO; 247facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn } 248facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn } 249facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn} 250facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn 251facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzynstatic void pmsgClose(struct android_log_logger_list *logger_list __unused, 252facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn struct android_log_transport_context *transp) { 253facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn if (transp->context.fd > 0) { 254facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn close (transp->context.fd); 255facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn } 256facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn transp->context.fd = 0; 257facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn} 2582b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn 2592b8157d9fd2a3dcb7370fe2614e2c47315186519Mark SalyzynLIBLOG_ABI_PRIVATE ssize_t __android_log_pmsg_file_read( 2602b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn log_id_t logId, 2612b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn char prio, 2622b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn const char *prefix, 2632b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn __android_log_pmsg_file_read_fn fn, void *arg) { 2642b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn ssize_t ret; 2652b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn struct android_log_logger_list logger_list; 2662b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn struct android_log_transport_context transp; 2672b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn struct content { 2682b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn struct listnode node; 2692b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn union { 2702b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn struct logger_entry_v4 entry; 2712b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn struct logger_entry_v4 entry_v4; 2722b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn struct logger_entry_v3 entry_v3; 2732b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn struct logger_entry_v2 entry_v2; 2742b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn struct logger_entry entry_v1; 2752b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn }; 2762b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn } *content; 2772b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn struct names { 2782b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn struct listnode node; 2792b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn struct listnode content; 2802b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn log_id_t id; 2812b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn char prio; 2822b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn char name[]; 2832b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn } *names; 2842b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn struct listnode name_list; 2852b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn struct listnode *node, *n; 2862b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn size_t len, prefix_len; 2872b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn 2882b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn if (!fn) { 2892b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn return -EINVAL; 2902b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn } 2912b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn 2922b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn /* Add just enough clues in logger_list and transp to make API function */ 2932b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn memset(&logger_list, 0, sizeof(logger_list)); 2942b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn memset(&transp, 0, sizeof(transp)); 2952b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn 2962b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn logger_list.mode = ANDROID_LOG_PSTORE | 2972b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn ANDROID_LOG_NONBLOCK | 2982b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn ANDROID_LOG_RDONLY; 2992b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn transp.logMask = (unsigned)-1; 3002b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn if (logId != LOG_ID_ANY) { 3012b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn transp.logMask = (1 << logId); 3022b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn } 3032b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn transp.logMask &= ~((1 << LOG_ID_KERNEL) | 3042b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn (1 << LOG_ID_EVENTS) | 3052b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn (1 << LOG_ID_SECURITY)); 3062b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn if (!transp.logMask) { 3072b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn return -EINVAL; 3082b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn } 3092b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn 3102b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn /* Initialize name list */ 3112b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn list_init(&name_list); 3122b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn 3132b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn ret = SSIZE_MAX; 3142b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn 3152b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn /* Validate incoming prefix, shift until it contains only 0 or 1 : or / */ 3162b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn prefix_len = 0; 3172b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn if (prefix) { 3182b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn const char *prev = NULL, *last = NULL, *cp = prefix; 3192b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn while ((cp = strpbrk(cp, "/:"))) { 3202b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn prev = last; 3212b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn last = cp; 3222b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn cp = cp + 1; 3232b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn } 3242b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn if (prev) { 3252b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn prefix = prev + 1; 3262b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn } 3272b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn prefix_len = strlen(prefix); 3282b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn } 3292b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn 3302b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn /* Read the file content */ 3312b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn while (pmsgRead(&logger_list, &transp, &transp.logMsg) > 0) { 3322b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn char *cp; 3332b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn size_t hdr_size = transp.logMsg.entry.hdr_size ? 3342b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn transp.logMsg.entry.hdr_size : sizeof(transp.logMsg.entry_v1); 3352b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn char *msg = (char *)&transp.logMsg + hdr_size; 3362b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn char *split = NULL; 3372b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn 3382b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn /* Check for invalid sequence number */ 3392b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn if ((transp.logMsg.entry.nsec % ANDROID_LOG_PMSG_FILE_SEQUENCE) || 3402b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn ((transp.logMsg.entry.nsec / ANDROID_LOG_PMSG_FILE_SEQUENCE) >= 3412b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn ANDROID_LOG_PMSG_FILE_MAX_SEQUENCE)) { 3422b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn continue; 3432b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn } 3442b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn 3452b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn /* Determine if it has <dirbase>:<filebase> format for tag */ 3462b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn len = transp.logMsg.entry.len - sizeof(prio); 3472b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn for (cp = msg + sizeof(prio); 3482b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn *cp && isprint(*cp) && !isspace(*cp) && --len; 3492b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn ++cp) { 3502b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn if (*cp == ':') { 3512b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn if (split) { 3522b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn break; 3532b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn } 3542b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn split = cp; 3552b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn } 3562b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn } 3572b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn if (*cp || !split) { 3582b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn continue; 3592b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn } 3602b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn 3612b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn /* Filters */ 3622b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn if (prefix_len && strncmp(msg + sizeof(prio), prefix, prefix_len)) { 3632b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn size_t offset; 3642b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn /* 3652b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn * Allow : to be a synonym for / 3662b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn * Things we do dealing with const char * and do not alloc 3672b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn */ 3682b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn split = strchr(prefix, ':'); 3692b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn if (split) { 3702b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn continue; 3712b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn } 3722b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn split = strchr(prefix, '/'); 3732b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn if (!split) { 3742b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn continue; 3752b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn } 3762b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn offset = split - prefix; 3772b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn if ((msg[offset + sizeof(prio)] != ':') || 3782b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn strncmp(msg + sizeof(prio), prefix, offset)) { 3792b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn continue; 3802b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn } 3812b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn ++offset; 3822b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn if ((prefix_len > offset) && 3832b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn strncmp(&msg[offset + sizeof(prio)], split + 1, prefix_len - offset)) { 3842b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn continue; 3852b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn } 3862b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn } 3872b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn 3882b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn if ((prio != ANDROID_LOG_ANY) && (*msg < prio)) { 3892b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn continue; 3902b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn } 3912b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn 3922b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn /* check if there is an existing entry */ 3932b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn list_for_each(node, &name_list) { 3942b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn names = node_to_item(node, struct names, node); 3952b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn if (!strcmp(names->name, msg + sizeof(prio)) && 3962b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn (names->id == transp.logMsg.entry.lid) && 3972b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn (names->prio == *msg)) { 3982b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn break; 3992b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn } 4002b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn } 4012b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn 4022b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn /* We do not have an existing entry, create and add one */ 4032b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn if (node == &name_list) { 4042b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn static const char numbers[] = "0123456789"; 4052b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn unsigned long long nl; 4062b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn 4072b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn len = strlen(msg + sizeof(prio)) + 1; 4082b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn names = calloc(1, sizeof(*names) + len); 4092b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn if (!names) { 4102b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn ret = -ENOMEM; 4112b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn break; 4122b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn } 4132b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn strcpy(names->name, msg + sizeof(prio)); 4142b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn names->id = transp.logMsg.entry.lid; 4152b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn names->prio = *msg; 4162b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn list_init(&names->content); 4172b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn /* 4182b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn * Insert in reverse numeric _then_ alpha sorted order as 4192b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn * representative of log rotation: 4202b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn * 4212b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn * log.10 4222b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn * klog.10 4232b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn * . . . 4242b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn * log.2 4252b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn * klog.2 4262b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn * log.1 4272b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn * klog.1 4282b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn * log 4292b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn * klog 4302b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn * 4312b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn * thus when we present the content, we are provided the oldest 4322b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn * first, which when 'refreshed' could spill off the end of the 4332b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn * pmsg FIFO but retaining the newest data for last with best 4342b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn * chances to survive. 4352b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn */ 4362b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn nl = 0; 4372b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn cp = strpbrk(names->name, numbers); 4382b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn if (cp) { 4392b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn nl = strtoull(cp, NULL, 10); 4402b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn } 4412b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn list_for_each_reverse(node, &name_list) { 4422b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn struct names *a_name = node_to_item(node, struct names, node); 4432b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn const char *r = a_name->name; 4442b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn int compare = 0; 4452b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn 4462b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn unsigned long long nr = 0; 4472b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn cp = strpbrk(r, numbers); 4482b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn if (cp) { 4492b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn nr = strtoull(cp, NULL, 10); 4502b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn } 4512b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn if (nr != nl) { 4522b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn compare = (nl > nr) ? 1 : -1; 4532b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn } 4542b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn if (compare == 0) { 4552b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn compare = strcmp(names->name, r); 4562b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn } 4572b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn if (compare <= 0) { 4582b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn break; 4592b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn } 4602b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn } 4612b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn list_add_head(node, &names->node); 4622b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn } 4632b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn 4642b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn /* Remove any file fragments that match our sequence number */ 4652b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn list_for_each_safe(node, n, &names->content) { 4662b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn content = node_to_item(node, struct content, node); 4672b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn if (transp.logMsg.entry.nsec == content->entry.nsec) { 4682b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn list_remove(&content->node); 4692b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn free(content); 4702b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn } 4712b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn } 4722b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn 4732b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn /* Add content */ 4742b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn content = calloc(1, sizeof(content->node) + 4752b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn hdr_size + transp.logMsg.entry.len); 4762b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn if (!content) { 4772b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn ret = -ENOMEM; 4782b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn break; 4792b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn } 4802b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn memcpy(&content->entry, &transp.logMsg.entry, 4812b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn hdr_size + transp.logMsg.entry.len); 4822b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn 4832b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn /* Insert in sequence number sorted order, to ease reconstruction */ 4842b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn list_for_each_reverse(node, &names->content) { 4852b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn if ((node_to_item(node, struct content, node))->entry.nsec < 4862b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn transp.logMsg.entry.nsec) { 4872b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn break; 4882b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn } 4892b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn } 4902b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn list_add_head(node, &content->node); 4912b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn } 4922b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn pmsgClose(&logger_list, &transp); 4932b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn 4942b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn /* Progress through all the collected files */ 4952b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn list_for_each_safe(node, n, &name_list) { 4962b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn struct listnode *content_node, *m; 4972b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn char *buf; 4982b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn size_t sequence, tag_len; 4992b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn 5002b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn names = node_to_item(node, struct names, node); 5012b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn 5022b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn /* Construct content into a linear buffer */ 5032b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn buf = NULL; 5042b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn len = 0; 5052b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn sequence = 0; 5062b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn tag_len = strlen(names->name) + sizeof(char); /* tag + nul */ 5072b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn list_for_each_safe(content_node, m, &names->content) { 5082b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn ssize_t add_len; 5092b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn 5102b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn content = node_to_item(content_node, struct content, node); 5112b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn add_len = content->entry.len - tag_len - sizeof(prio); 5122b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn if (add_len <= 0) { 5132b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn list_remove(content_node); 5142b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn free(content); 5152b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn continue; 5162b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn } 5172b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn 5182b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn if (!buf) { 5192b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn buf = malloc(sizeof(char)); 5202b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn if (!buf) { 5212b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn ret = -ENOMEM; 5222b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn list_remove(content_node); 5232b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn free(content); 5242b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn continue; 5252b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn } 5262b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn *buf = '\0'; 5272b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn } 5282b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn 5292b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn /* Missing sequence numbers */ 5302b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn while (sequence < content->entry.nsec) { 5312b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn /* plus space for enforced nul */ 5322b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn buf = realloc(buf, len + sizeof(char) + sizeof(char)); 5332b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn if (!buf) { 5342b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn break; 5352b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn } 5362b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn buf[len] = '\f'; /* Mark missing content with a form feed */ 5372b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn buf[++len] = '\0'; 5382b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn sequence += ANDROID_LOG_PMSG_FILE_SEQUENCE; 5392b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn } 5402b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn if (!buf) { 5412b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn ret = -ENOMEM; 5422b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn list_remove(content_node); 5432b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn free(content); 5442b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn continue; 5452b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn } 5462b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn /* plus space for enforced nul */ 5472b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn buf = realloc(buf, len + add_len + sizeof(char)); 5482b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn if (!buf) { 5492b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn ret = -ENOMEM; 5502b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn list_remove(content_node); 5512b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn free(content); 5522b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn continue; 5532b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn } 5542b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn memcpy(buf + len, 5552b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn (char *)&content->entry + content->entry.hdr_size + 5562b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn tag_len + sizeof(prio), 5572b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn add_len); 5582b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn len += add_len; 5592b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn buf[len] = '\0'; /* enforce trailing hidden nul */ 5602b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn sequence = content->entry.nsec + ANDROID_LOG_PMSG_FILE_SEQUENCE; 5612b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn 5622b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn list_remove(content_node); 5632b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn free(content); 5642b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn } 5652b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn if (buf) { 5662b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn if (len) { 5672b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn /* Buffer contains enforced trailing nul just beyond length */ 5682b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn ssize_t r; 5692b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn *strchr(names->name, ':') = '/'; /* Convert back to filename */ 5702b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn r = (*fn)(names->id, names->prio, names->name, buf, len, arg); 5712b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn if ((ret >= 0) && (r > 0)) { 5722b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn if (ret == SSIZE_MAX) { 5732b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn ret = r; 5742b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn } else { 5752b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn ret += r; 5762b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn } 5772b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn } else if (r < ret) { 5782b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn ret = r; 5792b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn } 5802b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn } 5812b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn free(buf); 5822b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn } 5832b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn list_remove(node); 5842b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn free(names); 5852b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn } 5862b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn return (ret == SSIZE_MAX) ? -ENOENT : ret; 5872b8157d9fd2a3dcb7370fe2614e2c47315186519Mark Salyzyn} 588