logcat: clear when specifying file output

If -c and -f are both specified, clear the files rather
than notifying the logger to clear its data. The -f then
acts like a switch between clearing the in-memory log
data, or the on-disk logrotate data.

Bug: 28936216
Change-Id: Ib1d1fb46ea09f81a2fd9bebb6c8f0f9f2355f6e8
This commit is contained in:
Mark Salyzyn 2016-06-06 14:56:00 -07:00
parent 95428817d6
commit b7d059bb2f
2 changed files with 106 additions and 1 deletions

View File

@ -290,6 +290,7 @@ static void show_help(const char *cmd)
" tag thread threadtime time uid usec UTC year zone\n"
" -D, --dividers Print dividers between each log buffer\n"
" -c, --clear Clear (flush) the entire log and exit\n"
" if Log to File specified, clear fileset instead\n"
" -d Dump the log and then exit (don't block)\n"
" -e <expr>, --regex=<expr>\n"
" Only print lines where the log message matches <expr>\n"
@ -1033,7 +1034,35 @@ int main(int argc, char **argv)
}
if (clearLog) {
if (android_logger_clear(dev->logger)) {
if (g_outputFileName) {
int maxRotationCountDigits =
(g_maxRotatedLogs > 0) ? (int) (floor(log10(g_maxRotatedLogs) + 1)) : 0;
for (int i = g_maxRotatedLogs ; i >= 0 ; --i) {
char *file;
if (i == 0) {
asprintf(&file, "%s", g_outputFileName);
} else {
asprintf(&file, "%s.%.*d", g_outputFileName, maxRotationCountDigits, i);
}
if (!file) {
perror("while clearing log files");
clearFail = clearFail ?: dev->device;
break;
}
err = unlink(file);
if (err < 0 && errno != ENOENT && clearFail == NULL) {
perror("while clearing log files");
clearFail = dev->device;
}
free(file);
}
} else if (android_logger_clear(dev->logger)) {
clearFail = clearFail ?: dev->device;
}
}

View File

@ -772,6 +772,82 @@ TEST(logcat, logrotate_continue) {
EXPECT_FALSE(system(command));
}
TEST(logcat, logrotate_clear) {
static const char tmp_out_dir_form[] = "/data/local/tmp/logcat.logrotate.XXXXXX";
char tmp_out_dir[sizeof(tmp_out_dir_form)];
ASSERT_TRUE(NULL != mkdtemp(strcpy(tmp_out_dir, tmp_out_dir_form)));
static const char log_filename[] = "log.txt";
static const unsigned num_val = 32;
static const char logcat_cmd[] = "logcat -b all -d -f %s/%s -n %d -r 1";
static const char clear_cmd[] = " -c";
static const char cleanup_cmd[] = "rm -rf %s";
char command[sizeof(tmp_out_dir) + sizeof(logcat_cmd) + sizeof(log_filename) + sizeof(clear_cmd) + 32];
// Run command with all data
{
snprintf(command, sizeof(command) - sizeof(clear_cmd),
logcat_cmd, tmp_out_dir, log_filename, num_val);
int ret;
EXPECT_FALSE((ret = system(command)));
if (ret) {
snprintf(command, sizeof(command), cleanup_cmd, tmp_out_dir);
EXPECT_FALSE(system(command));
return;
}
std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(tmp_out_dir), closedir);
EXPECT_NE(nullptr, dir);
if (!dir) {
snprintf(command, sizeof(command), cleanup_cmd, tmp_out_dir);
EXPECT_FALSE(system(command));
return;
}
struct dirent *entry;
unsigned count = 0;
while ((entry = readdir(dir.get()))) {
if (strncmp(entry->d_name, log_filename, sizeof(log_filename) - 1)) {
continue;
}
++count;
}
EXPECT_EQ(count, num_val + 1);
}
{
// Now with -c option tacked onto the end
strcat(command, clear_cmd);
int ret;
EXPECT_FALSE((ret = system(command)));
if (ret) {
snprintf(command, sizeof(command), cleanup_cmd, tmp_out_dir);
EXPECT_FALSE(system(command));
return;
}
std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(tmp_out_dir), closedir);
EXPECT_NE(nullptr, dir);
if (!dir) {
snprintf(command, sizeof(command), cleanup_cmd, tmp_out_dir);
EXPECT_FALSE(system(command));
return;
}
struct dirent *entry;
unsigned count = 0;
while ((entry = readdir(dir.get()))) {
if (strncmp(entry->d_name, log_filename, sizeof(log_filename) - 1)) {
continue;
}
fprintf(stderr, "Found %s/%s!!!\n", tmp_out_dir, entry->d_name);
++count;
}
EXPECT_EQ(count, 0U);
}
snprintf(command, sizeof(command), cleanup_cmd, tmp_out_dir);
EXPECT_FALSE(system(command));
}
TEST(logcat, logrotate_nodir) {
// expect logcat to error out on writing content and exit(1) for nodir
EXPECT_EQ(W_EXITCODE(1, 0),