From cde1c287b1bbbc128c3378f194a338399438ce51 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Tue, 24 Dec 2013 09:18:42 -0800 Subject: [PATCH] stdio: New module, initially to provide working [v]snprintf() on Windows. This should transparently define snprintf() and vsnprintf() wrappers for use on Windows. CC: Saurabh Shah Signed-off-by: Ben Pfaff --- configure.ac | 4 ++-- lib/.gitignore | 1 + lib/automake.mk | 5 ++++- lib/stdio.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++ lib/stdio.h.in | 43 ++++++++++++++++++++++++++++++++++++++++++ tests/library.at | 4 ++++ tests/test-util.c | 18 ++++++++++++++++++ 7 files changed, 120 insertions(+), 3 deletions(-) create mode 100644 lib/stdio.c create mode 100644 lib/stdio.h.in diff --git a/configure.ac b/configure.ac index aa6d940a7..f6a11f03f 100644 --- a/configure.ac +++ b/configure.ac @@ -91,8 +91,8 @@ OVS_CHECK_ATOMIC_ALWAYS_LOCK_FREE(8) OVS_CHECK_POSIX_AIO OVS_CHECK_PTHREAD_SET_NAME -OVS_CHECK_INCLUDE_NEXT([string.h]) -AC_CONFIG_FILES([lib/string.h]) +OVS_CHECK_INCLUDE_NEXT([stdio.h string.h]) +AC_CONFIG_FILES([lib/stdio.h lib/string.h]) OVS_ENABLE_OPTION([-Wall]) OVS_ENABLE_OPTION([-Wextra]) diff --git a/lib/.gitignore b/lib/.gitignore index 03706dec2..2d07244ac 100644 --- a/lib/.gitignore +++ b/lib/.gitignore @@ -5,6 +5,7 @@ /coverage-counters.c /ofp-errors.inc /ofp-msgs.inc +/stdio.h /string.h /vswitch-idl.c /vswitch-idl.h diff --git a/lib/automake.mk b/lib/automake.mk index 5eece1c2a..ac6ff4ae6 100644 --- a/lib/automake.mk +++ b/lib/automake.mk @@ -196,6 +196,7 @@ lib_libopenvswitch_la_SOURCES = \ lib/stream-unix.c \ lib/stream.c \ lib/stream.h \ + lib/stdio.c \ lib/string.c \ lib/svec.c \ lib/svec.h \ @@ -234,7 +235,9 @@ lib_libopenvswitch_la_SOURCES = \ lib/vswitch-idl.h \ lib/vtep-idl.c \ lib/vtep-idl.h -EXTRA_DIST += lib/string.h.in +EXTRA_DIST += \ + lib/stdio.h.in \ + lib/string.h.in nodist_lib_libopenvswitch_la_SOURCES = \ lib/dirs.c diff --git a/lib/stdio.c b/lib/stdio.c new file mode 100644 index 000000000..49a50786a --- /dev/null +++ b/lib/stdio.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2013 Nicira, Inc. + * + * 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. + */ + +#include + +#include + +#ifdef _WIN32 +#undef snprintf +#undef vsnprintf + +int +ovs_snprintf(char *s, size_t n, const char *format, ... ) +{ + va_list args; + int len; + + va_start(args, format); + len = ovs_vsnprintf(s, n, format, args); + va_end(args); + + return len; +} + +int +ovs_vsnprintf(char *s, size_t n, const char *format, va_list args) +{ + int needed = _vscprintf(format, args); + if (s && n) { + vsnprintf(s, n, format, args); + s[n - 1] = '\0'; + } + return needed; +} +#endif /* _WIN32 */ diff --git a/lib/stdio.h.in b/lib/stdio.h.in new file mode 100644 index 000000000..3bf1f03ca --- /dev/null +++ b/lib/stdio.h.in @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2013 Nicira, Inc. + * + * 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. + */ + +#@INCLUDE_NEXT@ @NEXT_STDIO_H@ + +#if !defined STDIO_H_WRAPPER +#define STDIO_H_WRAPPER 1 + +#ifdef _WIN32 + +#include +#include + +/* Windows libc has defective snprintf() and vsnprintf(): + * + * - They return -1 if the output won't fit. + * + * - They don't null-terminate the output if it won't fit. + * + * We need working versions so here we define substitutes. */ +#undef snprintf +#define snprintf ovs_snprintf +int ovs_snprintf(char *, size_t, const char *, ...); + +#undef vsnprintf +#define vsnprintf ovs_vsnprintf +int ovs_vsnprintf(char *, size_t, const char *, va_list); +#endif /* _WIN32 */ + +#endif /* stdio.h wrapper */ diff --git a/tests/library.at b/tests/library.at index 57cdd6c0d..b0ccd40da 100644 --- a/tests/library.at +++ b/tests/library.at @@ -181,3 +181,7 @@ AT_CHECK([sed 's/.*: // ]) AT_CLEANUP + +AT_SETUP([snprintf]) +AT_CHECK([test-util snprintf]) +AT_CLEANUP diff --git a/tests/test-util.c b/tests/test-util.c index 9152562cb..363abb179 100644 --- a/tests/test-util.c +++ b/tests/test-util.c @@ -1013,6 +1013,23 @@ test_ovs_scan(int argc OVS_UNUSED, char *argv[] OVS_UNUSED) ovs_assert(sscanf("0x12-3]xyz", "%[^-a-f]", str)); ovs_assert(!strcmp(str, "0x12")); } + +static void +test_snprintf(int argc OVS_UNUSED, char *argv[] OVS_UNUSED) +{ + char s[16]; + + ovs_assert(snprintf(s, 4, "abcde") == 5); + ovs_assert(!strcmp(s, "abc")); + + ovs_assert(snprintf(s, 5, "abcde") == 5); + ovs_assert(!strcmp(s, "abcd")); + + ovs_assert(snprintf(s, 6, "abcde") == 5); + ovs_assert(!strcmp(s, "abcde")); + + ovs_assert(snprintf(NULL, 0, "abcde") == 5); +} static const struct command commands[] = { {"ctz", 0, 0, test_ctz}, @@ -1028,6 +1045,7 @@ static const struct command commands[] = { {"follow-symlinks", 1, INT_MAX, test_follow_symlinks}, {"assert", 0, 0, test_assert}, {"ovs_scan", 0, 0, test_ovs_scan}, + {"snprintf", 0, 0, test_snprintf}, {NULL, 0, 0, NULL}, }; -- 2.43.0