aboutsummaryrefslogtreecommitdiffstats
path: root/libc/bionic/syslog.cpp
diff options
context:
space:
mode:
authorElliott Hughes <enh@google.com>2014-07-25 20:31:47 -0700
committerElliott Hughes <enh@google.com>2014-07-28 09:43:21 -0700
commitf1e83cc34a58761fc7bc5178c6f283db85d6057a (patch)
treebfdd6078020a74f855f320fbcb87f60de7bd47e6 /libc/bionic/syslog.cpp
parent1a918d9be83013cdc8e194edf35b5295eba4ab1c (diff)
downloadandroid_bionic-f1e83cc34a58761fc7bc5178c6f283db85d6057a.tar.gz
android_bionic-f1e83cc34a58761fc7bc5178c6f283db85d6057a.tar.bz2
android_bionic-f1e83cc34a58761fc7bc5178c6f283db85d6057a.zip
Use vsnprintf(3) in syslog(3).
It seemed like a clever trick to use the internal log message formatting code in syslog(3), but on reflection that means you can't (for example) format floating point numbers. This patch switches us over to using good old vsnprintf(3), even though that requires us to jump through a few hoops. There's no obvious way to unit test this, so I wrote a little program and ran that. (cherry-pick of b1b60c30bf321c0fc02264b953b5c16c49d34457.) Bug: 14292866 Change-Id: I9c83500ba9cbb209b6f496067a91bf69434eeef5
Diffstat (limited to 'libc/bionic/syslog.cpp')
-rw-r--r--libc/bionic/syslog.cpp48
1 files changed, 47 insertions, 1 deletions
diff --git a/libc/bionic/syslog.cpp b/libc/bionic/syslog.cpp
index 29f892a20..d8b8b190d 100644
--- a/libc/bionic/syslog.cpp
+++ b/libc/bionic/syslog.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <errno.h>
#include <stdlib.h>
#include <syslog.h>
@@ -47,6 +48,8 @@ void syslog(int priority, const char* fmt, ...) {
}
void vsyslog(int priority, const char* fmt, va_list args) {
+ int caller_errno = errno;
+
// Check whether we're supposed to be logging messages of this priority.
if ((syslog_priority_mask & LOG_MASK(LOG_PRI(priority))) == 0) {
return;
@@ -71,5 +74,48 @@ void vsyslog(int priority, const char* fmt, va_list args) {
android_log_priority = ANDROID_LOG_DEBUG;
}
- __libc_format_log_va_list(android_log_priority, log_tag, fmt, args);
+ // glibc's printf family support %m directly, but our BSD-based one doesn't.
+ // If the format string seems to contain "%m", rewrite it.
+ const char* log_fmt = fmt;
+ if (strstr(fmt, "%m") != NULL) {
+ size_t dst_len = 1024;
+ char* dst = reinterpret_cast<char*>(malloc(dst_len));
+ log_fmt = dst;
+
+ const char* src = fmt;
+ for (; dst_len > 0 && *src != '\0'; ++src) {
+ if (*src == '%' && *(src + 1) == 'm') {
+ // Expand %m.
+ size_t n = strlcpy(dst, strerror(caller_errno), dst_len);
+ if (n >= dst_len) {
+ n = dst_len;
+ }
+ dst += n;
+ dst_len -= n;
+ ++src;
+ } else if (*src == '%' && *(src + 1) == '%') {
+ // We need to copy pairs of '%'s so the %m test works.
+ if (dst_len <= 2) {
+ break;
+ }
+ *dst++ = '%'; --dst_len;
+ *dst++ = '%'; --dst_len;
+ ++src;
+ } else {
+ *dst++ = *src; --dst_len;
+ }
+ }
+ *dst = '\0';
+ }
+
+ // We can't let __libc_format_log do the formatting because it doesn't support
+ // all the printf functionality.
+ char log_line[1024];
+ vsnprintf(log_line, sizeof(log_line), log_fmt, args);
+
+ if (log_fmt != fmt) {
+ free(const_cast<char*>(log_fmt));
+ }
+
+ __libc_format_log(android_log_priority, log_tag, "%s", log_line);
}