Merge "Use vsnprintf(3) in syslog(3)."

This commit is contained in:
Elliott Hughes 2014-07-28 16:44:57 +00:00 committed by Gerrit Code Review
commit 8c66fd798e
3 changed files with 47 additions and 16 deletions

View file

@ -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");
}

View file

@ -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);
}

View file

@ -176,14 +176,3 @@ TEST(libc_logging, lld_LLONG_MIN) {
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif // __BIONIC__
}
TEST(libc_logging, m) {
#if defined(__BIONIC__)
char buf[BUFSIZ];
errno = EBADF;
__libc_format_buffer(buf, sizeof(buf), "<%m>");
EXPECT_STREQ("<Bad file number>", buf);
#else // __BIONIC__
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif // __BIONIC__
}