summaryrefslogtreecommitdiffstats
path: root/logcat
diff options
context:
space:
mode:
authorMark Salyzyn <salyzyn@google.com>2017-02-17 13:15:51 -0800
committerMark Salyzyn <salyzyn@google.com>2017-02-22 15:10:56 -0800
commite3d0c968ac4bf6de2a0cacfb956ee5d8df8e7583 (patch)
tree6b26a1222f9f0591765111c0fa1bfb36c95574ea /logcat
parent3e3aaca4c3f48a36d3725441d9d487d7aa0e7209 (diff)
downloadcore-e3d0c968ac4bf6de2a0cacfb956ee5d8df8e7583.tar.gz
core-e3d0c968ac4bf6de2a0cacfb956ee5d8df8e7583.tar.bz2
core-e3d0c968ac4bf6de2a0cacfb956ee5d8df8e7583.zip
liblogcat: add simple stdout redirection
Provide minimal redirection functionality, adding stdout redirection to the existing stderr redirection parsing. - stderr and stdout redirection do _not_ support append, will treat like write only. - stderr redirection does _not_ support filename. Only 2>&1 to join stderr and stdout and 2>/dev/null to drop content on floor. - stdout redirection supports filename only. - stderr 2>&1 redirection must be last for shell compatibility. - preserve 2>&1 through file rotation (bugfix) Test: logcat-benchmarks --benchmark_filter='BM_logcat_popen*|BM_logcat_system*' Bug: 35326290 Change-Id: Id36b59358167f21381bd1dbf0bd7a7e10e2a2ed9
Diffstat (limited to 'logcat')
-rw-r--r--logcat/logcat.cpp63
1 files changed, 49 insertions, 14 deletions
diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp
index 7f852d4fb..d67dee56c 100644
--- a/logcat/logcat.cpp
+++ b/logcat/logcat.cpp
@@ -67,8 +67,8 @@ struct android_logcat_context_internal {
std::vector<const char*> argv_hold;
std::vector<std::string> envs;
std::vector<const char*> envp_hold;
- int output_fd;
- int error_fd;
+ int output_fd; // duplication of fileno(output) (below)
+ int error_fd; // duplication of fileno(error) (below)
// library
int fds[2]; // From popen call
@@ -284,6 +284,15 @@ static void rotateLogs(android_logcat_context_internal* context) {
return;
}
context->output = fdopen(context->output_fd, "web");
+ if (context->output == NULL) {
+ logcat_panic(context, HELP_FALSE, "couldn't fdopen output file");
+ return;
+ }
+ if (context->stderr_stdout) {
+ close_error(context);
+ context->error = context->output;
+ context->error_fd = context->output_fd;
+ }
context->outByteCount = 0;
}
@@ -788,6 +797,7 @@ static int __logcat(android_logcat_context_internal* context) {
// Simulate shell stderr redirect parsing
if ((argv[i][0] != '2') || (argv[i][1] != '>')) continue;
+ // Append to file not implemented, just open file
size_t skip = (argv[i][2] == '>') + 2;
if (!strcmp(&argv[i][skip], "/dev/null")) {
context->stderr_null = true;
@@ -799,16 +809,29 @@ static int __logcat(android_logcat_context_internal* context) {
"stderr redirection to file %s unsupported, skipping\n",
&argv[i][skip]);
}
+ // Only the first one
+ break;
+ }
+
+ const char* filename = NULL;
+ for (int i = 0; i < argc; ++i) {
+ // Simulate shell stdout redirect parsing
+ if (argv[i][0] != '>') continue;
+
+ // Append to file not implemented, just open file
+ filename = &argv[i][(argv[i][1] == '>') + 1];
+ // Only the first one
+ break;
}
// Deal with setting up file descriptors and FILE pointers
- if (context->error_fd >= 0) {
+ if (context->error_fd >= 0) { // Is an error file descriptor supplied?
if (context->error_fd == context->output_fd) {
context->stderr_stdout = true;
- } else if (context->stderr_null) {
+ } else if (context->stderr_null) { // redirection told us to close it
close(context->error_fd);
context->error_fd = -1;
- } else {
+ } else { // All Ok, convert error to a FILE pointer
context->error = fdopen(context->error_fd, "web");
if (!context->error) {
context->retval = -errno;
@@ -819,22 +842,32 @@ static int __logcat(android_logcat_context_internal* context) {
}
}
}
- if (context->output_fd >= 0) {
- context->output = fdopen(context->output_fd, "web");
- if (!context->output) {
- context->retval = -errno;
- fprintf(context->stderr_stdout ? stdout : context->error,
- "Failed to fdopen(output_fd=%d) %s\n", context->output_fd,
- strerror(errno));
- goto exit;
+ if (context->output_fd >= 0) { // Is an output file descriptor supplied?
+ if (filename) { // redirect to file, close the supplied file descriptor.
+ close(context->output_fd);
+ context->output_fd = -1;
+ } else { // All Ok, convert output to a FILE pointer
+ context->output = fdopen(context->output_fd, "web");
+ if (!context->output) {
+ context->retval = -errno;
+ fprintf(context->stderr_stdout ? stdout : context->error,
+ "Failed to fdopen(output_fd=%d) %s\n",
+ context->output_fd, strerror(errno));
+ goto exit;
+ }
}
}
+ if (filename) { // We supplied an output file redirected in command line
+ context->output = fopen(filename, "web");
+ }
+ // Deal with 2>&1
if (context->stderr_stdout) context->error = context->output;
+ // Deal with 2>/dev/null
if (context->stderr_null) {
context->error_fd = -1;
context->error = NULL;
}
- // Only happens if output=stdout
+ // Only happens if output=stdout or output=filename
if ((context->output_fd < 0) && context->output) {
context->output_fd = fileno(context->output);
}
@@ -1351,6 +1384,8 @@ static int __logcat(android_logcat_context_internal* context) {
for (int i = optind ; i < argc ; i++) {
// skip stderr redirections of _all_ kinds
if ((argv[i][0] == '2') && (argv[i][1] == '>')) continue;
+ // skip stdout redirections of _all_ kinds
+ if (argv[i][0] == '>') continue;
err = android_log_addFilterString(context->logformat, argv[i]);
if (err < 0) {