Merge "logd: klogd crash"
diff --git a/adb/Android.mk b/adb/Android.mk
index 7c029be..3512323 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -111,7 +111,7 @@
# Even though we're building a static library (and thus there's no link step for
# this to take effect), this adds the includes to our path.
-LOCAL_STATIC_LIBRARIES := libcrypto_utils_static libcrypto_static libbase
+LOCAL_STATIC_LIBRARIES := libcrypto_utils libcrypto libbase
include $(BUILD_STATIC_LIBRARY)
@@ -134,7 +134,7 @@
# Even though we're building a static library (and thus there's no link step for
# this to take effect), this adds the includes to our path.
-LOCAL_STATIC_LIBRARIES := libcrypto_utils_static libcrypto_static libbase
+LOCAL_STATIC_LIBRARIES := libcrypto_utils libcrypto libbase
LOCAL_C_INCLUDES_windows := development/host/windows/usb/api/
LOCAL_MULTILIB := first
@@ -154,7 +154,7 @@
shell_service_test.cpp \
LOCAL_SANITIZE := $(adb_target_sanitize)
-LOCAL_STATIC_LIBRARIES := libadbd libcrypto_utils_static libcrypto_static
+LOCAL_STATIC_LIBRARIES := libadbd libcrypto_utils libcrypto
LOCAL_SHARED_LIBRARIES := liblog libbase libcutils
include $(BUILD_NATIVE_TEST)
@@ -194,8 +194,8 @@
LOCAL_SHARED_LIBRARIES := libbase
LOCAL_STATIC_LIBRARIES := \
libadb \
- libcrypto_utils_static \
- libcrypto_static \
+ libcrypto_utils \
+ libcrypto \
libcutils \
libdiagnose_usb \
@@ -257,8 +257,8 @@
LOCAL_STATIC_LIBRARIES := \
libadb \
libbase \
- libcrypto_utils_static \
- libcrypto_static \
+ libcrypto_utils \
+ libcrypto \
libdiagnose_usb \
liblog \
@@ -334,8 +334,8 @@
libsquashfs_utils \
libcutils \
libbase \
- libcrypto_utils_static \
- libcrypto_static \
+ libcrypto_utils \
+ libcrypto \
libminijail \
libdebuggerd_client \
diff --git a/adb/sysdeps_win32.cpp b/adb/sysdeps_win32.cpp
index ee27406..109a548 100644
--- a/adb/sysdeps_win32.cpp
+++ b/adb/sysdeps_win32.cpp
@@ -952,7 +952,7 @@
_socket_set_errno(err);
return -1;
}
- std::unique_ptr<struct addrinfo, decltype(freeaddrinfo)*> addrinfo(addrinfo_ptr, freeaddrinfo);
+ std::unique_ptr<struct addrinfo, decltype(&freeaddrinfo)> addrinfo(addrinfo_ptr, freeaddrinfo);
addrinfo_ptr = nullptr;
// TODO: Try all the addresses if there's more than one? This just uses
diff --git a/fs_mgr/Android.mk b/fs_mgr/Android.mk
index 7da3ca4..d6b699b 100644
--- a/fs_mgr/Android.mk
+++ b/fs_mgr/Android.mk
@@ -7,8 +7,8 @@
libfec \
libfec_rs \
libbase \
- libcrypto_utils_static \
- libcrypto_static \
+ libcrypto_utils \
+ libcrypto \
libext4_utils_static \
libsquashfs_utils \
libselinux
diff --git a/init/Android.mk b/init/Android.mk
index 7aa3c3f..5888456 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -94,8 +94,8 @@
libc \
libselinux \
liblog \
- libcrypto_utils_static \
- libcrypto_static \
+ libcrypto_utils \
+ libcrypto \
libc++_static \
libdl \
libsparse_static \
diff --git a/libcrypto_utils/Android.bp b/libcrypto_utils/Android.bp
new file mode 100644
index 0000000..ca7bd31
--- /dev/null
+++ b/libcrypto_utils/Android.bp
@@ -0,0 +1,37 @@
+//
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_library {
+ name: "libcrypto_utils",
+ host_supported: true,
+ srcs: [
+ "android_pubkey.c",
+ ],
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ "-std=c99",
+ ],
+ local_include_dirs: ["include"],
+ export_include_dirs: ["include"],
+ shared_libs: ["libcrypto"],
+ target: {
+ windows: {
+ enabled: true,
+ },
+ },
+}
diff --git a/libcrypto_utils/Android.mk b/libcrypto_utils/Android.mk
deleted file mode 100644
index b6d2204..0000000
--- a/libcrypto_utils/Android.mk
+++ /dev/null
@@ -1,56 +0,0 @@
-#
-# Copyright (C) 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := libcrypto_utils
-LOCAL_SRC_FILES := android_pubkey.c
-LOCAL_CFLAGS := -Wall -Werror -Wextra -std=c99
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_SHARED_LIBRARIES := libcrypto
-include $(BUILD_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := libcrypto_utils
-LOCAL_SRC_FILES := android_pubkey.c
-LOCAL_CFLAGS := -Wall -Werror -Wextra -std=c99
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_SHARED_LIBRARIES := libcrypto
-include $(BUILD_HOST_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := libcrypto_utils_static
-LOCAL_SRC_FILES := android_pubkey.c
-LOCAL_CFLAGS := -Wall -Werror -Wextra -std=c99
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_STATIC_LIBRARIES := libcrypto
-include $(BUILD_STATIC_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := libcrypto_utils_static
-LOCAL_MODULE_HOST_OS := darwin linux windows
-LOCAL_SRC_FILES := android_pubkey.c
-LOCAL_CFLAGS := -Wall -Werror -Wextra -std=c99
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_STATIC_LIBRARIES := libcrypto_static
-include $(BUILD_HOST_STATIC_LIBRARY)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/libutils/SharedBuffer.cpp b/libutils/SharedBuffer.cpp
index f3d6d8f..dc96aef 100644
--- a/libutils/SharedBuffer.cpp
+++ b/libutils/SharedBuffer.cpp
@@ -114,8 +114,9 @@
int32_t SharedBuffer::release(uint32_t flags) const
{
int32_t prev = 1;
- if (onlyOwner() || ((prev = mRefs.fetch_sub(1, std::memory_order_release) == 1)
- && (atomic_thread_fence(std::memory_order_acquire), true))) {
+ if (onlyOwner()
+ || (((prev = mRefs.fetch_sub(1, std::memory_order_release)) == 1)
+ && (atomic_thread_fence(std::memory_order_acquire), true))) {
mRefs.store(0, std::memory_order_relaxed);
if ((flags & eKeepStorage) == 0) {
free(const_cast<SharedBuffer*>(this));
diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp
index 5bac717..7e2bac7 100644
--- a/logcat/logcat.cpp
+++ b/logcat/logcat.cpp
@@ -26,6 +26,7 @@
#include <string>
#include <android-base/file.h>
+#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <cutils/sched_policy.h>
#include <cutils/sockets.h>
@@ -109,29 +110,27 @@
(g_maxRotatedLogs > 0) ? (int) (floor(log10(g_maxRotatedLogs) + 1)) : 0;
for (int i = g_maxRotatedLogs ; i > 0 ; i--) {
- char *file0, *file1;
+ std::string file1 = android::base::StringPrintf(
+ "%s.%.*d", g_outputFileName, maxRotationCountDigits, i);
- asprintf(&file1, "%s.%.*d", g_outputFileName, maxRotationCountDigits, i);
-
+ std::string file0;
if (i - 1 == 0) {
- asprintf(&file0, "%s", g_outputFileName);
+ file0 = android::base::StringPrintf("%s", g_outputFileName);
} else {
- asprintf(&file0, "%s.%.*d", g_outputFileName, maxRotationCountDigits, i - 1);
+ file0 = android::base::StringPrintf(
+ "%s.%.*d", g_outputFileName, maxRotationCountDigits, i - 1);
}
- if (!file0 || !file1) {
+ if ((file0.length() == 0) || (file1.length() == 0)) {
perror("while rotating log files");
break;
}
- err = rename(file0, file1);
+ err = rename(file0.c_str(), file1.c_str());
if (err < 0 && errno != ENOENT) {
perror("while rotating log files");
}
-
- free(file1);
- free(file0);
}
g_outFD = openLogFile(g_outputFileName);
@@ -231,13 +230,15 @@
}
}
-static void setupOutput()
-{
-
+static void setupOutputAndSchedulingPolicy(bool blocking) {
if (g_outputFileName == NULL) {
g_outFD = STDOUT_FILENO;
+ return;
+ }
- } else {
+ if (blocking) {
+ // Lower priority and set to batch scheduling if we are saving
+ // the logs into files and taking continuous content.
if (set_sched_policy(0, SP_BACKGROUND) < 0) {
fprintf(stderr, "failed to set background scheduling policy\n");
}
@@ -251,26 +252,26 @@
if (setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_BACKGROUND) < 0) {
fprintf(stderr, "failed set to priority\n");
}
-
- g_outFD = openLogFile (g_outputFileName);
-
- if (g_outFD < 0) {
- logcat_panic(false, "couldn't open output file");
- }
-
- struct stat statbuf;
- if (fstat(g_outFD, &statbuf) == -1) {
- close(g_outFD);
- logcat_panic(false, "couldn't get output file stat\n");
- }
-
- if ((size_t) statbuf.st_size > SIZE_MAX || statbuf.st_size < 0) {
- close(g_outFD);
- logcat_panic(false, "invalid output file stat\n");
- }
-
- g_outByteCount = statbuf.st_size;
}
+
+ g_outFD = openLogFile (g_outputFileName);
+
+ if (g_outFD < 0) {
+ logcat_panic(false, "couldn't open output file");
+ }
+
+ struct stat statbuf;
+ if (fstat(g_outFD, &statbuf) == -1) {
+ close(g_outFD);
+ logcat_panic(false, "couldn't get output file stat\n");
+ }
+
+ if ((size_t) statbuf.st_size > SIZE_MAX || statbuf.st_size < 0) {
+ close(g_outFD);
+ logcat_panic(false, "invalid output file stat\n");
+ }
+
+ g_outByteCount = statbuf.st_size;
}
static void show_help(const char *cmd)
@@ -284,6 +285,8 @@
" Rotate log every kbytes. Requires -f option\n"
" -n <count>, --rotate-count=<count>\n"
" Sets max number of rotated logs to <count>, default 4\n"
+ " --id=<id> If the signature id for logging to file changes, then clear\n"
+ " the fileset and continue\n"
" -v <format>, --format=<format>\n"
" Sets log print format verb and adverbs, where <format> is:\n"
" brief long process raw tag thread threadtime time\n"
@@ -443,7 +446,7 @@
return t.strptime(cp, "%s.%q");
}
-// Find last logged line in gestalt of all matching existing output files
+// Find last logged line in <outputFileName>, or <outputFileName>.1
static log_time lastLogTime(char *outputFileName) {
log_time retval(log_time::EPOCH);
if (!outputFileName) {
@@ -468,24 +471,18 @@
return retval;
}
- clockid_t clock_type = android_log_clockid();
- log_time now(clock_type);
- bool monotonic = clock_type == CLOCK_MONOTONIC;
+ log_time now(android_log_clockid());
size_t len = strlen(file);
log_time modulo(0, NS_PER_SEC);
struct dirent *dp;
while ((dp = readdir(dir.get())) != NULL) {
- if ((dp->d_type != DT_REG)
- // If we are using realtime, check all files that match the
- // basename for latest time. If we are using monotonic time
- // then only check the main file because time cycles on
- // every reboot.
- || strncmp(dp->d_name, file, len + monotonic)
- || (dp->d_name[len]
- && ((dp->d_name[len] != '.')
- || !isdigit(dp->d_name[len+1])))) {
+ if ((dp->d_type != DT_REG) ||
+ (strncmp(dp->d_name, file, len) != 0) ||
+ (dp->d_name[len] &&
+ ((dp->d_name[len] != '.') ||
+ (strtoll(dp->d_name + 1, NULL, 10) != 1)))) {
continue;
}
@@ -547,6 +544,7 @@
unsigned long setLogSize = 0;
int getPruneList = 0;
char *setPruneList = NULL;
+ char *setId = NULL;
int printStatistics = 0;
int mode = ANDROID_LOG_RDONLY;
const char *forceFilters = NULL;
@@ -574,6 +572,7 @@
int option_index = 0;
// list of long-argument only strings for later comparison
static const char pid_str[] = "pid";
+ static const char id_str[] = "id";
static const char wrap_str[] = "wrap";
static const char print_str[] = "print";
static const struct option long_options[] = {
@@ -588,6 +587,7 @@
{ "grep", required_argument, NULL, 'e' },
// hidden and undocumented reserved alias for --max-count
{ "head", required_argument, NULL, 'm' },
+ { id_str, required_argument, NULL, 0 },
{ "last", no_argument, NULL, 'L' },
{ "max-count", required_argument, NULL, 'm' },
{ pid_str, required_argument, NULL, 0 },
@@ -613,7 +613,7 @@
switch (ret) {
case 0:
- // One of the long options
+ // only long options
if (long_options[option_index].name == pid_str) {
// ToDo: determine runtime PID_MAX?
if (!getSizeTArg(optarg, &pid, 1)) {
@@ -644,6 +644,10 @@
g_printItAnyways = true;
break;
}
+ if (long_options[option_index].name == id_str) {
+ setId = optarg && optarg[0] ? optarg : NULL;
+ break;
+ }
break;
case 's':
@@ -657,7 +661,7 @@
break;
case 'L':
- mode |= ANDROID_LOG_PSTORE;
+ mode |= ANDROID_LOG_RDONLY | ANDROID_LOG_PSTORE | ANDROID_LOG_NONBLOCK;
break;
case 'd':
@@ -968,7 +972,20 @@
logcat_panic(true, "-r requires -f as well\n");
}
- setupOutput();
+ if (setId != NULL) {
+ if (g_outputFileName == NULL) {
+ logcat_panic(true, "--id='%s' requires -f as well\n", setId);
+ }
+
+ std::string file_name = android::base::StringPrintf("%s.id", g_outputFileName);
+ std::string file;
+ bool file_ok = android::base::ReadFileToString(file_name, &file);
+ android::base::WriteStringToFile(setId, file_name,
+ S_IRUSR | S_IWUSR, getuid(), getgid());
+ if (!file_ok || (file.compare(setId) == 0)) {
+ setId = NULL;
+ }
+ }
if (hasSetLogFormat == 0) {
const char* logFormat = getenv("ANDROID_PRINTF_LOG");
@@ -1034,34 +1051,33 @@
continue;
}
- if (clearLog) {
+ if (clearLog || setId) {
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;
+ std::string file;
if (i == 0) {
- asprintf(&file, "%s", g_outputFileName);
+ file = android::base::StringPrintf("%s", g_outputFileName);
} else {
- asprintf(&file, "%s.%.*d", g_outputFileName, maxRotationCountDigits, i);
+ file = android::base::StringPrintf("%s.%.*d",
+ g_outputFileName, maxRotationCountDigits, i);
}
- if (!file) {
+ if (file.length() == 0) {
perror("while clearing log files");
clearFail = clearFail ?: dev->device;
break;
}
- err = unlink(file);
+ err = unlink(file.c_str());
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;
@@ -1177,7 +1193,6 @@
return EXIT_SUCCESS;
}
-
if (getLogSize) {
return EXIT_SUCCESS;
}
@@ -1188,6 +1203,8 @@
return EXIT_SUCCESS;
}
+ setupOutputAndSchedulingPolicy((mode & ANDROID_LOG_NONBLOCK) == 0);
+
//LOG_EVENT_INT(10, 12345);
//LOG_EVENT_LONG(11, 0x1122334455667788LL);
//LOG_EVENT_STRING(0, "whassup, doc?");
diff --git a/logcat/logcatd.rc b/logcat/logcatd.rc
index ce1a451..1da1942 100644
--- a/logcat/logcatd.rc
+++ b/logcat/logcatd.rc
@@ -35,7 +35,7 @@
# all exec/services are called with umask(077), so no gain beyond 0700
mkdir /data/misc/logd 0700 logd log
# logd for write to /data/misc/logd, log group for read from pstore (-L)
- exec - logd log -- /system/bin/logcat -L -b ${logd.logpersistd.buffer:-all} -v threadtime -v usec -v printable -D -f /data/misc/logd/logcat -r 1024 -n ${logd.logpersistd.size:-256}
+ exec - logd log -- /system/bin/logcat -L -b ${logd.logpersistd.buffer:-all} -v threadtime -v usec -v printable -D -f /data/misc/logd/logcat -r 1024 -n ${logd.logpersistd.size:-256} --id=${ro.build.id}
start logcatd
# stop logcatd service and clear data
@@ -56,7 +56,7 @@
stop logcatd
# logcatd service
-service logcatd /system/bin/logcat -b ${logd.logpersistd.buffer:-all} -v threadtime -v usec -v printable -D -f /data/misc/logd/logcat -r 1024 -n ${logd.logpersistd.size:-256}
+service logcatd /system/bin/logcat -b ${logd.logpersistd.buffer:-all} -v threadtime -v usec -v printable -D -f /data/misc/logd/logcat -r 1024 -n ${logd.logpersistd.size:-256} --id=${ro.build.id}
class late_start
disabled
# logd for write to /data/misc/logd, log group for read from log daemon
diff --git a/logcat/logpersist b/logcat/logpersist
index f0e7d42..c09b6b2 100755
--- a/logcat/logpersist
+++ b/logcat/logpersist
@@ -17,8 +17,9 @@
;;
esac
+log_uid=logd
log_tag_property=persist.log.tag
-data=/data/misc/logd
+data=/data/misc/logd/logcat
service=logcatd
size_default=256
buffer_default=all
@@ -74,11 +75,12 @@
if [ -n "${size}${buffer}" -o "true" = "${clear}" ]; then
echo WARNING: Can not use --clear, --size or --buffer with ${progname%.*}.cat >&2
fi
- su logd ls "${data}" |
+ su ${log_uid} ls "${data%/*}" |
tr -d '\r' |
sort -ru |
- sed "s#^#${data}/#" |
- su logd xargs cat
+ sed "s#^#${data%/*}/#" |
+ grep "${data}[.]*[0-9]*\$" |
+ su ${log_uid} xargs cat
;;
*.start)
current_buffer="`getprop ${property#persist.}.buffer`"
@@ -139,7 +141,7 @@
sleep 1
getprop ${property#persist.}
# also generate an error return code if not found running
- pgrep -u ${data##*/} ${service%d}
+ pgrep -u ${log_uid} ${service%d}
;;
*.stop)
if [ -n "${size}${buffer}" ]; then
@@ -171,6 +173,6 @@
if [ X"${log_tag}" != X"`getprop ${log_tag_property}`" ] ||
[ X"${logd_logpersistd}" != X"`getprop ${property}`" ]; then
- echo "WARNING: killing Settings" >&2
+ echo "WARNING: killing Settings application to pull in new values" >&2
am force-stop com.android.settings
fi
diff --git a/logcat/tests/logcat_test.cpp b/logcat/tests/logcat_test.cpp
index 0043d1b..3daee13 100644
--- a/logcat/tests/logcat_test.cpp
+++ b/logcat/tests/logcat_test.cpp
@@ -20,6 +20,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
@@ -848,6 +849,75 @@
EXPECT_FALSE(system(command));
}
+static int logrotate_count_id(const char *logcat_cmd, const char *tmp_out_dir) {
+
+ static const char log_filename[] = "log.txt";
+ char command[strlen(tmp_out_dir) + strlen(logcat_cmd) + strlen(log_filename) + 32];
+
+ snprintf(command, sizeof(command), logcat_cmd, tmp_out_dir, log_filename);
+
+ int ret;
+ EXPECT_FALSE((ret = system(command)));
+ if (ret) {
+ return -1;
+ }
+ std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(tmp_out_dir), closedir);
+ EXPECT_NE(nullptr, dir);
+ if (!dir) {
+ return -1;
+ }
+ struct dirent *entry;
+ int count = 0;
+ while ((entry = readdir(dir.get()))) {
+ if (strncmp(entry->d_name, log_filename, sizeof(log_filename) - 1)) {
+ continue;
+ }
+ ++count;
+ }
+ return count;
+}
+
+TEST(logcat, logrotate_id) {
+ static const char logcat_cmd[] = "logcat -b all -d -f %s/%s -n 32 -r 1 --id=test";
+ static const char logcat_short_cmd[] = "logcat -b all -t 10 -f %s/%s -n 32 -r 1 --id=test";
+ static const char tmp_out_dir_form[] = "/data/local/tmp/logcat.logrotate.XXXXXX";
+ static const char log_filename[] = "log.txt";
+ char tmp_out_dir[strlen(tmp_out_dir_form) + 1];
+ ASSERT_TRUE(NULL != mkdtemp(strcpy(tmp_out_dir, tmp_out_dir_form)));
+
+ EXPECT_EQ(34, logrotate_count_id(logcat_cmd, tmp_out_dir));
+ EXPECT_EQ(34, logrotate_count_id(logcat_short_cmd, tmp_out_dir));
+
+ char id_file[strlen(tmp_out_dir_form) + strlen(log_filename) + 5];
+ snprintf(id_file, sizeof(id_file), "%s/%s.id", tmp_out_dir, log_filename);
+ if (getuid() != 0) {
+ chmod(id_file, 0);
+ EXPECT_EQ(34, logrotate_count_id(logcat_short_cmd, tmp_out_dir));
+ }
+ unlink(id_file);
+ EXPECT_EQ(34, logrotate_count_id(logcat_short_cmd, tmp_out_dir));
+
+ FILE *fp = fopen(id_file, "w");
+ if (fp) {
+ fprintf(fp, "not_a_test");
+ fclose(fp);
+ }
+ if (getuid() != 0) {
+ chmod(id_file, 0); // API to preserve content even with signature change
+ ASSERT_EQ(34, logrotate_count_id(logcat_short_cmd, tmp_out_dir));
+ chmod(id_file, 0600);
+ }
+
+ int new_signature;
+ EXPECT_LE(2, (new_signature = logrotate_count_id(logcat_short_cmd, tmp_out_dir)));
+ EXPECT_GT(34, new_signature);
+
+ static const char cleanup_cmd[] = "rm -rf %s";
+ char command[strlen(cleanup_cmd) + strlen(tmp_out_dir_form)];
+ 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),