1*598139dcSAndroid Build Coastguard Worker /*
2*598139dcSAndroid Build Coastguard Worker * Copyright (C) 2006 The Android Open Source Project
3*598139dcSAndroid Build Coastguard Worker *
4*598139dcSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*598139dcSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*598139dcSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*598139dcSAndroid Build Coastguard Worker *
8*598139dcSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*598139dcSAndroid Build Coastguard Worker *
10*598139dcSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*598139dcSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*598139dcSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*598139dcSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*598139dcSAndroid Build Coastguard Worker * limitations under the License.
15*598139dcSAndroid Build Coastguard Worker */
16*598139dcSAndroid Build Coastguard Worker
17*598139dcSAndroid Build Coastguard Worker #include <ctype.h>
18*598139dcSAndroid Build Coastguard Worker #include <dirent.h>
19*598139dcSAndroid Build Coastguard Worker #include <errno.h>
20*598139dcSAndroid Build Coastguard Worker #include <error.h>
21*598139dcSAndroid Build Coastguard Worker #include <fcntl.h>
22*598139dcSAndroid Build Coastguard Worker #include <getopt.h>
23*598139dcSAndroid Build Coastguard Worker #include <linux/f2fs.h>
24*598139dcSAndroid Build Coastguard Worker #include <linux/fs.h>
25*598139dcSAndroid Build Coastguard Worker #include <malloc.h>
26*598139dcSAndroid Build Coastguard Worker #include <math.h>
27*598139dcSAndroid Build Coastguard Worker #include <sched.h>
28*598139dcSAndroid Build Coastguard Worker #include <stdarg.h>
29*598139dcSAndroid Build Coastguard Worker #include <stdio.h>
30*598139dcSAndroid Build Coastguard Worker #include <stdlib.h>
31*598139dcSAndroid Build Coastguard Worker #include <string.h>
32*598139dcSAndroid Build Coastguard Worker #include <sys/cdefs.h>
33*598139dcSAndroid Build Coastguard Worker #include <sys/ioctl.h>
34*598139dcSAndroid Build Coastguard Worker #include <sys/resource.h>
35*598139dcSAndroid Build Coastguard Worker #include <sys/stat.h>
36*598139dcSAndroid Build Coastguard Worker #include <sys/types.h>
37*598139dcSAndroid Build Coastguard Worker #include <time.h>
38*598139dcSAndroid Build Coastguard Worker #include <unistd.h>
39*598139dcSAndroid Build Coastguard Worker
40*598139dcSAndroid Build Coastguard Worker #include <memory>
41*598139dcSAndroid Build Coastguard Worker #include <regex>
42*598139dcSAndroid Build Coastguard Worker #include <set>
43*598139dcSAndroid Build Coastguard Worker #include <string>
44*598139dcSAndroid Build Coastguard Worker #include <utility>
45*598139dcSAndroid Build Coastguard Worker #include <vector>
46*598139dcSAndroid Build Coastguard Worker
47*598139dcSAndroid Build Coastguard Worker #include <android-base/file.h>
48*598139dcSAndroid Build Coastguard Worker #include <android-base/macros.h>
49*598139dcSAndroid Build Coastguard Worker #include <android-base/parseint.h>
50*598139dcSAndroid Build Coastguard Worker #include <android-base/properties.h>
51*598139dcSAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
52*598139dcSAndroid Build Coastguard Worker #include <android-base/strings.h>
53*598139dcSAndroid Build Coastguard Worker #include <android-base/unique_fd.h>
54*598139dcSAndroid Build Coastguard Worker #include <android/log.h>
55*598139dcSAndroid Build Coastguard Worker #include <log/event_tag_map.h>
56*598139dcSAndroid Build Coastguard Worker #include <log/log_id.h>
57*598139dcSAndroid Build Coastguard Worker #include <log/log_read.h>
58*598139dcSAndroid Build Coastguard Worker #include <log/logprint.h>
59*598139dcSAndroid Build Coastguard Worker #include <private/android_logger.h>
60*598139dcSAndroid Build Coastguard Worker #include <processgroup/sched_policy.h>
61*598139dcSAndroid Build Coastguard Worker #include <system/thread_defs.h>
62*598139dcSAndroid Build Coastguard Worker #include "logcat.pb.h"
63*598139dcSAndroid Build Coastguard Worker #include "process_names.h"
64*598139dcSAndroid Build Coastguard Worker
65*598139dcSAndroid Build Coastguard Worker using com::android::logcat::proto::LogcatEntryProto;
66*598139dcSAndroid Build Coastguard Worker using com::android::logcat::proto::LogcatPriorityProto;
67*598139dcSAndroid Build Coastguard Worker
68*598139dcSAndroid Build Coastguard Worker #define DEFAULT_MAX_ROTATED_LOGS 4
69*598139dcSAndroid Build Coastguard Worker
70*598139dcSAndroid Build Coastguard Worker using android::base::Join;
71*598139dcSAndroid Build Coastguard Worker using android::base::ParseByteCount;
72*598139dcSAndroid Build Coastguard Worker using android::base::ParseUint;
73*598139dcSAndroid Build Coastguard Worker using android::base::Split;
74*598139dcSAndroid Build Coastguard Worker using android::base::StringPrintf;
75*598139dcSAndroid Build Coastguard Worker using android::base::WaitForProperty;
76*598139dcSAndroid Build Coastguard Worker using android::base::WriteFully;
77*598139dcSAndroid Build Coastguard Worker
78*598139dcSAndroid Build Coastguard Worker namespace {
79*598139dcSAndroid Build Coastguard Worker enum OutputType {
80*598139dcSAndroid Build Coastguard Worker TEXT, // Human-readable formatted
81*598139dcSAndroid Build Coastguard Worker BINARY, // Raw struct log_msg as obtained from logd
82*598139dcSAndroid Build Coastguard Worker PROTO // Protobuffer format. See logcat.proto for details. Each message is prefixed with
83*598139dcSAndroid Build Coastguard Worker // 8 bytes (little endian) size of the message.
84*598139dcSAndroid Build Coastguard Worker };
85*598139dcSAndroid Build Coastguard Worker } // namespace
86*598139dcSAndroid Build Coastguard Worker
87*598139dcSAndroid Build Coastguard Worker class Logcat {
88*598139dcSAndroid Build Coastguard Worker public:
89*598139dcSAndroid Build Coastguard Worker int Run(int argc, char** argv);
90*598139dcSAndroid Build Coastguard Worker
91*598139dcSAndroid Build Coastguard Worker private:
92*598139dcSAndroid Build Coastguard Worker FILE* OpenLogFile(const char* path);
93*598139dcSAndroid Build Coastguard Worker void RotateLogs();
94*598139dcSAndroid Build Coastguard Worker void ProcessBuffer(struct log_msg* buf);
95*598139dcSAndroid Build Coastguard Worker LogcatPriorityProto GetProtoPriority(const AndroidLogEntry& entry);
96*598139dcSAndroid Build Coastguard Worker uint64_t PrintToProto(const AndroidLogEntry& entry);
97*598139dcSAndroid Build Coastguard Worker void PrintDividers(log_id_t log_id, bool print_dividers);
98*598139dcSAndroid Build Coastguard Worker void SetupOutputAndSchedulingPolicy(bool blocking);
99*598139dcSAndroid Build Coastguard Worker int SetLogFormat(const char* format_string);
WriteFully(const void * p,size_t n)100*598139dcSAndroid Build Coastguard Worker void WriteFully(const void* p, size_t n) {
101*598139dcSAndroid Build Coastguard Worker if (fwrite(p, 1, n, output_file_) != n) {
102*598139dcSAndroid Build Coastguard Worker error(EXIT_FAILURE, errno, "Write to output file failed");
103*598139dcSAndroid Build Coastguard Worker }
104*598139dcSAndroid Build Coastguard Worker }
105*598139dcSAndroid Build Coastguard Worker
106*598139dcSAndroid Build Coastguard Worker const bool kCompressLogcat = android::base::GetBoolProperty("ro.logcat.compress", false);
107*598139dcSAndroid Build Coastguard Worker
108*598139dcSAndroid Build Coastguard Worker // Used for all options
109*598139dcSAndroid Build Coastguard Worker std::unique_ptr<AndroidLogFormat, decltype(&android_log_format_free)> logformat_{
110*598139dcSAndroid Build Coastguard Worker android_log_format_new(), &android_log_format_free};
111*598139dcSAndroid Build Coastguard Worker // This isn't a unique_ptr because it's usually stdout;
112*598139dcSAndroid Build Coastguard Worker // stdio's atexit handler ensures we flush on exit.
113*598139dcSAndroid Build Coastguard Worker FILE* output_file_ = stdout;
114*598139dcSAndroid Build Coastguard Worker
115*598139dcSAndroid Build Coastguard Worker // For logging to a file and log rotation
116*598139dcSAndroid Build Coastguard Worker const char* output_file_name_ = nullptr;
117*598139dcSAndroid Build Coastguard Worker size_t log_rotate_size_kb_ = 0; // 0 means "no log rotation"
118*598139dcSAndroid Build Coastguard Worker size_t max_rotated_logs_ = DEFAULT_MAX_ROTATED_LOGS; // 0 means "unbounded"
119*598139dcSAndroid Build Coastguard Worker uint64_t out_byte_count_ = 0;
120*598139dcSAndroid Build Coastguard Worker
121*598139dcSAndroid Build Coastguard Worker enum OutputType output_type_ = TEXT;
122*598139dcSAndroid Build Coastguard Worker
123*598139dcSAndroid Build Coastguard Worker // For binary log buffers
124*598139dcSAndroid Build Coastguard Worker std::unique_ptr<EventTagMap, decltype(&android_closeEventTagMap)> event_tag_map_{
125*598139dcSAndroid Build Coastguard Worker nullptr, &android_closeEventTagMap};
126*598139dcSAndroid Build Coastguard Worker bool has_opened_event_tag_map_ = false;
127*598139dcSAndroid Build Coastguard Worker
128*598139dcSAndroid Build Coastguard Worker // For the related --regex, --max-count, --print
129*598139dcSAndroid Build Coastguard Worker std::unique_ptr<std::regex> regex_;
130*598139dcSAndroid Build Coastguard Worker size_t max_count_ = 0; // 0 means "infinite"
131*598139dcSAndroid Build Coastguard Worker size_t print_count_ = 0;
132*598139dcSAndroid Build Coastguard Worker bool print_it_anyway_ = false;
133*598139dcSAndroid Build Coastguard Worker
134*598139dcSAndroid Build Coastguard Worker // For PrintDividers()
135*598139dcSAndroid Build Coastguard Worker bool print_dividers_ = false;
136*598139dcSAndroid Build Coastguard Worker log_id_t last_printed_id_ = LOG_ID_MAX;
137*598139dcSAndroid Build Coastguard Worker bool printed_start_[LOG_ID_MAX] = {};
138*598139dcSAndroid Build Coastguard Worker
139*598139dcSAndroid Build Coastguard Worker bool debug_ = false;
140*598139dcSAndroid Build Coastguard Worker
141*598139dcSAndroid Build Coastguard Worker ProcessNames process_names_;
142*598139dcSAndroid Build Coastguard Worker };
143*598139dcSAndroid Build Coastguard Worker
startCompMode(int fd)144*598139dcSAndroid Build Coastguard Worker static void startCompMode(int fd) {
145*598139dcSAndroid Build Coastguard Worker // Ignore errors.
146*598139dcSAndroid Build Coastguard Worker long flag = FS_COMPR_FL;
147*598139dcSAndroid Build Coastguard Worker ioctl(fd, FS_IOC_SETFLAGS, &flag);
148*598139dcSAndroid Build Coastguard Worker }
149*598139dcSAndroid Build Coastguard Worker
releaseCompBlocks(const char * pathname)150*598139dcSAndroid Build Coastguard Worker static void releaseCompBlocks(const char* pathname) {
151*598139dcSAndroid Build Coastguard Worker int fd = open(pathname, O_RDONLY);
152*598139dcSAndroid Build Coastguard Worker if (fd != -1) {
153*598139dcSAndroid Build Coastguard Worker // Ignore errors.
154*598139dcSAndroid Build Coastguard Worker unsigned long long blkcnt;
155*598139dcSAndroid Build Coastguard Worker ioctl(fd, F2FS_IOC_RELEASE_COMPRESS_BLOCKS, &blkcnt);
156*598139dcSAndroid Build Coastguard Worker close(fd);
157*598139dcSAndroid Build Coastguard Worker }
158*598139dcSAndroid Build Coastguard Worker }
159*598139dcSAndroid Build Coastguard Worker
OpenLogFile(const char * path)160*598139dcSAndroid Build Coastguard Worker FILE* Logcat::OpenLogFile(const char* path) {
161*598139dcSAndroid Build Coastguard Worker int fd = open(path, O_WRONLY | O_APPEND | O_CREAT | O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP);
162*598139dcSAndroid Build Coastguard Worker if (fd == -1) {
163*598139dcSAndroid Build Coastguard Worker error(EXIT_FAILURE, errno, "couldn't open output file '%s'", path);
164*598139dcSAndroid Build Coastguard Worker }
165*598139dcSAndroid Build Coastguard Worker if (kCompressLogcat) {
166*598139dcSAndroid Build Coastguard Worker startCompMode(fd);
167*598139dcSAndroid Build Coastguard Worker }
168*598139dcSAndroid Build Coastguard Worker return fdopen(fd, "w");
169*598139dcSAndroid Build Coastguard Worker }
170*598139dcSAndroid Build Coastguard Worker
RotateLogs()171*598139dcSAndroid Build Coastguard Worker void Logcat::RotateLogs() {
172*598139dcSAndroid Build Coastguard Worker // Can't rotate logs if we're not outputting to a file
173*598139dcSAndroid Build Coastguard Worker if (!output_file_name_) return;
174*598139dcSAndroid Build Coastguard Worker
175*598139dcSAndroid Build Coastguard Worker fclose(output_file_);
176*598139dcSAndroid Build Coastguard Worker output_file_ = nullptr;
177*598139dcSAndroid Build Coastguard Worker
178*598139dcSAndroid Build Coastguard Worker if (kCompressLogcat) {
179*598139dcSAndroid Build Coastguard Worker releaseCompBlocks(output_file_name_);
180*598139dcSAndroid Build Coastguard Worker }
181*598139dcSAndroid Build Coastguard Worker
182*598139dcSAndroid Build Coastguard Worker // Compute the maximum number of digits needed to count up to
183*598139dcSAndroid Build Coastguard Worker // maxRotatedLogs in decimal. eg:
184*598139dcSAndroid Build Coastguard Worker // maxRotatedLogs == 30
185*598139dcSAndroid Build Coastguard Worker // -> log10(30) == 1.477
186*598139dcSAndroid Build Coastguard Worker // -> maxRotationCountDigits == 2
187*598139dcSAndroid Build Coastguard Worker int max_rotation_count_digits =
188*598139dcSAndroid Build Coastguard Worker max_rotated_logs_ > 0 ? (int)(floor(log10(max_rotated_logs_) + 1)) : 0;
189*598139dcSAndroid Build Coastguard Worker
190*598139dcSAndroid Build Coastguard Worker for (int i = max_rotated_logs_; i > 0; i--) {
191*598139dcSAndroid Build Coastguard Worker std::string file1 =
192*598139dcSAndroid Build Coastguard Worker StringPrintf("%s.%.*d", output_file_name_, max_rotation_count_digits, i);
193*598139dcSAndroid Build Coastguard Worker
194*598139dcSAndroid Build Coastguard Worker std::string file0;
195*598139dcSAndroid Build Coastguard Worker if (!(i - 1)) {
196*598139dcSAndroid Build Coastguard Worker file0 = output_file_name_;
197*598139dcSAndroid Build Coastguard Worker } else {
198*598139dcSAndroid Build Coastguard Worker file0 = StringPrintf("%s.%.*d", output_file_name_, max_rotation_count_digits, i - 1);
199*598139dcSAndroid Build Coastguard Worker }
200*598139dcSAndroid Build Coastguard Worker
201*598139dcSAndroid Build Coastguard Worker if (!file0.length() || !file1.length()) {
202*598139dcSAndroid Build Coastguard Worker perror("while rotating log files");
203*598139dcSAndroid Build Coastguard Worker break;
204*598139dcSAndroid Build Coastguard Worker }
205*598139dcSAndroid Build Coastguard Worker
206*598139dcSAndroid Build Coastguard Worker if (rename(file0.c_str(), file1.c_str()) == -1 && errno != ENOENT) {
207*598139dcSAndroid Build Coastguard Worker error(0, errno, "rename('%s', '%s') failed while rotating log files", file0.c_str(),
208*598139dcSAndroid Build Coastguard Worker file1.c_str());
209*598139dcSAndroid Build Coastguard Worker }
210*598139dcSAndroid Build Coastguard Worker }
211*598139dcSAndroid Build Coastguard Worker
212*598139dcSAndroid Build Coastguard Worker output_file_ = OpenLogFile(output_file_name_);
213*598139dcSAndroid Build Coastguard Worker out_byte_count_ = 0;
214*598139dcSAndroid Build Coastguard Worker }
215*598139dcSAndroid Build Coastguard Worker
ProcessBuffer(struct log_msg * buf)216*598139dcSAndroid Build Coastguard Worker void Logcat::ProcessBuffer(struct log_msg* buf) {
217*598139dcSAndroid Build Coastguard Worker AndroidLogEntry entry;
218*598139dcSAndroid Build Coastguard Worker char binaryMsgBuf[1024] __attribute__((__uninitialized__));
219*598139dcSAndroid Build Coastguard Worker
220*598139dcSAndroid Build Coastguard Worker bool is_binary =
221*598139dcSAndroid Build Coastguard Worker buf->id() == LOG_ID_EVENTS || buf->id() == LOG_ID_STATS || buf->id() == LOG_ID_SECURITY;
222*598139dcSAndroid Build Coastguard Worker int err;
223*598139dcSAndroid Build Coastguard Worker if (is_binary) {
224*598139dcSAndroid Build Coastguard Worker if (!event_tag_map_ && !has_opened_event_tag_map_) {
225*598139dcSAndroid Build Coastguard Worker event_tag_map_.reset(android_openEventTagMap(nullptr));
226*598139dcSAndroid Build Coastguard Worker has_opened_event_tag_map_ = true;
227*598139dcSAndroid Build Coastguard Worker }
228*598139dcSAndroid Build Coastguard Worker // This causes entry to point to binaryMsgBuf!
229*598139dcSAndroid Build Coastguard Worker err = android_log_processBinaryLogBuffer(&buf->entry, &entry, event_tag_map_.get(),
230*598139dcSAndroid Build Coastguard Worker binaryMsgBuf, sizeof(binaryMsgBuf));
231*598139dcSAndroid Build Coastguard Worker
232*598139dcSAndroid Build Coastguard Worker // printf(">>> pri=%d len=%d msg='%s'\n",
233*598139dcSAndroid Build Coastguard Worker // entry.priority, entry.messageLen, entry.message);
234*598139dcSAndroid Build Coastguard Worker } else {
235*598139dcSAndroid Build Coastguard Worker err = android_log_processLogBuffer(&buf->entry, &entry);
236*598139dcSAndroid Build Coastguard Worker }
237*598139dcSAndroid Build Coastguard Worker if (err < 0 && !debug_) return;
238*598139dcSAndroid Build Coastguard Worker
239*598139dcSAndroid Build Coastguard Worker if (android_log_shouldPrintLine(logformat_.get(), std::string(entry.tag, entry.tagLen).c_str(),
240*598139dcSAndroid Build Coastguard Worker entry.priority)) {
241*598139dcSAndroid Build Coastguard Worker bool match = !regex_ ||
242*598139dcSAndroid Build Coastguard Worker std::regex_search(entry.message, entry.message + entry.messageLen, *regex_);
243*598139dcSAndroid Build Coastguard Worker
244*598139dcSAndroid Build Coastguard Worker print_count_ += match;
245*598139dcSAndroid Build Coastguard Worker if (match || print_it_anyway_) {
246*598139dcSAndroid Build Coastguard Worker switch (output_type_) {
247*598139dcSAndroid Build Coastguard Worker case TEXT: {
248*598139dcSAndroid Build Coastguard Worker PrintDividers(buf->id(), print_dividers_);
249*598139dcSAndroid Build Coastguard Worker out_byte_count_ +=
250*598139dcSAndroid Build Coastguard Worker android_log_printLogLine(logformat_.get(), output_file_, &entry);
251*598139dcSAndroid Build Coastguard Worker break;
252*598139dcSAndroid Build Coastguard Worker }
253*598139dcSAndroid Build Coastguard Worker case PROTO: {
254*598139dcSAndroid Build Coastguard Worker out_byte_count_ += PrintToProto(entry);
255*598139dcSAndroid Build Coastguard Worker break;
256*598139dcSAndroid Build Coastguard Worker }
257*598139dcSAndroid Build Coastguard Worker case BINARY: {
258*598139dcSAndroid Build Coastguard Worker error(EXIT_FAILURE, errno, "Binary output reached ProcessBuffer");
259*598139dcSAndroid Build Coastguard Worker }
260*598139dcSAndroid Build Coastguard Worker }
261*598139dcSAndroid Build Coastguard Worker }
262*598139dcSAndroid Build Coastguard Worker }
263*598139dcSAndroid Build Coastguard Worker
264*598139dcSAndroid Build Coastguard Worker if (log_rotate_size_kb_ > 0 && (out_byte_count_ / 1024) >= log_rotate_size_kb_) {
265*598139dcSAndroid Build Coastguard Worker RotateLogs();
266*598139dcSAndroid Build Coastguard Worker }
267*598139dcSAndroid Build Coastguard Worker }
268*598139dcSAndroid Build Coastguard Worker
GetProtoPriority(const AndroidLogEntry & entry)269*598139dcSAndroid Build Coastguard Worker LogcatPriorityProto Logcat::GetProtoPriority(const AndroidLogEntry& entry) {
270*598139dcSAndroid Build Coastguard Worker switch (entry.priority) {
271*598139dcSAndroid Build Coastguard Worker case ANDROID_LOG_UNKNOWN:
272*598139dcSAndroid Build Coastguard Worker return com::android::logcat::proto::UNKNOWN;
273*598139dcSAndroid Build Coastguard Worker case ANDROID_LOG_DEFAULT:
274*598139dcSAndroid Build Coastguard Worker return com::android::logcat::proto::DEFAULT;
275*598139dcSAndroid Build Coastguard Worker case ANDROID_LOG_VERBOSE:
276*598139dcSAndroid Build Coastguard Worker return com::android::logcat::proto::VERBOSE;
277*598139dcSAndroid Build Coastguard Worker case ANDROID_LOG_DEBUG:
278*598139dcSAndroid Build Coastguard Worker return com::android::logcat::proto::DEBUG;
279*598139dcSAndroid Build Coastguard Worker case ANDROID_LOG_INFO:
280*598139dcSAndroid Build Coastguard Worker return com::android::logcat::proto::INFO;
281*598139dcSAndroid Build Coastguard Worker case ANDROID_LOG_WARN:
282*598139dcSAndroid Build Coastguard Worker return com::android::logcat::proto::WARN;
283*598139dcSAndroid Build Coastguard Worker case ANDROID_LOG_ERROR:
284*598139dcSAndroid Build Coastguard Worker return com::android::logcat::proto::ERROR;
285*598139dcSAndroid Build Coastguard Worker case ANDROID_LOG_FATAL:
286*598139dcSAndroid Build Coastguard Worker return com::android::logcat::proto::FATAL;
287*598139dcSAndroid Build Coastguard Worker case ANDROID_LOG_SILENT:
288*598139dcSAndroid Build Coastguard Worker return com::android::logcat::proto::SILENT;
289*598139dcSAndroid Build Coastguard Worker }
290*598139dcSAndroid Build Coastguard Worker return com::android::logcat::proto::UNKNOWN;
291*598139dcSAndroid Build Coastguard Worker }
PrintToProto(const AndroidLogEntry & entry)292*598139dcSAndroid Build Coastguard Worker uint64_t Logcat::PrintToProto(const AndroidLogEntry& entry) {
293*598139dcSAndroid Build Coastguard Worker // Convert AndroidLogEntry to LogcatEntryProto
294*598139dcSAndroid Build Coastguard Worker LogcatEntryProto proto;
295*598139dcSAndroid Build Coastguard Worker proto.set_time_sec(entry.tv_sec);
296*598139dcSAndroid Build Coastguard Worker proto.set_time_nsec(entry.tv_nsec);
297*598139dcSAndroid Build Coastguard Worker proto.set_priority(GetProtoPriority(entry));
298*598139dcSAndroid Build Coastguard Worker proto.set_uid(entry.uid);
299*598139dcSAndroid Build Coastguard Worker proto.set_pid(entry.pid);
300*598139dcSAndroid Build Coastguard Worker proto.set_tid(entry.tid);
301*598139dcSAndroid Build Coastguard Worker proto.set_tag(entry.tag, entry.tagLen);
302*598139dcSAndroid Build Coastguard Worker proto.set_message(entry.message, entry.messageLen);
303*598139dcSAndroid Build Coastguard Worker const std::string name = process_names_.Get(entry.pid);
304*598139dcSAndroid Build Coastguard Worker if (!name.empty()) {
305*598139dcSAndroid Build Coastguard Worker proto.set_process_name(name);
306*598139dcSAndroid Build Coastguard Worker }
307*598139dcSAndroid Build Coastguard Worker
308*598139dcSAndroid Build Coastguard Worker // Serialize
309*598139dcSAndroid Build Coastguard Worker std::string data;
310*598139dcSAndroid Build Coastguard Worker proto.SerializeToString(&data);
311*598139dcSAndroid Build Coastguard Worker
312*598139dcSAndroid Build Coastguard Worker uint64_t size = data.length();
313*598139dcSAndroid Build Coastguard Worker WriteFully(&size, sizeof(size));
314*598139dcSAndroid Build Coastguard Worker
315*598139dcSAndroid Build Coastguard Worker // Write proto
316*598139dcSAndroid Build Coastguard Worker WriteFully(data.data(), data.length());
317*598139dcSAndroid Build Coastguard Worker
318*598139dcSAndroid Build Coastguard Worker // Return how many bytes we wrote so log file rotation can happen
319*598139dcSAndroid Build Coastguard Worker return sizeof(size) + sizeof(data.length());
320*598139dcSAndroid Build Coastguard Worker }
321*598139dcSAndroid Build Coastguard Worker
PrintDividers(log_id_t log_id,bool print_dividers)322*598139dcSAndroid Build Coastguard Worker void Logcat::PrintDividers(log_id_t log_id, bool print_dividers) {
323*598139dcSAndroid Build Coastguard Worker if (log_id == last_printed_id_) {
324*598139dcSAndroid Build Coastguard Worker return;
325*598139dcSAndroid Build Coastguard Worker }
326*598139dcSAndroid Build Coastguard Worker if (!printed_start_[log_id] || print_dividers) {
327*598139dcSAndroid Build Coastguard Worker if (fprintf(output_file_, "--------- %s %s\n",
328*598139dcSAndroid Build Coastguard Worker printed_start_[log_id] ? "switch to" : "beginning of",
329*598139dcSAndroid Build Coastguard Worker android_log_id_to_name(log_id)) < 0) {
330*598139dcSAndroid Build Coastguard Worker error(EXIT_FAILURE, errno, "Output error");
331*598139dcSAndroid Build Coastguard Worker }
332*598139dcSAndroid Build Coastguard Worker }
333*598139dcSAndroid Build Coastguard Worker last_printed_id_ = log_id;
334*598139dcSAndroid Build Coastguard Worker printed_start_[log_id] = true;
335*598139dcSAndroid Build Coastguard Worker }
336*598139dcSAndroid Build Coastguard Worker
SetupOutputAndSchedulingPolicy(bool blocking)337*598139dcSAndroid Build Coastguard Worker void Logcat::SetupOutputAndSchedulingPolicy(bool blocking) {
338*598139dcSAndroid Build Coastguard Worker if (!output_file_name_) return;
339*598139dcSAndroid Build Coastguard Worker
340*598139dcSAndroid Build Coastguard Worker if (blocking) {
341*598139dcSAndroid Build Coastguard Worker // Lower priority and set to batch scheduling if we are saving
342*598139dcSAndroid Build Coastguard Worker // the logs into files and taking continuous content.
343*598139dcSAndroid Build Coastguard Worker if (set_sched_policy(0, SP_BACKGROUND) < 0) {
344*598139dcSAndroid Build Coastguard Worker fprintf(stderr, "failed to set background scheduling policy\n");
345*598139dcSAndroid Build Coastguard Worker }
346*598139dcSAndroid Build Coastguard Worker
347*598139dcSAndroid Build Coastguard Worker struct sched_param param = {};
348*598139dcSAndroid Build Coastguard Worker if (sched_setscheduler((pid_t)0, SCHED_BATCH, ¶m) < 0) {
349*598139dcSAndroid Build Coastguard Worker fprintf(stderr, "failed to set to batch scheduler\n");
350*598139dcSAndroid Build Coastguard Worker }
351*598139dcSAndroid Build Coastguard Worker
352*598139dcSAndroid Build Coastguard Worker if (setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_BACKGROUND) < 0) {
353*598139dcSAndroid Build Coastguard Worker fprintf(stderr, "failed set to priority\n");
354*598139dcSAndroid Build Coastguard Worker }
355*598139dcSAndroid Build Coastguard Worker }
356*598139dcSAndroid Build Coastguard Worker
357*598139dcSAndroid Build Coastguard Worker output_file_ = OpenLogFile(output_file_name_);
358*598139dcSAndroid Build Coastguard Worker
359*598139dcSAndroid Build Coastguard Worker struct stat sb;
360*598139dcSAndroid Build Coastguard Worker if (fstat(fileno(output_file_), &sb) == -1) {
361*598139dcSAndroid Build Coastguard Worker error(EXIT_FAILURE, errno, "Couldn't stat output file");
362*598139dcSAndroid Build Coastguard Worker }
363*598139dcSAndroid Build Coastguard Worker out_byte_count_ = sb.st_size;
364*598139dcSAndroid Build Coastguard Worker }
365*598139dcSAndroid Build Coastguard Worker
366*598139dcSAndroid Build Coastguard Worker // clang-format off
show_help()367*598139dcSAndroid Build Coastguard Worker static void show_help() {
368*598139dcSAndroid Build Coastguard Worker printf(R"logcat(
369*598139dcSAndroid Build Coastguard Worker Usage: logcat [OPTION]... [FILTERSPEC]...
370*598139dcSAndroid Build Coastguard Worker
371*598139dcSAndroid Build Coastguard Worker General options:
372*598139dcSAndroid Build Coastguard Worker
373*598139dcSAndroid Build Coastguard Worker -b BUFFER, --buffer=BUFFER
374*598139dcSAndroid Build Coastguard Worker Request alternate ring buffer(s). Options are:
375*598139dcSAndroid Build Coastguard Worker main system radio events crash default all
376*598139dcSAndroid Build Coastguard Worker Additionally, 'kernel' for userdebug and eng builds, and 'security' for
377*598139dcSAndroid Build Coastguard Worker Device Owner installations.
378*598139dcSAndroid Build Coastguard Worker Multiple -b parameters or comma separated list of buffers are
379*598139dcSAndroid Build Coastguard Worker allowed. Buffers are interleaved.
380*598139dcSAndroid Build Coastguard Worker Default is "main,system,crash,kernel".
381*598139dcSAndroid Build Coastguard Worker -c, --clear
382*598139dcSAndroid Build Coastguard Worker Clear (flush) the entire log and exit. With -f, clear the specified file
383*598139dcSAndroid Build Coastguard Worker and its related rotated log files instead. With -L, clear pstore instead.
384*598139dcSAndroid Build Coastguard Worker -d Dump the log and then exit (don't block).
385*598139dcSAndroid Build Coastguard Worker -L, --last Dump logs from prior to last reboot from pstore.
386*598139dcSAndroid Build Coastguard Worker --pid=PID Only print logs from the given pid.
387*598139dcSAndroid Build Coastguard Worker --wrap
388*598139dcSAndroid Build Coastguard Worker Sleep for 2 hours or until buffer about to wrap (whichever comes first).
389*598139dcSAndroid Build Coastguard Worker Improves efficiency of polling by providing an about-to-wrap wakeup.
390*598139dcSAndroid Build Coastguard Worker
391*598139dcSAndroid Build Coastguard Worker Formatting:
392*598139dcSAndroid Build Coastguard Worker
393*598139dcSAndroid Build Coastguard Worker -v, --format=FORMAT Sets log print format. See FORMAT below.
394*598139dcSAndroid Build Coastguard Worker -D, --dividers Print dividers between each log buffer.
395*598139dcSAndroid Build Coastguard Worker -B, --binary Output the log in binary.
396*598139dcSAndroid Build Coastguard Worker --proto Output the log in protobuffer.
397*598139dcSAndroid Build Coastguard Worker
398*598139dcSAndroid Build Coastguard Worker Output files:
399*598139dcSAndroid Build Coastguard Worker
400*598139dcSAndroid Build Coastguard Worker -f, --file=FILE Log to FILE instead of stdout.
401*598139dcSAndroid Build Coastguard Worker -r, --rotate-kbytes=N Rotate log every N KiB. Requires -f.
402*598139dcSAndroid Build Coastguard Worker -n, --rotate-count=N Sets max number of rotated logs, default 4.
403*598139dcSAndroid Build Coastguard Worker --id=<id>
404*598139dcSAndroid Build Coastguard Worker Clears the associated files if the signature <id> for logging to file
405*598139dcSAndroid Build Coastguard Worker changes.
406*598139dcSAndroid Build Coastguard Worker
407*598139dcSAndroid Build Coastguard Worker Logd control:
408*598139dcSAndroid Build Coastguard Worker
409*598139dcSAndroid Build Coastguard Worker These options send a control message to the logd daemon on device, print its
410*598139dcSAndroid Build Coastguard Worker return message if applicable, then exit. They are incompatible with -L
411*598139dcSAndroid Build Coastguard Worker because these attributes do not apply to pstore.
412*598139dcSAndroid Build Coastguard Worker
413*598139dcSAndroid Build Coastguard Worker -g, --buffer-size
414*598139dcSAndroid Build Coastguard Worker Get size of the ring buffers within logd.
415*598139dcSAndroid Build Coastguard Worker -G, --buffer-size=SIZE
416*598139dcSAndroid Build Coastguard Worker Set size of a ring buffer in logd. May suffix with K or M.
417*598139dcSAndroid Build Coastguard Worker This can individually control each buffer's size with -b.
418*598139dcSAndroid Build Coastguard Worker -p, --prune
419*598139dcSAndroid Build Coastguard Worker Get prune rules. Each rule is specified as UID, UID/PID or /PID. A
420*598139dcSAndroid Build Coastguard Worker '~' prefix indicates that elements matching the rule should be pruned
421*598139dcSAndroid Build Coastguard Worker with higher priority otherwise they're pruned with lower priority. All
422*598139dcSAndroid Build Coastguard Worker other pruning activity is oldest first. Special case ~! represents an
423*598139dcSAndroid Build Coastguard Worker automatic pruning for the noisiest UID as determined by the current
424*598139dcSAndroid Build Coastguard Worker statistics. Special case ~1000/! represents pruning of the worst PID
425*598139dcSAndroid Build Coastguard Worker within AID_SYSTEM when AID_SYSTEM is the noisiest UID.
426*598139dcSAndroid Build Coastguard Worker -P, --prune='LIST ...'
427*598139dcSAndroid Build Coastguard Worker Set prune rules, using same format as listed above. Must be quoted.
428*598139dcSAndroid Build Coastguard Worker -S, --statistics
429*598139dcSAndroid Build Coastguard Worker Output statistics. With --pid provides pid-specific stats.
430*598139dcSAndroid Build Coastguard Worker
431*598139dcSAndroid Build Coastguard Worker Filtering:
432*598139dcSAndroid Build Coastguard Worker
433*598139dcSAndroid Build Coastguard Worker -s Set default filter to silent (like filterspec '*:S').
434*598139dcSAndroid Build Coastguard Worker -e, --regex=EXPR Only print lines matching ECMAScript regex.
435*598139dcSAndroid Build Coastguard Worker -m, --max-count=N Exit after printing <count> lines.
436*598139dcSAndroid Build Coastguard Worker --print With --regex and --max-count, prints all messages
437*598139dcSAndroid Build Coastguard Worker even if they do not match the regex, but exits after
438*598139dcSAndroid Build Coastguard Worker printing max-count matching lines.
439*598139dcSAndroid Build Coastguard Worker -t N Print most recent <count> lines (implies -d).
440*598139dcSAndroid Build Coastguard Worker -T N Print most recent <count> lines (does not imply -d).
441*598139dcSAndroid Build Coastguard Worker -t TIME Print lines since specified time (implies -d).
442*598139dcSAndroid Build Coastguard Worker -T TIME Print lines since specified time (not imply -d).
443*598139dcSAndroid Build Coastguard Worker Time format is 'MM-DD hh:mm:ss.mmm...',
444*598139dcSAndroid Build Coastguard Worker 'YYYY-MM-DD hh:mm:ss.mmm...', or 'sssss.mmm...'.
445*598139dcSAndroid Build Coastguard Worker --uid=UIDS
446*598139dcSAndroid Build Coastguard Worker Only display log messages from UIDs in the comma-separated list UIDS.
447*598139dcSAndroid Build Coastguard Worker UIDs must be numeric because no name lookup is performed.
448*598139dcSAndroid Build Coastguard Worker Note that only root/log/system users can view logs from other users.
449*598139dcSAndroid Build Coastguard Worker
450*598139dcSAndroid Build Coastguard Worker FILTERSPEC:
451*598139dcSAndroid Build Coastguard Worker
452*598139dcSAndroid Build Coastguard Worker Filter specifications are a series of
453*598139dcSAndroid Build Coastguard Worker
454*598139dcSAndroid Build Coastguard Worker <tag>[:priority]
455*598139dcSAndroid Build Coastguard Worker
456*598139dcSAndroid Build Coastguard Worker where <tag> is a log component tag (or * for all) and priority is:
457*598139dcSAndroid Build Coastguard Worker
458*598139dcSAndroid Build Coastguard Worker V Verbose (default for <tag>)
459*598139dcSAndroid Build Coastguard Worker D Debug (default for '*')
460*598139dcSAndroid Build Coastguard Worker I Info
461*598139dcSAndroid Build Coastguard Worker W Warn
462*598139dcSAndroid Build Coastguard Worker E Error
463*598139dcSAndroid Build Coastguard Worker F Fatal
464*598139dcSAndroid Build Coastguard Worker S Silent (suppress all output)
465*598139dcSAndroid Build Coastguard Worker
466*598139dcSAndroid Build Coastguard Worker '*' by itself means '*:D' and <tag> by itself means <tag>:V.
467*598139dcSAndroid Build Coastguard Worker If no '*' filterspec or -s on command line, all filter defaults to '*:V'.
468*598139dcSAndroid Build Coastguard Worker '*:S <tag>' prints only <tag>, '<tag>:S' suppresses all <tag> log messages.
469*598139dcSAndroid Build Coastguard Worker
470*598139dcSAndroid Build Coastguard Worker If not specified on the command line, FILTERSPEC is $ANDROID_LOG_TAGS.
471*598139dcSAndroid Build Coastguard Worker
472*598139dcSAndroid Build Coastguard Worker FORMAT:
473*598139dcSAndroid Build Coastguard Worker
474*598139dcSAndroid Build Coastguard Worker Formats are a comma-separated sequence of verbs and adverbs.
475*598139dcSAndroid Build Coastguard Worker
476*598139dcSAndroid Build Coastguard Worker Single format verbs:
477*598139dcSAndroid Build Coastguard Worker
478*598139dcSAndroid Build Coastguard Worker brief Show priority, tag, and PID of the process issuing the message.
479*598139dcSAndroid Build Coastguard Worker long Show all metadata fields and separate messages with blank lines.
480*598139dcSAndroid Build Coastguard Worker process Show PID only.
481*598139dcSAndroid Build Coastguard Worker raw Show the raw log message with no other metadata fields.
482*598139dcSAndroid Build Coastguard Worker tag Show the priority and tag only.
483*598139dcSAndroid Build Coastguard Worker thread Show priority, PID, and TID of the thread issuing the message.
484*598139dcSAndroid Build Coastguard Worker threadtime Show the date, invocation time, priority, tag, PID, and TID of
485*598139dcSAndroid Build Coastguard Worker the thread issuing the message. (This is the default.)
486*598139dcSAndroid Build Coastguard Worker time Show the date, invocation time, priority, tag, and PID of the
487*598139dcSAndroid Build Coastguard Worker process issuing the message.
488*598139dcSAndroid Build Coastguard Worker
489*598139dcSAndroid Build Coastguard Worker Adverb modifiers can be used in combination:
490*598139dcSAndroid Build Coastguard Worker
491*598139dcSAndroid Build Coastguard Worker color Show each priority with a different color.
492*598139dcSAndroid Build Coastguard Worker descriptive Show event descriptions from event-log-tags database.
493*598139dcSAndroid Build Coastguard Worker epoch Show time as seconds since 1970-01-01 (Unix epoch).
494*598139dcSAndroid Build Coastguard Worker monotonic Show time as CPU seconds since boot.
495*598139dcSAndroid Build Coastguard Worker printable Ensure that any binary logging content is escaped.
496*598139dcSAndroid Build Coastguard Worker uid Show UID or Android ID of logged process (if permitted).
497*598139dcSAndroid Build Coastguard Worker usec Show time with microsecond precision.
498*598139dcSAndroid Build Coastguard Worker UTC Show time as UTC.
499*598139dcSAndroid Build Coastguard Worker year Add the year to the displayed time.
500*598139dcSAndroid Build Coastguard Worker zone Add the local timezone to the displayed time.
501*598139dcSAndroid Build Coastguard Worker \"<ZONE>\" Print using this named timezone (experimental).
502*598139dcSAndroid Build Coastguard Worker
503*598139dcSAndroid Build Coastguard Worker If not specified with -v on command line, FORMAT is $ANDROID_PRINTF_LOG or
504*598139dcSAndroid Build Coastguard Worker defaults to "threadtime".
505*598139dcSAndroid Build Coastguard Worker )logcat");
506*598139dcSAndroid Build Coastguard Worker }
507*598139dcSAndroid Build Coastguard Worker // clang-format on
508*598139dcSAndroid Build Coastguard Worker
SetLogFormat(const char * format_string)509*598139dcSAndroid Build Coastguard Worker int Logcat::SetLogFormat(const char* format_string) {
510*598139dcSAndroid Build Coastguard Worker AndroidLogPrintFormat format = android_log_formatFromString(format_string);
511*598139dcSAndroid Build Coastguard Worker
512*598139dcSAndroid Build Coastguard Worker // invalid string?
513*598139dcSAndroid Build Coastguard Worker if (format == FORMAT_OFF) return -1;
514*598139dcSAndroid Build Coastguard Worker
515*598139dcSAndroid Build Coastguard Worker return android_log_setPrintFormat(logformat_.get(), format);
516*598139dcSAndroid Build Coastguard Worker }
517*598139dcSAndroid Build Coastguard Worker
format_of_size(unsigned long value)518*598139dcSAndroid Build Coastguard Worker static std::pair<unsigned long, const char*> format_of_size(unsigned long value) {
519*598139dcSAndroid Build Coastguard Worker static const char multipliers[][3] = {{""}, {"Ki"}, {"Mi"}, {"Gi"}};
520*598139dcSAndroid Build Coastguard Worker size_t i;
521*598139dcSAndroid Build Coastguard Worker for (i = 0;
522*598139dcSAndroid Build Coastguard Worker (i < sizeof(multipliers) / sizeof(multipliers[0])) && (value >= 1024);
523*598139dcSAndroid Build Coastguard Worker value /= 1024, ++i)
524*598139dcSAndroid Build Coastguard Worker ;
525*598139dcSAndroid Build Coastguard Worker return std::make_pair(value, multipliers[i]);
526*598139dcSAndroid Build Coastguard Worker }
527*598139dcSAndroid Build Coastguard Worker
parseTime(log_time & t,const char * cp)528*598139dcSAndroid Build Coastguard Worker static char* parseTime(log_time& t, const char* cp) {
529*598139dcSAndroid Build Coastguard Worker char* ep = t.strptime(cp, "%m-%d %H:%M:%S.%q");
530*598139dcSAndroid Build Coastguard Worker if (ep) return ep;
531*598139dcSAndroid Build Coastguard Worker ep = t.strptime(cp, "%Y-%m-%d %H:%M:%S.%q");
532*598139dcSAndroid Build Coastguard Worker if (ep) return ep;
533*598139dcSAndroid Build Coastguard Worker return t.strptime(cp, "%s.%q");
534*598139dcSAndroid Build Coastguard Worker }
535*598139dcSAndroid Build Coastguard Worker
536*598139dcSAndroid Build Coastguard Worker // Find last logged line in <outputFileName>, or <outputFileName>.1
lastLogTime(const char * outputFileName)537*598139dcSAndroid Build Coastguard Worker static log_time lastLogTime(const char* outputFileName) {
538*598139dcSAndroid Build Coastguard Worker log_time retval(log_time::EPOCH);
539*598139dcSAndroid Build Coastguard Worker if (!outputFileName) return retval;
540*598139dcSAndroid Build Coastguard Worker
541*598139dcSAndroid Build Coastguard Worker std::string directory;
542*598139dcSAndroid Build Coastguard Worker const char* file = strrchr(outputFileName, '/');
543*598139dcSAndroid Build Coastguard Worker if (!file) {
544*598139dcSAndroid Build Coastguard Worker directory = ".";
545*598139dcSAndroid Build Coastguard Worker file = outputFileName;
546*598139dcSAndroid Build Coastguard Worker } else {
547*598139dcSAndroid Build Coastguard Worker directory = std::string(outputFileName, file - outputFileName);
548*598139dcSAndroid Build Coastguard Worker ++file;
549*598139dcSAndroid Build Coastguard Worker }
550*598139dcSAndroid Build Coastguard Worker
551*598139dcSAndroid Build Coastguard Worker std::unique_ptr<DIR, int (*)(DIR*)> dir(opendir(directory.c_str()),
552*598139dcSAndroid Build Coastguard Worker closedir);
553*598139dcSAndroid Build Coastguard Worker if (!dir.get()) return retval;
554*598139dcSAndroid Build Coastguard Worker
555*598139dcSAndroid Build Coastguard Worker log_time now(CLOCK_REALTIME);
556*598139dcSAndroid Build Coastguard Worker
557*598139dcSAndroid Build Coastguard Worker size_t len = strlen(file);
558*598139dcSAndroid Build Coastguard Worker log_time modulo(0, NS_PER_SEC);
559*598139dcSAndroid Build Coastguard Worker struct dirent* dp;
560*598139dcSAndroid Build Coastguard Worker
561*598139dcSAndroid Build Coastguard Worker while (!!(dp = readdir(dir.get()))) {
562*598139dcSAndroid Build Coastguard Worker if ((dp->d_type != DT_REG) || !!strncmp(dp->d_name, file, len) ||
563*598139dcSAndroid Build Coastguard Worker (dp->d_name[len] && ((dp->d_name[len] != '.') ||
564*598139dcSAndroid Build Coastguard Worker (strtoll(dp->d_name + 1, nullptr, 10) != 1)))) {
565*598139dcSAndroid Build Coastguard Worker continue;
566*598139dcSAndroid Build Coastguard Worker }
567*598139dcSAndroid Build Coastguard Worker
568*598139dcSAndroid Build Coastguard Worker std::string file_name = directory;
569*598139dcSAndroid Build Coastguard Worker file_name += "/";
570*598139dcSAndroid Build Coastguard Worker file_name += dp->d_name;
571*598139dcSAndroid Build Coastguard Worker std::string file;
572*598139dcSAndroid Build Coastguard Worker if (!android::base::ReadFileToString(file_name, &file)) continue;
573*598139dcSAndroid Build Coastguard Worker
574*598139dcSAndroid Build Coastguard Worker bool found = false;
575*598139dcSAndroid Build Coastguard Worker for (const auto& line : android::base::Split(file, "\n")) {
576*598139dcSAndroid Build Coastguard Worker log_time t(log_time::EPOCH);
577*598139dcSAndroid Build Coastguard Worker char* ep = parseTime(t, line.c_str());
578*598139dcSAndroid Build Coastguard Worker if (!ep || (*ep != ' ')) continue;
579*598139dcSAndroid Build Coastguard Worker // determine the time precision of the logs (eg: msec or usec)
580*598139dcSAndroid Build Coastguard Worker for (unsigned long mod = 1UL; mod < modulo.tv_nsec; mod *= 10) {
581*598139dcSAndroid Build Coastguard Worker if (t.tv_nsec % (mod * 10)) {
582*598139dcSAndroid Build Coastguard Worker modulo.tv_nsec = mod;
583*598139dcSAndroid Build Coastguard Worker break;
584*598139dcSAndroid Build Coastguard Worker }
585*598139dcSAndroid Build Coastguard Worker }
586*598139dcSAndroid Build Coastguard Worker // We filter any times later than current as we may not have the
587*598139dcSAndroid Build Coastguard Worker // year stored with each log entry. Also, since it is possible for
588*598139dcSAndroid Build Coastguard Worker // entries to be recorded out of order (very rare) we select the
589*598139dcSAndroid Build Coastguard Worker // maximum we find just in case.
590*598139dcSAndroid Build Coastguard Worker if ((t < now) && (t > retval)) {
591*598139dcSAndroid Build Coastguard Worker retval = t;
592*598139dcSAndroid Build Coastguard Worker found = true;
593*598139dcSAndroid Build Coastguard Worker }
594*598139dcSAndroid Build Coastguard Worker }
595*598139dcSAndroid Build Coastguard Worker // We count on the basename file to be the definitive end, so stop here.
596*598139dcSAndroid Build Coastguard Worker if (!dp->d_name[len] && found) break;
597*598139dcSAndroid Build Coastguard Worker }
598*598139dcSAndroid Build Coastguard Worker if (retval == log_time::EPOCH) return retval;
599*598139dcSAndroid Build Coastguard Worker // tail_time prints matching or higher, round up by the modulo to prevent
600*598139dcSAndroid Build Coastguard Worker // a replay of the last entry we have just checked.
601*598139dcSAndroid Build Coastguard Worker retval += modulo;
602*598139dcSAndroid Build Coastguard Worker return retval;
603*598139dcSAndroid Build Coastguard Worker }
604*598139dcSAndroid Build Coastguard Worker
ReportErrorName(const std::string & name,bool allow_security,std::vector<std::string> * errors)605*598139dcSAndroid Build Coastguard Worker void ReportErrorName(const std::string& name, bool allow_security,
606*598139dcSAndroid Build Coastguard Worker std::vector<std::string>* errors) {
607*598139dcSAndroid Build Coastguard Worker if (allow_security || name != "security") {
608*598139dcSAndroid Build Coastguard Worker errors->emplace_back(name);
609*598139dcSAndroid Build Coastguard Worker }
610*598139dcSAndroid Build Coastguard Worker }
611*598139dcSAndroid Build Coastguard Worker
Run(int argc,char ** argv)612*598139dcSAndroid Build Coastguard Worker int Logcat::Run(int argc, char** argv) {
613*598139dcSAndroid Build Coastguard Worker bool hasSetLogFormat = false;
614*598139dcSAndroid Build Coastguard Worker bool clearLog = false;
615*598139dcSAndroid Build Coastguard Worker bool security_buffer_selected =
616*598139dcSAndroid Build Coastguard Worker false; // Do not report errors on the security buffer unless it is explicitly named.
617*598139dcSAndroid Build Coastguard Worker bool getLogSize = false;
618*598139dcSAndroid Build Coastguard Worker bool getPruneList = false;
619*598139dcSAndroid Build Coastguard Worker bool printStatistics = false;
620*598139dcSAndroid Build Coastguard Worker unsigned long setLogSize = 0;
621*598139dcSAndroid Build Coastguard Worker const char* setPruneList = nullptr;
622*598139dcSAndroid Build Coastguard Worker const char* setId = nullptr;
623*598139dcSAndroid Build Coastguard Worker int mode = 0;
624*598139dcSAndroid Build Coastguard Worker std::string forceFilters;
625*598139dcSAndroid Build Coastguard Worker size_t tail_lines = 0;
626*598139dcSAndroid Build Coastguard Worker log_time tail_time(log_time::EPOCH);
627*598139dcSAndroid Build Coastguard Worker size_t pid = 0;
628*598139dcSAndroid Build Coastguard Worker bool got_t = false;
629*598139dcSAndroid Build Coastguard Worker unsigned id_mask = 0;
630*598139dcSAndroid Build Coastguard Worker std::set<uid_t> uids;
631*598139dcSAndroid Build Coastguard Worker
632*598139dcSAndroid Build Coastguard Worker if (argc == 2 && !strcmp(argv[1], "--help")) {
633*598139dcSAndroid Build Coastguard Worker show_help();
634*598139dcSAndroid Build Coastguard Worker return EXIT_SUCCESS;
635*598139dcSAndroid Build Coastguard Worker }
636*598139dcSAndroid Build Coastguard Worker
637*598139dcSAndroid Build Coastguard Worker // meant to catch comma-delimited values, but cast a wider
638*598139dcSAndroid Build Coastguard Worker // net for stability dealing with possible mistaken inputs.
639*598139dcSAndroid Build Coastguard Worker static const char delimiters[] = ",:; \t\n\r\f";
640*598139dcSAndroid Build Coastguard Worker
641*598139dcSAndroid Build Coastguard Worker optind = 0;
642*598139dcSAndroid Build Coastguard Worker while (true) {
643*598139dcSAndroid Build Coastguard Worker int option_index = 0;
644*598139dcSAndroid Build Coastguard Worker // list of long-argument only strings for later comparison
645*598139dcSAndroid Build Coastguard Worker static const char pid_str[] = "pid";
646*598139dcSAndroid Build Coastguard Worker static const char debug_str[] = "debug";
647*598139dcSAndroid Build Coastguard Worker static const char id_str[] = "id";
648*598139dcSAndroid Build Coastguard Worker static const char wrap_str[] = "wrap";
649*598139dcSAndroid Build Coastguard Worker static const char print_str[] = "print";
650*598139dcSAndroid Build Coastguard Worker static const char uid_str[] = "uid";
651*598139dcSAndroid Build Coastguard Worker static const char proto_str[] = "proto";
652*598139dcSAndroid Build Coastguard Worker // clang-format off
653*598139dcSAndroid Build Coastguard Worker static const struct option long_options[] = {
654*598139dcSAndroid Build Coastguard Worker { "binary", no_argument, nullptr, 'B' },
655*598139dcSAndroid Build Coastguard Worker { "buffer", required_argument, nullptr, 'b' },
656*598139dcSAndroid Build Coastguard Worker { "buffer-size", optional_argument, nullptr, 'g' },
657*598139dcSAndroid Build Coastguard Worker { "clear", no_argument, nullptr, 'c' },
658*598139dcSAndroid Build Coastguard Worker { debug_str, no_argument, nullptr, 0 },
659*598139dcSAndroid Build Coastguard Worker { "dividers", no_argument, nullptr, 'D' },
660*598139dcSAndroid Build Coastguard Worker { "file", required_argument, nullptr, 'f' },
661*598139dcSAndroid Build Coastguard Worker { "format", required_argument, nullptr, 'v' },
662*598139dcSAndroid Build Coastguard Worker // hidden and undocumented reserved alias for --regex
663*598139dcSAndroid Build Coastguard Worker { "grep", required_argument, nullptr, 'e' },
664*598139dcSAndroid Build Coastguard Worker // hidden and undocumented reserved alias for --max-count
665*598139dcSAndroid Build Coastguard Worker { "head", required_argument, nullptr, 'm' },
666*598139dcSAndroid Build Coastguard Worker { "help", no_argument, nullptr, 'h' },
667*598139dcSAndroid Build Coastguard Worker { id_str, required_argument, nullptr, 0 },
668*598139dcSAndroid Build Coastguard Worker { "last", no_argument, nullptr, 'L' },
669*598139dcSAndroid Build Coastguard Worker { "max-count", required_argument, nullptr, 'm' },
670*598139dcSAndroid Build Coastguard Worker { pid_str, required_argument, nullptr, 0 },
671*598139dcSAndroid Build Coastguard Worker { print_str, no_argument, nullptr, 0 },
672*598139dcSAndroid Build Coastguard Worker { "prune", optional_argument, nullptr, 'p' },
673*598139dcSAndroid Build Coastguard Worker { proto_str, no_argument, nullptr, 0 },
674*598139dcSAndroid Build Coastguard Worker { "regex", required_argument, nullptr, 'e' },
675*598139dcSAndroid Build Coastguard Worker { "rotate-count", required_argument, nullptr, 'n' },
676*598139dcSAndroid Build Coastguard Worker { "rotate-kbytes", required_argument, nullptr, 'r' },
677*598139dcSAndroid Build Coastguard Worker { "statistics", no_argument, nullptr, 'S' },
678*598139dcSAndroid Build Coastguard Worker // hidden and undocumented reserved alias for -t
679*598139dcSAndroid Build Coastguard Worker { "tail", required_argument, nullptr, 't' },
680*598139dcSAndroid Build Coastguard Worker { uid_str, required_argument, nullptr, 0 },
681*598139dcSAndroid Build Coastguard Worker // support, but ignore and do not document, the optional argument
682*598139dcSAndroid Build Coastguard Worker { wrap_str, optional_argument, nullptr, 0 },
683*598139dcSAndroid Build Coastguard Worker { nullptr, 0, nullptr, 0 }
684*598139dcSAndroid Build Coastguard Worker };
685*598139dcSAndroid Build Coastguard Worker // clang-format on
686*598139dcSAndroid Build Coastguard Worker
687*598139dcSAndroid Build Coastguard Worker int c = getopt_long(argc, argv, ":cdDhLt:T:gG:sQf:r:n:v:b:BSpP:m:e:", long_options,
688*598139dcSAndroid Build Coastguard Worker &option_index);
689*598139dcSAndroid Build Coastguard Worker if (c == -1) break;
690*598139dcSAndroid Build Coastguard Worker
691*598139dcSAndroid Build Coastguard Worker switch (c) {
692*598139dcSAndroid Build Coastguard Worker case 0:
693*598139dcSAndroid Build Coastguard Worker // only long options
694*598139dcSAndroid Build Coastguard Worker if (long_options[option_index].name == pid_str) {
695*598139dcSAndroid Build Coastguard Worker if (pid != 0) {
696*598139dcSAndroid Build Coastguard Worker error(EXIT_FAILURE, 0, "Only one --pid argument can be provided.");
697*598139dcSAndroid Build Coastguard Worker }
698*598139dcSAndroid Build Coastguard Worker
699*598139dcSAndroid Build Coastguard Worker if (!ParseUint(optarg, &pid) || pid < 1) {
700*598139dcSAndroid Build Coastguard Worker error(EXIT_FAILURE, 0, "pid '%s' out of range.", optarg);
701*598139dcSAndroid Build Coastguard Worker }
702*598139dcSAndroid Build Coastguard Worker break;
703*598139dcSAndroid Build Coastguard Worker }
704*598139dcSAndroid Build Coastguard Worker if (long_options[option_index].name == wrap_str) {
705*598139dcSAndroid Build Coastguard Worker mode |= ANDROID_LOG_WRAP | ANDROID_LOG_NONBLOCK;
706*598139dcSAndroid Build Coastguard Worker // ToDo: implement API that supports setting a wrap timeout
707*598139dcSAndroid Build Coastguard Worker size_t timeout = ANDROID_LOG_WRAP_DEFAULT_TIMEOUT;
708*598139dcSAndroid Build Coastguard Worker if (optarg && (!ParseUint(optarg, &timeout) || timeout < 1)) {
709*598139dcSAndroid Build Coastguard Worker error(EXIT_FAILURE, 0, "wrap timeout '%s' out of range.", optarg);
710*598139dcSAndroid Build Coastguard Worker }
711*598139dcSAndroid Build Coastguard Worker if (timeout != ANDROID_LOG_WRAP_DEFAULT_TIMEOUT) {
712*598139dcSAndroid Build Coastguard Worker fprintf(stderr, "WARNING: wrap timeout %zus, not default %us\n", timeout,
713*598139dcSAndroid Build Coastguard Worker ANDROID_LOG_WRAP_DEFAULT_TIMEOUT);
714*598139dcSAndroid Build Coastguard Worker }
715*598139dcSAndroid Build Coastguard Worker break;
716*598139dcSAndroid Build Coastguard Worker }
717*598139dcSAndroid Build Coastguard Worker if (long_options[option_index].name == print_str) {
718*598139dcSAndroid Build Coastguard Worker print_it_anyway_ = true;
719*598139dcSAndroid Build Coastguard Worker break;
720*598139dcSAndroid Build Coastguard Worker }
721*598139dcSAndroid Build Coastguard Worker if (long_options[option_index].name == debug_str) {
722*598139dcSAndroid Build Coastguard Worker debug_ = true;
723*598139dcSAndroid Build Coastguard Worker break;
724*598139dcSAndroid Build Coastguard Worker }
725*598139dcSAndroid Build Coastguard Worker if (long_options[option_index].name == id_str) {
726*598139dcSAndroid Build Coastguard Worker setId = (optarg && optarg[0]) ? optarg : nullptr;
727*598139dcSAndroid Build Coastguard Worker }
728*598139dcSAndroid Build Coastguard Worker if (long_options[option_index].name == uid_str) {
729*598139dcSAndroid Build Coastguard Worker auto uid_strings = Split(optarg, delimiters);
730*598139dcSAndroid Build Coastguard Worker for (const auto& uid_string : uid_strings) {
731*598139dcSAndroid Build Coastguard Worker uid_t uid;
732*598139dcSAndroid Build Coastguard Worker if (!ParseUint(uid_string, &uid)) {
733*598139dcSAndroid Build Coastguard Worker error(EXIT_FAILURE, 0, "Unable to parse UID '%s'", uid_string.c_str());
734*598139dcSAndroid Build Coastguard Worker }
735*598139dcSAndroid Build Coastguard Worker uids.emplace(uid);
736*598139dcSAndroid Build Coastguard Worker }
737*598139dcSAndroid Build Coastguard Worker break;
738*598139dcSAndroid Build Coastguard Worker }
739*598139dcSAndroid Build Coastguard Worker if (long_options[option_index].name == proto_str) {
740*598139dcSAndroid Build Coastguard Worker output_type_ = PROTO;
741*598139dcSAndroid Build Coastguard Worker break;
742*598139dcSAndroid Build Coastguard Worker }
743*598139dcSAndroid Build Coastguard Worker break;
744*598139dcSAndroid Build Coastguard Worker
745*598139dcSAndroid Build Coastguard Worker case 's':
746*598139dcSAndroid Build Coastguard Worker // default to all silent
747*598139dcSAndroid Build Coastguard Worker android_log_addFilterRule(logformat_.get(), "*:s");
748*598139dcSAndroid Build Coastguard Worker break;
749*598139dcSAndroid Build Coastguard Worker
750*598139dcSAndroid Build Coastguard Worker case 'c':
751*598139dcSAndroid Build Coastguard Worker clearLog = true;
752*598139dcSAndroid Build Coastguard Worker break;
753*598139dcSAndroid Build Coastguard Worker
754*598139dcSAndroid Build Coastguard Worker case 'L':
755*598139dcSAndroid Build Coastguard Worker mode |= ANDROID_LOG_PSTORE | ANDROID_LOG_NONBLOCK;
756*598139dcSAndroid Build Coastguard Worker break;
757*598139dcSAndroid Build Coastguard Worker
758*598139dcSAndroid Build Coastguard Worker case 'd':
759*598139dcSAndroid Build Coastguard Worker mode |= ANDROID_LOG_NONBLOCK;
760*598139dcSAndroid Build Coastguard Worker break;
761*598139dcSAndroid Build Coastguard Worker
762*598139dcSAndroid Build Coastguard Worker case 't':
763*598139dcSAndroid Build Coastguard Worker got_t = true;
764*598139dcSAndroid Build Coastguard Worker mode |= ANDROID_LOG_NONBLOCK;
765*598139dcSAndroid Build Coastguard Worker FALLTHROUGH_INTENDED;
766*598139dcSAndroid Build Coastguard Worker case 'T':
767*598139dcSAndroid Build Coastguard Worker if (strspn(optarg, "0123456789") != strlen(optarg)) {
768*598139dcSAndroid Build Coastguard Worker char* cp = parseTime(tail_time, optarg);
769*598139dcSAndroid Build Coastguard Worker if (!cp) {
770*598139dcSAndroid Build Coastguard Worker error(EXIT_FAILURE, 0, "-%c '%s' not in time format.", c, optarg);
771*598139dcSAndroid Build Coastguard Worker }
772*598139dcSAndroid Build Coastguard Worker if (*cp) {
773*598139dcSAndroid Build Coastguard Worker char ch = *cp;
774*598139dcSAndroid Build Coastguard Worker *cp = '\0';
775*598139dcSAndroid Build Coastguard Worker fprintf(stderr, "WARNING: -%c '%s' '%c%s' time truncated\n", c, optarg, ch,
776*598139dcSAndroid Build Coastguard Worker cp + 1);
777*598139dcSAndroid Build Coastguard Worker *cp = ch;
778*598139dcSAndroid Build Coastguard Worker }
779*598139dcSAndroid Build Coastguard Worker } else {
780*598139dcSAndroid Build Coastguard Worker if (!ParseUint(optarg, &tail_lines) || tail_lines < 1) {
781*598139dcSAndroid Build Coastguard Worker fprintf(stderr, "WARNING: -%c %s invalid, setting to 1\n", c, optarg);
782*598139dcSAndroid Build Coastguard Worker tail_lines = 1;
783*598139dcSAndroid Build Coastguard Worker }
784*598139dcSAndroid Build Coastguard Worker }
785*598139dcSAndroid Build Coastguard Worker break;
786*598139dcSAndroid Build Coastguard Worker
787*598139dcSAndroid Build Coastguard Worker case 'D':
788*598139dcSAndroid Build Coastguard Worker print_dividers_ = true;
789*598139dcSAndroid Build Coastguard Worker break;
790*598139dcSAndroid Build Coastguard Worker
791*598139dcSAndroid Build Coastguard Worker case 'e':
792*598139dcSAndroid Build Coastguard Worker regex_.reset(new std::regex(optarg));
793*598139dcSAndroid Build Coastguard Worker break;
794*598139dcSAndroid Build Coastguard Worker
795*598139dcSAndroid Build Coastguard Worker case 'm': {
796*598139dcSAndroid Build Coastguard Worker if (!ParseUint(optarg, &max_count_) || max_count_ < 1) {
797*598139dcSAndroid Build Coastguard Worker error(EXIT_FAILURE, 0, "-%c '%s' isn't an integer greater than zero.", c,
798*598139dcSAndroid Build Coastguard Worker optarg);
799*598139dcSAndroid Build Coastguard Worker }
800*598139dcSAndroid Build Coastguard Worker } break;
801*598139dcSAndroid Build Coastguard Worker
802*598139dcSAndroid Build Coastguard Worker case 'g':
803*598139dcSAndroid Build Coastguard Worker if (!optarg) {
804*598139dcSAndroid Build Coastguard Worker getLogSize = true;
805*598139dcSAndroid Build Coastguard Worker break;
806*598139dcSAndroid Build Coastguard Worker }
807*598139dcSAndroid Build Coastguard Worker FALLTHROUGH_INTENDED;
808*598139dcSAndroid Build Coastguard Worker
809*598139dcSAndroid Build Coastguard Worker case 'G': {
810*598139dcSAndroid Build Coastguard Worker if (!ParseByteCount(optarg, &setLogSize) || setLogSize < 1) {
811*598139dcSAndroid Build Coastguard Worker error(EXIT_FAILURE, 0, "-G must be specified as <num><multiplier>.");
812*598139dcSAndroid Build Coastguard Worker }
813*598139dcSAndroid Build Coastguard Worker } break;
814*598139dcSAndroid Build Coastguard Worker
815*598139dcSAndroid Build Coastguard Worker case 'p':
816*598139dcSAndroid Build Coastguard Worker if (!optarg) {
817*598139dcSAndroid Build Coastguard Worker getPruneList = true;
818*598139dcSAndroid Build Coastguard Worker break;
819*598139dcSAndroid Build Coastguard Worker }
820*598139dcSAndroid Build Coastguard Worker FALLTHROUGH_INTENDED;
821*598139dcSAndroid Build Coastguard Worker
822*598139dcSAndroid Build Coastguard Worker case 'P':
823*598139dcSAndroid Build Coastguard Worker setPruneList = optarg;
824*598139dcSAndroid Build Coastguard Worker break;
825*598139dcSAndroid Build Coastguard Worker
826*598139dcSAndroid Build Coastguard Worker case 'b':
827*598139dcSAndroid Build Coastguard Worker for (const auto& buffer : Split(optarg, delimiters)) {
828*598139dcSAndroid Build Coastguard Worker if (buffer == "default") {
829*598139dcSAndroid Build Coastguard Worker id_mask |= (1 << LOG_ID_MAIN) | (1 << LOG_ID_SYSTEM) | (1 << LOG_ID_CRASH);
830*598139dcSAndroid Build Coastguard Worker } else if (buffer == "all") {
831*598139dcSAndroid Build Coastguard Worker id_mask = -1;
832*598139dcSAndroid Build Coastguard Worker } else {
833*598139dcSAndroid Build Coastguard Worker log_id_t log_id = android_name_to_log_id(buffer.c_str());
834*598139dcSAndroid Build Coastguard Worker if (!__android_log_id_is_valid(log_id)) {
835*598139dcSAndroid Build Coastguard Worker error(EXIT_FAILURE, 0, "Unknown -b buffer '%s'.", buffer.c_str());
836*598139dcSAndroid Build Coastguard Worker }
837*598139dcSAndroid Build Coastguard Worker if (log_id == LOG_ID_SECURITY) {
838*598139dcSAndroid Build Coastguard Worker security_buffer_selected = true;
839*598139dcSAndroid Build Coastguard Worker }
840*598139dcSAndroid Build Coastguard Worker id_mask |= (1 << log_id);
841*598139dcSAndroid Build Coastguard Worker }
842*598139dcSAndroid Build Coastguard Worker }
843*598139dcSAndroid Build Coastguard Worker break;
844*598139dcSAndroid Build Coastguard Worker
845*598139dcSAndroid Build Coastguard Worker case 'B':
846*598139dcSAndroid Build Coastguard Worker output_type_ = BINARY;
847*598139dcSAndroid Build Coastguard Worker break;
848*598139dcSAndroid Build Coastguard Worker
849*598139dcSAndroid Build Coastguard Worker case 'f':
850*598139dcSAndroid Build Coastguard Worker if ((tail_time == log_time::EPOCH) && !tail_lines) {
851*598139dcSAndroid Build Coastguard Worker tail_time = lastLogTime(optarg);
852*598139dcSAndroid Build Coastguard Worker }
853*598139dcSAndroid Build Coastguard Worker // redirect output to a file
854*598139dcSAndroid Build Coastguard Worker output_file_name_ = optarg;
855*598139dcSAndroid Build Coastguard Worker break;
856*598139dcSAndroid Build Coastguard Worker
857*598139dcSAndroid Build Coastguard Worker case 'r':
858*598139dcSAndroid Build Coastguard Worker if (!ParseUint(optarg, &log_rotate_size_kb_) || log_rotate_size_kb_ < 1) {
859*598139dcSAndroid Build Coastguard Worker error(EXIT_FAILURE, 0, "Invalid -r '%s'.", optarg);
860*598139dcSAndroid Build Coastguard Worker }
861*598139dcSAndroid Build Coastguard Worker break;
862*598139dcSAndroid Build Coastguard Worker
863*598139dcSAndroid Build Coastguard Worker case 'n':
864*598139dcSAndroid Build Coastguard Worker if (!ParseUint(optarg, &max_rotated_logs_) || max_rotated_logs_ < 1) {
865*598139dcSAndroid Build Coastguard Worker error(EXIT_FAILURE, 0, "Invalid -n '%s'.", optarg);
866*598139dcSAndroid Build Coastguard Worker }
867*598139dcSAndroid Build Coastguard Worker break;
868*598139dcSAndroid Build Coastguard Worker
869*598139dcSAndroid Build Coastguard Worker case 'v':
870*598139dcSAndroid Build Coastguard Worker for (const auto& arg : Split(optarg, delimiters)) {
871*598139dcSAndroid Build Coastguard Worker int err = SetLogFormat(arg.c_str());
872*598139dcSAndroid Build Coastguard Worker if (err < 0) {
873*598139dcSAndroid Build Coastguard Worker error(EXIT_FAILURE, 0, "Invalid -v '%s'.", arg.c_str());
874*598139dcSAndroid Build Coastguard Worker }
875*598139dcSAndroid Build Coastguard Worker if (err) hasSetLogFormat = true;
876*598139dcSAndroid Build Coastguard Worker }
877*598139dcSAndroid Build Coastguard Worker break;
878*598139dcSAndroid Build Coastguard Worker
879*598139dcSAndroid Build Coastguard Worker case 'S':
880*598139dcSAndroid Build Coastguard Worker printStatistics = true;
881*598139dcSAndroid Build Coastguard Worker break;
882*598139dcSAndroid Build Coastguard Worker
883*598139dcSAndroid Build Coastguard Worker case ':':
884*598139dcSAndroid Build Coastguard Worker error(EXIT_FAILURE, 0, "Option '%s' needs an argument.", argv[optind - 1]);
885*598139dcSAndroid Build Coastguard Worker break;
886*598139dcSAndroid Build Coastguard Worker
887*598139dcSAndroid Build Coastguard Worker case 'h':
888*598139dcSAndroid Build Coastguard Worker show_help();
889*598139dcSAndroid Build Coastguard Worker return EXIT_SUCCESS;
890*598139dcSAndroid Build Coastguard Worker
891*598139dcSAndroid Build Coastguard Worker case '?':
892*598139dcSAndroid Build Coastguard Worker error(EXIT_FAILURE, 0, "Unknown option '%s'.", argv[optind]);
893*598139dcSAndroid Build Coastguard Worker break;
894*598139dcSAndroid Build Coastguard Worker
895*598139dcSAndroid Build Coastguard Worker default:
896*598139dcSAndroid Build Coastguard Worker error(EXIT_FAILURE, 0, "Unknown getopt_long() result '%c'.", c);
897*598139dcSAndroid Build Coastguard Worker }
898*598139dcSAndroid Build Coastguard Worker }
899*598139dcSAndroid Build Coastguard Worker
900*598139dcSAndroid Build Coastguard Worker if (max_count_ && got_t) {
901*598139dcSAndroid Build Coastguard Worker error(EXIT_FAILURE, 0, "Cannot use -m (--max-count) and -t together.");
902*598139dcSAndroid Build Coastguard Worker }
903*598139dcSAndroid Build Coastguard Worker if (print_it_anyway_ && (!regex_ || !max_count_)) {
904*598139dcSAndroid Build Coastguard Worker // One day it would be nice if --print -v color and --regex <expr>
905*598139dcSAndroid Build Coastguard Worker // could play with each other and show regex highlighted content.
906*598139dcSAndroid Build Coastguard Worker fprintf(stderr,
907*598139dcSAndroid Build Coastguard Worker "WARNING: "
908*598139dcSAndroid Build Coastguard Worker "--print ignored, to be used in combination with\n"
909*598139dcSAndroid Build Coastguard Worker " "
910*598139dcSAndroid Build Coastguard Worker "--regex <expr> and --max-count <N>\n");
911*598139dcSAndroid Build Coastguard Worker print_it_anyway_ = false;
912*598139dcSAndroid Build Coastguard Worker }
913*598139dcSAndroid Build Coastguard Worker
914*598139dcSAndroid Build Coastguard Worker // If no buffers are specified, default to using these buffers.
915*598139dcSAndroid Build Coastguard Worker if (id_mask == 0) {
916*598139dcSAndroid Build Coastguard Worker id_mask = (1 << LOG_ID_MAIN) | (1 << LOG_ID_SYSTEM) | (1 << LOG_ID_CRASH) |
917*598139dcSAndroid Build Coastguard Worker (1 << LOG_ID_KERNEL);
918*598139dcSAndroid Build Coastguard Worker }
919*598139dcSAndroid Build Coastguard Worker
920*598139dcSAndroid Build Coastguard Worker if (log_rotate_size_kb_ != 0 && !output_file_name_) {
921*598139dcSAndroid Build Coastguard Worker error(EXIT_FAILURE, 0, "-r requires -f as well.");
922*598139dcSAndroid Build Coastguard Worker }
923*598139dcSAndroid Build Coastguard Worker
924*598139dcSAndroid Build Coastguard Worker if (setId != 0) {
925*598139dcSAndroid Build Coastguard Worker if (!output_file_name_) {
926*598139dcSAndroid Build Coastguard Worker error(EXIT_FAILURE, 0, "--id='%s' requires -f as well.", setId);
927*598139dcSAndroid Build Coastguard Worker }
928*598139dcSAndroid Build Coastguard Worker
929*598139dcSAndroid Build Coastguard Worker std::string file_name = StringPrintf("%s.id", output_file_name_);
930*598139dcSAndroid Build Coastguard Worker std::string file;
931*598139dcSAndroid Build Coastguard Worker bool file_ok = android::base::ReadFileToString(file_name, &file);
932*598139dcSAndroid Build Coastguard Worker android::base::WriteStringToFile(setId, file_name, S_IRUSR | S_IWUSR,
933*598139dcSAndroid Build Coastguard Worker getuid(), getgid());
934*598139dcSAndroid Build Coastguard Worker if (!file_ok || !file.compare(setId)) setId = nullptr;
935*598139dcSAndroid Build Coastguard Worker }
936*598139dcSAndroid Build Coastguard Worker
937*598139dcSAndroid Build Coastguard Worker if (!hasSetLogFormat) {
938*598139dcSAndroid Build Coastguard Worker const char* logFormat = getenv("ANDROID_PRINTF_LOG");
939*598139dcSAndroid Build Coastguard Worker
940*598139dcSAndroid Build Coastguard Worker if (!!logFormat) {
941*598139dcSAndroid Build Coastguard Worker for (const auto& arg : Split(logFormat, delimiters)) {
942*598139dcSAndroid Build Coastguard Worker int err = SetLogFormat(arg.c_str());
943*598139dcSAndroid Build Coastguard Worker // environment should not cause crash of logcat
944*598139dcSAndroid Build Coastguard Worker if (err < 0) {
945*598139dcSAndroid Build Coastguard Worker fprintf(stderr, "invalid format in ANDROID_PRINTF_LOG '%s'\n", arg.c_str());
946*598139dcSAndroid Build Coastguard Worker }
947*598139dcSAndroid Build Coastguard Worker if (err > 0) hasSetLogFormat = true;
948*598139dcSAndroid Build Coastguard Worker }
949*598139dcSAndroid Build Coastguard Worker }
950*598139dcSAndroid Build Coastguard Worker if (!hasSetLogFormat) {
951*598139dcSAndroid Build Coastguard Worker SetLogFormat("threadtime");
952*598139dcSAndroid Build Coastguard Worker }
953*598139dcSAndroid Build Coastguard Worker }
954*598139dcSAndroid Build Coastguard Worker
955*598139dcSAndroid Build Coastguard Worker if (forceFilters.size()) {
956*598139dcSAndroid Build Coastguard Worker int err = android_log_addFilterString(logformat_.get(), forceFilters.c_str());
957*598139dcSAndroid Build Coastguard Worker if (err < 0) {
958*598139dcSAndroid Build Coastguard Worker error(EXIT_FAILURE, 0, "Invalid filter expression '%s' in logcat args.",
959*598139dcSAndroid Build Coastguard Worker forceFilters.c_str());
960*598139dcSAndroid Build Coastguard Worker }
961*598139dcSAndroid Build Coastguard Worker } else if (argc == optind) {
962*598139dcSAndroid Build Coastguard Worker // Add from environment variable
963*598139dcSAndroid Build Coastguard Worker const char* env_tags_orig = getenv("ANDROID_LOG_TAGS");
964*598139dcSAndroid Build Coastguard Worker
965*598139dcSAndroid Build Coastguard Worker if (!!env_tags_orig) {
966*598139dcSAndroid Build Coastguard Worker int err = android_log_addFilterString(logformat_.get(), env_tags_orig);
967*598139dcSAndroid Build Coastguard Worker
968*598139dcSAndroid Build Coastguard Worker if (err < 0) {
969*598139dcSAndroid Build Coastguard Worker error(EXIT_FAILURE, 0, "Invalid filter expression '%s' in ANDROID_LOG_TAGS.",
970*598139dcSAndroid Build Coastguard Worker env_tags_orig);
971*598139dcSAndroid Build Coastguard Worker }
972*598139dcSAndroid Build Coastguard Worker }
973*598139dcSAndroid Build Coastguard Worker } else {
974*598139dcSAndroid Build Coastguard Worker // Add from commandline
975*598139dcSAndroid Build Coastguard Worker for (int i = optind ; i < argc ; i++) {
976*598139dcSAndroid Build Coastguard Worker int err = android_log_addFilterString(logformat_.get(), argv[i]);
977*598139dcSAndroid Build Coastguard Worker if (err < 0) {
978*598139dcSAndroid Build Coastguard Worker error(EXIT_FAILURE, 0, "Invalid filter expression '%s'.", argv[i]);
979*598139dcSAndroid Build Coastguard Worker }
980*598139dcSAndroid Build Coastguard Worker }
981*598139dcSAndroid Build Coastguard Worker }
982*598139dcSAndroid Build Coastguard Worker
983*598139dcSAndroid Build Coastguard Worker if (mode & ANDROID_LOG_PSTORE) {
984*598139dcSAndroid Build Coastguard Worker if (setLogSize || getLogSize || printStatistics || getPruneList || setPruneList) {
985*598139dcSAndroid Build Coastguard Worker error(EXIT_FAILURE, 0, "-L is incompatible with -g/-G, -S, and -p/-P.");
986*598139dcSAndroid Build Coastguard Worker }
987*598139dcSAndroid Build Coastguard Worker if (clearLog) {
988*598139dcSAndroid Build Coastguard Worker if (output_file_name_) {
989*598139dcSAndroid Build Coastguard Worker error(EXIT_FAILURE, 0, "-c is ambiguous with both -f and -L specified.");
990*598139dcSAndroid Build Coastguard Worker }
991*598139dcSAndroid Build Coastguard Worker unlink("/sys/fs/pstore/pmsg-ramoops-0");
992*598139dcSAndroid Build Coastguard Worker return EXIT_SUCCESS;
993*598139dcSAndroid Build Coastguard Worker }
994*598139dcSAndroid Build Coastguard Worker }
995*598139dcSAndroid Build Coastguard Worker
996*598139dcSAndroid Build Coastguard Worker if (output_file_name_) {
997*598139dcSAndroid Build Coastguard Worker if (setLogSize || getLogSize || printStatistics || getPruneList || setPruneList) {
998*598139dcSAndroid Build Coastguard Worker error(EXIT_FAILURE, 0, "-f is incompatible with -g/-G, -S, and -p/-P.");
999*598139dcSAndroid Build Coastguard Worker }
1000*598139dcSAndroid Build Coastguard Worker
1001*598139dcSAndroid Build Coastguard Worker if (clearLog || setId) {
1002*598139dcSAndroid Build Coastguard Worker int max_rotation_count_digits =
1003*598139dcSAndroid Build Coastguard Worker max_rotated_logs_ > 0 ? (int)(floor(log10(max_rotated_logs_) + 1)) : 0;
1004*598139dcSAndroid Build Coastguard Worker
1005*598139dcSAndroid Build Coastguard Worker for (int i = max_rotated_logs_; i >= 0; --i) {
1006*598139dcSAndroid Build Coastguard Worker std::string file;
1007*598139dcSAndroid Build Coastguard Worker
1008*598139dcSAndroid Build Coastguard Worker if (!i) {
1009*598139dcSAndroid Build Coastguard Worker file = output_file_name_;
1010*598139dcSAndroid Build Coastguard Worker } else {
1011*598139dcSAndroid Build Coastguard Worker file = StringPrintf("%s.%.*d", output_file_name_, max_rotation_count_digits, i);
1012*598139dcSAndroid Build Coastguard Worker }
1013*598139dcSAndroid Build Coastguard Worker
1014*598139dcSAndroid Build Coastguard Worker int err = unlink(file.c_str());
1015*598139dcSAndroid Build Coastguard Worker
1016*598139dcSAndroid Build Coastguard Worker if (err < 0 && errno != ENOENT) {
1017*598139dcSAndroid Build Coastguard Worker fprintf(stderr, "failed to delete log file '%s': %s\n", file.c_str(),
1018*598139dcSAndroid Build Coastguard Worker strerror(errno));
1019*598139dcSAndroid Build Coastguard Worker }
1020*598139dcSAndroid Build Coastguard Worker }
1021*598139dcSAndroid Build Coastguard Worker }
1022*598139dcSAndroid Build Coastguard Worker
1023*598139dcSAndroid Build Coastguard Worker if (clearLog) {
1024*598139dcSAndroid Build Coastguard Worker return EXIT_SUCCESS;
1025*598139dcSAndroid Build Coastguard Worker }
1026*598139dcSAndroid Build Coastguard Worker }
1027*598139dcSAndroid Build Coastguard Worker
1028*598139dcSAndroid Build Coastguard Worker std::unique_ptr<logger_list, decltype(&android_logger_list_free)> logger_list{
1029*598139dcSAndroid Build Coastguard Worker nullptr, &android_logger_list_free};
1030*598139dcSAndroid Build Coastguard Worker if (tail_time != log_time::EPOCH) {
1031*598139dcSAndroid Build Coastguard Worker logger_list.reset(android_logger_list_alloc_time(mode, tail_time, pid));
1032*598139dcSAndroid Build Coastguard Worker } else {
1033*598139dcSAndroid Build Coastguard Worker logger_list.reset(android_logger_list_alloc(mode, tail_lines, pid));
1034*598139dcSAndroid Build Coastguard Worker }
1035*598139dcSAndroid Build Coastguard Worker // We have three orthogonal actions below to clear, set log size and
1036*598139dcSAndroid Build Coastguard Worker // get log size. All sharing the same iteration loop.
1037*598139dcSAndroid Build Coastguard Worker std::vector<std::string> open_device_failures;
1038*598139dcSAndroid Build Coastguard Worker std::vector<std::string> clear_failures;
1039*598139dcSAndroid Build Coastguard Worker std::vector<std::string> set_size_failures;
1040*598139dcSAndroid Build Coastguard Worker std::vector<std::string> get_size_failures;
1041*598139dcSAndroid Build Coastguard Worker
1042*598139dcSAndroid Build Coastguard Worker for (int i = LOG_ID_MIN; i < LOG_ID_MAX; ++i) {
1043*598139dcSAndroid Build Coastguard Worker if (!(id_mask & (1 << i))) continue;
1044*598139dcSAndroid Build Coastguard Worker const char* buffer_name = android_log_id_to_name(static_cast<log_id_t>(i));
1045*598139dcSAndroid Build Coastguard Worker
1046*598139dcSAndroid Build Coastguard Worker auto logger = android_logger_open(logger_list.get(), static_cast<log_id_t>(i));
1047*598139dcSAndroid Build Coastguard Worker if (logger == nullptr) {
1048*598139dcSAndroid Build Coastguard Worker ReportErrorName(buffer_name, security_buffer_selected, &open_device_failures);
1049*598139dcSAndroid Build Coastguard Worker continue;
1050*598139dcSAndroid Build Coastguard Worker }
1051*598139dcSAndroid Build Coastguard Worker
1052*598139dcSAndroid Build Coastguard Worker if (clearLog) {
1053*598139dcSAndroid Build Coastguard Worker if (android_logger_clear(logger)) {
1054*598139dcSAndroid Build Coastguard Worker ReportErrorName(buffer_name, security_buffer_selected, &clear_failures);
1055*598139dcSAndroid Build Coastguard Worker }
1056*598139dcSAndroid Build Coastguard Worker }
1057*598139dcSAndroid Build Coastguard Worker
1058*598139dcSAndroid Build Coastguard Worker if (setLogSize) {
1059*598139dcSAndroid Build Coastguard Worker if (android_logger_set_log_size(logger, setLogSize)) {
1060*598139dcSAndroid Build Coastguard Worker ReportErrorName(buffer_name, security_buffer_selected, &set_size_failures);
1061*598139dcSAndroid Build Coastguard Worker }
1062*598139dcSAndroid Build Coastguard Worker }
1063*598139dcSAndroid Build Coastguard Worker
1064*598139dcSAndroid Build Coastguard Worker if (getLogSize) {
1065*598139dcSAndroid Build Coastguard Worker long size = android_logger_get_log_size(logger);
1066*598139dcSAndroid Build Coastguard Worker long readable = android_logger_get_log_readable_size(logger);
1067*598139dcSAndroid Build Coastguard Worker long consumed = android_logger_get_log_consumed_size(logger);
1068*598139dcSAndroid Build Coastguard Worker
1069*598139dcSAndroid Build Coastguard Worker if (size < 0 || readable < 0) {
1070*598139dcSAndroid Build Coastguard Worker ReportErrorName(buffer_name, security_buffer_selected, &get_size_failures);
1071*598139dcSAndroid Build Coastguard Worker } else {
1072*598139dcSAndroid Build Coastguard Worker auto size_format = format_of_size(size);
1073*598139dcSAndroid Build Coastguard Worker auto readable_format = format_of_size(readable);
1074*598139dcSAndroid Build Coastguard Worker auto consumed_format = format_of_size(consumed);
1075*598139dcSAndroid Build Coastguard Worker std::string str = android::base::StringPrintf(
1076*598139dcSAndroid Build Coastguard Worker "%s: ring buffer is %lu %sB (%lu %sB consumed, %lu %sB readable),"
1077*598139dcSAndroid Build Coastguard Worker " max entry is %d B, max payload is %d B\n",
1078*598139dcSAndroid Build Coastguard Worker buffer_name, size_format.first, size_format.second, consumed_format.first,
1079*598139dcSAndroid Build Coastguard Worker consumed_format.second, readable_format.first, readable_format.second,
1080*598139dcSAndroid Build Coastguard Worker (int)LOGGER_ENTRY_MAX_LEN, (int)LOGGER_ENTRY_MAX_PAYLOAD);
1081*598139dcSAndroid Build Coastguard Worker WriteFully(str.data(), str.length());
1082*598139dcSAndroid Build Coastguard Worker }
1083*598139dcSAndroid Build Coastguard Worker }
1084*598139dcSAndroid Build Coastguard Worker }
1085*598139dcSAndroid Build Coastguard Worker
1086*598139dcSAndroid Build Coastguard Worker // report any errors in the above loop and exit
1087*598139dcSAndroid Build Coastguard Worker if (!open_device_failures.empty()) {
1088*598139dcSAndroid Build Coastguard Worker error(EXIT_FAILURE, 0, "Unable to open log device%s '%s'.",
1089*598139dcSAndroid Build Coastguard Worker open_device_failures.size() > 1 ? "s" : "", Join(open_device_failures, ",").c_str());
1090*598139dcSAndroid Build Coastguard Worker }
1091*598139dcSAndroid Build Coastguard Worker if (!clear_failures.empty()) {
1092*598139dcSAndroid Build Coastguard Worker error(EXIT_FAILURE, 0, "failed to clear the '%s' log%s.", Join(clear_failures, ",").c_str(),
1093*598139dcSAndroid Build Coastguard Worker clear_failures.size() > 1 ? "s" : "");
1094*598139dcSAndroid Build Coastguard Worker }
1095*598139dcSAndroid Build Coastguard Worker if (!set_size_failures.empty()) {
1096*598139dcSAndroid Build Coastguard Worker error(EXIT_FAILURE, 0, "failed to set the '%s' log size%s.",
1097*598139dcSAndroid Build Coastguard Worker Join(set_size_failures, ",").c_str(), set_size_failures.size() > 1 ? "s" : "");
1098*598139dcSAndroid Build Coastguard Worker }
1099*598139dcSAndroid Build Coastguard Worker if (!get_size_failures.empty()) {
1100*598139dcSAndroid Build Coastguard Worker error(EXIT_FAILURE, 0, "failed to get the readable '%s' log size%s.",
1101*598139dcSAndroid Build Coastguard Worker Join(get_size_failures, ",").c_str(), get_size_failures.size() > 1 ? "s" : "");
1102*598139dcSAndroid Build Coastguard Worker }
1103*598139dcSAndroid Build Coastguard Worker
1104*598139dcSAndroid Build Coastguard Worker if (setPruneList) {
1105*598139dcSAndroid Build Coastguard Worker size_t len = strlen(setPruneList);
1106*598139dcSAndroid Build Coastguard Worker if (android_logger_set_prune_list(logger_list.get(), setPruneList, len)) {
1107*598139dcSAndroid Build Coastguard Worker error(EXIT_FAILURE, 0, "Failed to set the prune list to '%s'.", setPruneList);
1108*598139dcSAndroid Build Coastguard Worker }
1109*598139dcSAndroid Build Coastguard Worker return EXIT_SUCCESS;
1110*598139dcSAndroid Build Coastguard Worker }
1111*598139dcSAndroid Build Coastguard Worker
1112*598139dcSAndroid Build Coastguard Worker if (printStatistics || getPruneList) {
1113*598139dcSAndroid Build Coastguard Worker std::string buf(8192, '\0');
1114*598139dcSAndroid Build Coastguard Worker size_t ret_length = 0;
1115*598139dcSAndroid Build Coastguard Worker int retry = 32;
1116*598139dcSAndroid Build Coastguard Worker
1117*598139dcSAndroid Build Coastguard Worker for (; retry >= 0; --retry) {
1118*598139dcSAndroid Build Coastguard Worker if (getPruneList) {
1119*598139dcSAndroid Build Coastguard Worker android_logger_get_prune_list(logger_list.get(), buf.data(), buf.size());
1120*598139dcSAndroid Build Coastguard Worker } else {
1121*598139dcSAndroid Build Coastguard Worker android_logger_get_statistics(logger_list.get(), buf.data(), buf.size());
1122*598139dcSAndroid Build Coastguard Worker }
1123*598139dcSAndroid Build Coastguard Worker
1124*598139dcSAndroid Build Coastguard Worker ret_length = atol(buf.c_str());
1125*598139dcSAndroid Build Coastguard Worker if (ret_length < 3) {
1126*598139dcSAndroid Build Coastguard Worker error(EXIT_FAILURE, 0, "Failed to read data.");
1127*598139dcSAndroid Build Coastguard Worker }
1128*598139dcSAndroid Build Coastguard Worker
1129*598139dcSAndroid Build Coastguard Worker if (ret_length < buf.size()) {
1130*598139dcSAndroid Build Coastguard Worker break;
1131*598139dcSAndroid Build Coastguard Worker }
1132*598139dcSAndroid Build Coastguard Worker
1133*598139dcSAndroid Build Coastguard Worker buf.resize(ret_length + 1);
1134*598139dcSAndroid Build Coastguard Worker }
1135*598139dcSAndroid Build Coastguard Worker
1136*598139dcSAndroid Build Coastguard Worker if (retry < 0) {
1137*598139dcSAndroid Build Coastguard Worker error(EXIT_FAILURE, 0, "Failed to read data.");
1138*598139dcSAndroid Build Coastguard Worker }
1139*598139dcSAndroid Build Coastguard Worker
1140*598139dcSAndroid Build Coastguard Worker buf.resize(ret_length);
1141*598139dcSAndroid Build Coastguard Worker if (buf.back() == '\f') {
1142*598139dcSAndroid Build Coastguard Worker buf.pop_back();
1143*598139dcSAndroid Build Coastguard Worker }
1144*598139dcSAndroid Build Coastguard Worker
1145*598139dcSAndroid Build Coastguard Worker // Remove the byte count prefix
1146*598139dcSAndroid Build Coastguard Worker const char* cp = buf.c_str();
1147*598139dcSAndroid Build Coastguard Worker while (isdigit(*cp)) ++cp;
1148*598139dcSAndroid Build Coastguard Worker if (*cp == '\n') ++cp;
1149*598139dcSAndroid Build Coastguard Worker
1150*598139dcSAndroid Build Coastguard Worker WriteFully(cp, strlen(cp));
1151*598139dcSAndroid Build Coastguard Worker return EXIT_SUCCESS;
1152*598139dcSAndroid Build Coastguard Worker }
1153*598139dcSAndroid Build Coastguard Worker
1154*598139dcSAndroid Build Coastguard Worker if (getLogSize || setLogSize || clearLog) return EXIT_SUCCESS;
1155*598139dcSAndroid Build Coastguard Worker
1156*598139dcSAndroid Build Coastguard Worker bool blocking = !(mode & ANDROID_LOG_NONBLOCK);
1157*598139dcSAndroid Build Coastguard Worker SetupOutputAndSchedulingPolicy(blocking);
1158*598139dcSAndroid Build Coastguard Worker
1159*598139dcSAndroid Build Coastguard Worker // Purge as much memory as possible before going into the log reading loop.
1160*598139dcSAndroid Build Coastguard Worker // Do this before checking if logd is ready just in case logd isn't
1161*598139dcSAndroid Build Coastguard Worker // ready and this call can be done without penalizing start up.
1162*598139dcSAndroid Build Coastguard Worker mallopt(M_PURGE_ALL, 0);
1163*598139dcSAndroid Build Coastguard Worker
1164*598139dcSAndroid Build Coastguard Worker if (!WaitForProperty("logd.ready", "true", std::chrono::seconds(1))) {
1165*598139dcSAndroid Build Coastguard Worker error(EXIT_FAILURE, 0, "Failed to wait for logd.ready to become true. logd not running?");
1166*598139dcSAndroid Build Coastguard Worker }
1167*598139dcSAndroid Build Coastguard Worker
1168*598139dcSAndroid Build Coastguard Worker while (!max_count_ || print_count_ < max_count_) {
1169*598139dcSAndroid Build Coastguard Worker struct log_msg log_msg;
1170*598139dcSAndroid Build Coastguard Worker int ret = android_logger_list_read(logger_list.get(), &log_msg);
1171*598139dcSAndroid Build Coastguard Worker if (!ret) {
1172*598139dcSAndroid Build Coastguard Worker error(EXIT_FAILURE, 0, R"init(Unexpected EOF!
1173*598139dcSAndroid Build Coastguard Worker
1174*598139dcSAndroid Build Coastguard Worker This means that either the device shut down, logd crashed, or this instance of logcat was unable to read log
1175*598139dcSAndroid Build Coastguard Worker messages as quickly as they were being produced.
1176*598139dcSAndroid Build Coastguard Worker
1177*598139dcSAndroid Build Coastguard Worker If you have enabled significant logging, look into using the -G option to increase log buffer sizes.)init");
1178*598139dcSAndroid Build Coastguard Worker }
1179*598139dcSAndroid Build Coastguard Worker
1180*598139dcSAndroid Build Coastguard Worker if (ret < 0) {
1181*598139dcSAndroid Build Coastguard Worker if (ret == -EAGAIN || ret == -EWOULDBLOCK || ret == -ETIMEDOUT) {
1182*598139dcSAndroid Build Coastguard Worker // For non-blocking mode, a socket with a 2s timeout is used to read logs.
1183*598139dcSAndroid Build Coastguard Worker // Either recv returned -EAGAIN or -EWOULDBLOCK (see man recv)
1184*598139dcSAndroid Build Coastguard Worker // or connect returned -EAGAIN or -ETIMEOUT.
1185*598139dcSAndroid Build Coastguard Worker // In either case, the caller should call logcat again at a later time.
1186*598139dcSAndroid Build Coastguard Worker break;
1187*598139dcSAndroid Build Coastguard Worker }
1188*598139dcSAndroid Build Coastguard Worker if (ret == -EIO) {
1189*598139dcSAndroid Build Coastguard Worker error(EXIT_FAILURE, 0, "Unexpected EOF!");
1190*598139dcSAndroid Build Coastguard Worker }
1191*598139dcSAndroid Build Coastguard Worker if (ret == -EINVAL) {
1192*598139dcSAndroid Build Coastguard Worker error(EXIT_FAILURE, 0, "Unexpected length.");
1193*598139dcSAndroid Build Coastguard Worker }
1194*598139dcSAndroid Build Coastguard Worker error(EXIT_FAILURE, errno, "Logcat read failure");
1195*598139dcSAndroid Build Coastguard Worker }
1196*598139dcSAndroid Build Coastguard Worker
1197*598139dcSAndroid Build Coastguard Worker if (!__android_log_id_is_valid(static_cast<log_id_t>(log_msg.id()))) {
1198*598139dcSAndroid Build Coastguard Worker error(EXIT_FAILURE, 0, "Unexpected log id (%d) out of bounds.", log_msg.id());
1199*598139dcSAndroid Build Coastguard Worker }
1200*598139dcSAndroid Build Coastguard Worker
1201*598139dcSAndroid Build Coastguard Worker if (!uids.empty() && uids.count(log_msg.entry.uid) == 0) {
1202*598139dcSAndroid Build Coastguard Worker continue;
1203*598139dcSAndroid Build Coastguard Worker }
1204*598139dcSAndroid Build Coastguard Worker
1205*598139dcSAndroid Build Coastguard Worker switch (output_type_) {
1206*598139dcSAndroid Build Coastguard Worker case BINARY:
1207*598139dcSAndroid Build Coastguard Worker WriteFully(&log_msg, log_msg.len());
1208*598139dcSAndroid Build Coastguard Worker break;
1209*598139dcSAndroid Build Coastguard Worker case TEXT:
1210*598139dcSAndroid Build Coastguard Worker case PROTO:
1211*598139dcSAndroid Build Coastguard Worker ProcessBuffer(&log_msg);
1212*598139dcSAndroid Build Coastguard Worker break;
1213*598139dcSAndroid Build Coastguard Worker }
1214*598139dcSAndroid Build Coastguard Worker if (blocking && output_file_ == stdout) fflush(stdout);
1215*598139dcSAndroid Build Coastguard Worker }
1216*598139dcSAndroid Build Coastguard Worker return EXIT_SUCCESS;
1217*598139dcSAndroid Build Coastguard Worker }
1218*598139dcSAndroid Build Coastguard Worker
main(int argc,char ** argv)1219*598139dcSAndroid Build Coastguard Worker int main(int argc, char** argv) {
1220*598139dcSAndroid Build Coastguard Worker Logcat logcat;
1221*598139dcSAndroid Build Coastguard Worker return logcat.Run(argc, argv);
1222*598139dcSAndroid Build Coastguard Worker }
1223