diff options
author | Elliott Hughes <enh@google.com> | 2014-07-28 16:44:57 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2014-07-24 20:55:36 +0000 |
commit | 8c66fd798ed5b7cefe1568d9a000d01b69d29dd9 (patch) | |
tree | bfdd6078020a74f855f320fbcb87f60de7bd47e6 /libc | |
parent | 1a918d9be83013cdc8e194edf35b5295eba4ab1c (diff) | |
parent | f1e83cc34a58761fc7bc5178c6f283db85d6057a (diff) | |
download | android_bionic-8c66fd798ed5b7cefe1568d9a000d01b69d29dd9.tar.gz android_bionic-8c66fd798ed5b7cefe1568d9a000d01b69d29dd9.tar.bz2 android_bionic-8c66fd798ed5b7cefe1568d9a000d01b69d29dd9.zip |
Merge "Use vsnprintf(3) in syslog(3)."
Diffstat (limited to 'libc')
-rw-r--r-- | libc/bionic/libc_logging.cpp | 4 | ||||
-rw-r--r-- | libc/bionic/syslog.cpp | 48 |
2 files changed, 47 insertions, 5 deletions
diff --git a/libc/bionic/libc_logging.cpp b/libc/bionic/libc_logging.cpp index b57e24297..d0172edaa 100644 --- a/libc/bionic/libc_logging.cpp +++ b/libc/bionic/libc_logging.cpp @@ -230,7 +230,6 @@ static void SendRepeat(Out& o, char ch, int count) { /* Perform formatted output to an output target 'o' */ template <typename Out> static void out_vformat(Out& o, const char* format, va_list args) { - int caller_errno = errno; int nn = 0; for (;;) { @@ -379,9 +378,6 @@ static void out_vformat(Out& o, const char* format, va_list args) { } else if (c == '%') { buffer[0] = '%'; buffer[1] = '\0'; - } else if (c == 'm') { - // syslog-like %m for strerror(errno). - str = strerror(caller_errno); } else { __assert(__FILE__, __LINE__, "conversion specifier unsupported"); } 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); } |