📄 logcat.cpp
字号:
// Copyright 2006 The Android Open Source Project#include <utils/misc.h>#include <utils/logger.h>#include <cutils/logd.h>#include <cutils/sockets.h>#include <cutils/logprint.h>#include <cutils/event_tag_map.h>#include <stdio.h>#include <stdlib.h>#include <stdarg.h>#include <string.h>#include <unistd.h>#include <fcntl.h>#include <time.h>#include <errno.h>#include <assert.h>#include <ctype.h>#include <sys/socket.h>#include <sys/stat.h>#include <arpa/inet.h>#define DEFAULT_LOG_ROTATE_SIZE_KBYTES 16#define DEFAULT_MAX_ROTATED_LOGS 4static AndroidLogFormat * g_logformat;/* logd prefixes records with a length field */#define RECORD_LENGTH_FIELD_SIZE_BYTES sizeof(uint32_t)#define LOG_FILE_DIR "/dev/log/"namespace android {/* Global Variables */static const char * g_outputFileName = NULL;static int g_logRotateSizeKBytes = 0; // 0 means "no log rotation"static int g_maxRotatedLogs = DEFAULT_MAX_ROTATED_LOGS; // 0 means "unbounded"static int g_outFD = -1;static off_t g_outByteCount = 0;static int g_isBinary = 0;static int g_printBinary = 0;static EventTagMap* g_eventTagMap = NULL;static int openLogFile (const char *pathname){ return open(g_outputFileName, O_WRONLY | O_APPEND | O_CREAT, S_IRUSR | S_IWUSR);}static void rotateLogs(){ int err; // Can't rotate logs if we're not outputting to a file if (g_outputFileName == NULL) { return; } close(g_outFD); for (int i = g_maxRotatedLogs ; i > 0 ; i--) { char *file0, *file1; asprintf(&file1, "%s.%d", g_outputFileName, i); if (i - 1 == 0) { asprintf(&file0, "%s", g_outputFileName); } else { asprintf(&file0, "%s.%d", g_outputFileName, i - 1); } err = rename (file0, file1); if (err < 0 && errno != ENOENT) { perror("while rotating log files"); } free(file1); free(file0); } g_outFD = openLogFile (g_outputFileName); if (g_outFD < 0) { perror ("couldn't open output file"); exit(-1); } g_outByteCount = 0;}void printBinary(struct logger_entry *buf){ size_t size = sizeof(logger_entry) + buf->len; int ret; do { ret = write(g_outFD, buf, size); } while (ret < 0 && errno == EINTR);}static void processBuffer(struct logger_entry *buf){ int bytesWritten; int err; AndroidLogEntry entry; char binaryMsgBuf[1024]; if (g_isBinary) { err = android_log_processBinaryLogBuffer(buf, &entry, g_eventTagMap, binaryMsgBuf, sizeof(binaryMsgBuf)); //printf(">>> pri=%d len=%d msg='%s'\n", // entry.priority, entry.messageLen, entry.message); } else { err = android_log_processLogBuffer(buf, &entry); } if (err < 0) goto error; bytesWritten = android_log_filterAndPrintLogLine( g_logformat, g_outFD, &entry); if (bytesWritten < 0) { perror("output error"); exit(-1); } g_outByteCount += bytesWritten; if (g_logRotateSizeKBytes > 0 && (g_outByteCount / 1024) >= g_logRotateSizeKBytes ) { rotateLogs(); }error: //fprintf (stderr, "Error processing record\n"); return;}static void readLogLines(int logfd){ while (1) { unsigned char buf[LOGGER_ENTRY_MAX_LEN + 1] __attribute__((aligned(4))); struct logger_entry *entry = (struct logger_entry *) buf; int ret; ret = read(logfd, entry, LOGGER_ENTRY_MAX_LEN); if (ret < 0) { if (errno == EINTR) continue; if (errno == EAGAIN) break; perror("logcat read"); exit(EXIT_FAILURE); } else if (!ret) { fprintf(stderr, "read: Unexpected EOF!\n"); exit(EXIT_FAILURE); } /* NOTE: driver guarantees we read exactly one full entry */ entry->msg[entry->len] = '\0'; if (g_printBinary) { printBinary(entry); } else { (void) processBuffer(entry); } }}static int clearLog(int logfd){ return ioctl(logfd, LOGGER_FLUSH_LOG);}/* returns the total size of the log's ring buffer */static int getLogSize(int logfd){ return ioctl(logfd, LOGGER_GET_LOG_BUF_SIZE);}/* returns the readable size of the log's ring buffer (that is, amount of the log consumed) */static int getLogReadableSize(int logfd){ return ioctl(logfd, LOGGER_GET_LOG_LEN);}static void setupOutput(){ if (g_outputFileName == NULL) { g_outFD = STDOUT_FILENO; } else { struct stat statbuf; g_outFD = openLogFile (g_outputFileName); if (g_outFD < 0) { perror ("couldn't open output file"); exit(-1); } fstat(g_outFD, &statbuf); g_outByteCount = statbuf.st_size; }}static void show_help(const char *cmd){ fprintf(stderr,"Usage: %s [options] [filterspecs]\n", cmd); fprintf(stderr, "options include:\n" " -s Set default filter to silent.\n" " Like specifying filterspec '*:s'\n" " -f <filename> Log to file. Default to stdout\n" " -r [<kbytes>] Rotate log every kbytes. (16 if unspecified). Requires -f\n" " -n <count> Sets max number of rotated logs to <count>, default 4\n" " -v <format> Sets the log print format, where <format> is one of:\n\n" " brief process tag thread raw time threadtime long\n\n" " -c clear (flush) the entire log and exit\n" " -d dump the log and then exit (don't block)\n" " -g get the size of the log's ring buffer and exit\n" " -b <buffer> request alternate ring buffer\n" " ('main' (default), 'radio', 'events')\n" " -B output the log in binary"); fprintf(stderr,"\nfilterspecs are a series of \n" " <tag>[:priority]\n\n" "where <tag> is a log component tag (or * for all) and priority is:\n" " V Verbose\n" " D Debug\n" " I Info\n" " W Warn\n" " E Error\n" " F Fatal\n" " S Silent (supress all output)\n" "\n'*' means '*:d' and <tag> by itself means <tag>:v\n" "\nIf not specified on the commandline, filterspec is set from ANDROID_LOG_TAGS.\n" "If no filterspec is found, filter defaults to '*:I'\n" "\nIf not specified with -v, format is set from ANDROID_PRINTF_LOG\n" "or defaults to \"brief\"\n\n");}} /* namespace android */static int setLogFormat(const char * formatString){ static AndroidLogPrintFormat format; format = android_log_formatFromString(formatString); if (format == FORMAT_OFF) { // FORMAT_OFF means invalid string return -1; } android_log_setPrintFormat(g_logformat, format); return 0;}extern "C" void logprint_run_tests(void);int main (int argc, char **argv){ int logfd; int err; int hasSetLogFormat = 0; int clearLog = 0; int getLogSize = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -