static int __write_to_log_init(log_id_t log_id, struct iovec *vec, size_t nr) { DECLARE_SIGSET(sigflags); lock(&sigflags); if (write_to_log == __write_to_log_init) { int ret; ret = __write_to_log_initialize(); if (ret < 0) { unlock(&sigflags); #if (FAKE_LOG_DEVICE == 0) if (pstore_fd >= 0) { __write_to_log_daemon(log_id, vec, nr); } #endif return ret; } write_to_log = __write_to_log_daemon; } unlock(&sigflags); return write_to_log(log_id, vec, nr); }
static int __write_to_log_init(log_id_t log_id, struct iovec *vec, size_t nr) { #if !defined(_WIN32) pthread_mutex_lock(&log_init_lock); #endif if (write_to_log == __write_to_log_init) { int ret; ret = __write_to_log_initialize(); if (ret < 0) { #if !defined(_WIN32) pthread_mutex_unlock(&log_init_lock); #endif #if (FAKE_LOG_DEVICE == 0) if (pstore_fd >= 0) { __write_to_log_daemon(log_id, vec, nr); } #endif return ret; } write_to_log = __write_to_log_daemon; } #if !defined(_WIN32) pthread_mutex_unlock(&log_init_lock); #endif return write_to_log(log_id, vec, nr); }
static int __write_to_log_daemon(log_id_t log_id, struct iovec *vec, size_t nr) { ssize_t ret; #if FAKE_LOG_DEVICE int log_fd; if (/*(int)log_id >= 0 &&*/ (int)log_id < (int)LOG_ID_MAX) { log_fd = log_fds[(int)log_id]; } else { return -EBADF; } do { ret = fakeLogWritev(log_fd, vec, nr); if (ret < 0) { ret = -errno; } } while (ret == -EINTR); #else static const unsigned header_length = 2; struct iovec newVec[nr + header_length]; android_log_header_t header; android_pmsg_log_header_t pmsg_header; struct timespec ts; size_t i, payload_size; static uid_t last_uid = AID_ROOT; /* logd *always* starts up as AID_ROOT */ static pid_t last_pid = (pid_t) -1; static atomic_int_fast32_t dropped; if (!nr) { return -EINVAL; } if (last_uid == AID_ROOT) { /* have we called to get the UID yet? */ last_uid = getuid(); } if (last_pid == (pid_t) -1) { last_pid = getpid(); } /* * struct { * // what we provide to pstore * android_pmsg_log_header_t pmsg_header; * // what we provide to socket * android_log_header_t header; * // caller provides * union { * struct { * char prio; * char payload[]; * } string; * struct { * uint32_t tag * char payload[]; * } binary; * }; * }; */ if (android_log_timestamp() == 'm') { clock_gettime(CLOCK_MONOTONIC, &ts); } else { clock_gettime(CLOCK_REALTIME, &ts); } pmsg_header.magic = LOGGER_MAGIC; pmsg_header.len = sizeof(pmsg_header) + sizeof(header); pmsg_header.uid = last_uid; pmsg_header.pid = last_pid; header.tid = gettid(); header.realtime.tv_sec = ts.tv_sec; header.realtime.tv_nsec = ts.tv_nsec; newVec[0].iov_base = (unsigned char *) &pmsg_header; newVec[0].iov_len = sizeof(pmsg_header); newVec[1].iov_base = (unsigned char *) &header; newVec[1].iov_len = sizeof(header); if (logd_fd > 0) { int32_t snapshot = atomic_exchange_explicit(&dropped, 0, memory_order_relaxed); if (snapshot) { android_log_event_int_t buffer; header.id = LOG_ID_EVENTS; buffer.header.tag = htole32(LIBLOG_LOG_TAG); buffer.payload.type = EVENT_TYPE_INT; buffer.payload.data = htole32(snapshot); newVec[2].iov_base = &buffer; newVec[2].iov_len = sizeof(buffer); ret = TEMP_FAILURE_RETRY(writev(logd_fd, newVec + 1, 2)); if (ret != (ssize_t)(sizeof(header) + sizeof(buffer))) { atomic_fetch_add_explicit(&dropped, snapshot, memory_order_relaxed); } } } header.id = log_id; for (payload_size = 0, i = header_length; i < nr + header_length; i++) { newVec[i].iov_base = vec[i - header_length].iov_base; payload_size += newVec[i].iov_len = vec[i - header_length].iov_len; if (payload_size > LOGGER_ENTRY_MAX_PAYLOAD) { newVec[i].iov_len -= payload_size - LOGGER_ENTRY_MAX_PAYLOAD; if (newVec[i].iov_len) { ++i; } payload_size = LOGGER_ENTRY_MAX_PAYLOAD; break; } } pmsg_header.len += payload_size; if (pstore_fd >= 0) { TEMP_FAILURE_RETRY(writev(pstore_fd, newVec, i)); } if (last_uid == AID_LOGD) { /* logd, after initialization and priv drop */ /* * ignore log messages we send to ourself (logd). * Such log messages are often generated by libraries we depend on * which use standard Android logging. */ return 0; } if (logd_fd < 0) { return -EBADF; } /* * The write below could be lost, but will never block. * * To logd, we drop the pmsg_header * * ENOTCONN occurs if logd dies. * EAGAIN occurs if logd is overloaded. */ ret = TEMP_FAILURE_RETRY(writev(logd_fd, newVec + 1, i - 1)); if (ret < 0) { DECLARE_SIGSET(sigflags); ret = -errno; if (ret == -ENOTCONN) { lock(&sigflags); close(logd_fd); logd_fd = -1; ret = __write_to_log_initialize(); unlock(&sigflags); if (ret < 0) { return ret; } ret = TEMP_FAILURE_RETRY(writev(logd_fd, newVec + 1, i - 1)); if (ret < 0) { ret = -errno; } } } if (ret > (ssize_t)sizeof(header)) { ret -= sizeof(header); } else if (ret == -EAGAIN) { atomic_fetch_add_explicit(&dropped, 1, memory_order_relaxed); } #endif return ret; }