From 6001c87cbcafba68975fd9b3aa69f4952396f83c Mon Sep 17 00:00:00 2001 From: Spencer Low Date: Wed, 13 May 2015 00:02:55 -0700 Subject: [PATCH] adb: win32: fix StringPrintf format string checking of %zd and PRIu64 At runtime, vsnprintf (and android::base::StringPrintf which calls it) call a mingw version of vsnprintf, not the vsnprintf from MSVCRT.DLL. The mingw version properly understands %zd and PRIu64 (the latter, provided that you #include ). The problem was that android::base::StringPrintf was causing compile-time errors saying that %zd and PRIu64 were not recognized. It seems that this was because the attribute on the function prototypes specified `printf' instead of `gnu_printf'. Once that was fixed to match vsnprintf's attribute, the warnings went away. This uses similar preprocessor techniques as . Also restore a %zd usage to avoid a static_cast<>, and make print_transfer_progress()'s format string compile-time checkable (and tweak some types and %llu => PRIu64). Change-Id: I80b31b9994858a28cb7c6847143b86108b8ab842 Signed-off-by: Spencer Low --- adb/adb_client.cpp | 4 ++-- adb/commandline.cpp | 10 ---------- adb/file_sync_client.cpp | 10 +++++----- base/include/base/stringprintf.h | 22 +++++++++++++++++++--- 4 files changed, 26 insertions(+), 20 deletions(-) diff --git a/adb/adb_client.cpp b/adb/adb_client.cpp index 532af4534..c73d73728 100644 --- a/adb/adb_client.cpp +++ b/adb/adb_client.cpp @@ -145,8 +145,8 @@ bool adb_status(int fd, std::string* error) { int _adb_connect(const std::string& service, std::string* error) { D("_adb_connect: %s\n", service.c_str()); if (service.empty() || service.size() > 1024) { - *error = android::base::StringPrintf("bad service name length (%d)", - static_cast(service.size())); + *error = android::base::StringPrintf("bad service name length (%zd)", + service.size()); return -1; } diff --git a/adb/commandline.cpp b/adb/commandline.cpp index 6caec6ce4..d7bee91f3 100644 --- a/adb/commandline.cpp +++ b/adb/commandline.cpp @@ -1593,11 +1593,7 @@ static int install_multiple_app(TransportType transport, const char* serial, int return 1; } -#if defined(_WIN32) // Remove when we're using clang for Win32. - std::string cmd = android::base::StringPrintf("exec:pm install-create -S %u", (unsigned) total_size); -#else std::string cmd = android::base::StringPrintf("exec:pm install-create -S %" PRIu64, total_size); -#endif for (i = 1; i < first_apk; i++) { cmd += " " + escape_arg(argv[i]); } @@ -1638,15 +1634,9 @@ static int install_multiple_app(TransportType transport, const char* serial, int goto finalize_session; } -#if defined(_WIN32) // Remove when we're using clang for Win32. - std::string cmd = android::base::StringPrintf( - "exec:pm install-write -S %u %d %d_%s -", - (unsigned) sb.st_size, session_id, i, get_basename(file)); -#else std::string cmd = android::base::StringPrintf( "exec:pm install-write -S %" PRIu64 " %d %d_%s -", static_cast(sb.st_size), session_id, i, get_basename(file)); -#endif int localFd = adb_open(file, O_RDONLY); if (localFd < 0) { diff --git a/adb/file_sync_client.cpp b/adb/file_sync_client.cpp index 2efc890e8..1dc711aec 100644 --- a/adb/file_sync_client.cpp +++ b/adb/file_sync_client.cpp @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -63,13 +64,12 @@ static void END() total_bytes, (t / 1000000LL), (t % 1000000LL) / 1000LL); } -static const char* transfer_progress_format = "\rTransferring: %llu/%llu (%d%%)"; - -static void print_transfer_progress(unsigned long long bytes_current, - unsigned long long bytes_total) { +static void print_transfer_progress(uint64_t bytes_current, + uint64_t bytes_total) { if (bytes_total == 0) return; - fprintf(stderr, transfer_progress_format, bytes_current, bytes_total, + fprintf(stderr, "\rTransferring: %" PRIu64 "/%" PRIu64 " (%d%%)", + bytes_current, bytes_total, (int) (bytes_current * 100 / bytes_total)); if (bytes_current == bytes_total) { diff --git a/base/include/base/stringprintf.h b/base/include/base/stringprintf.h index 195c1decb..d68af8713 100644 --- a/base/include/base/stringprintf.h +++ b/base/include/base/stringprintf.h @@ -23,16 +23,32 @@ namespace android { namespace base { +// These printf-like functions are implemented in terms of vsnprintf, so they +// use the same attribute for compile-time format string checking. On Windows, +// if the mingw version of vsnprintf is used, use `gnu_printf' which allows z +// in %zd and PRIu64 (and related) to be recognized by the compile-time +// checking. +#define FORMAT_ARCHETYPE __printf__ +#ifdef __USE_MINGW_ANSI_STDIO +#if __USE_MINGW_ANSI_STDIO +#undef FORMAT_ARCHETYPE +#define FORMAT_ARCHETYPE gnu_printf +#endif +#endif + // Returns a string corresponding to printf-like formatting of the arguments. std::string StringPrintf(const char* fmt, ...) - __attribute__((__format__(__printf__, 1, 2))); + __attribute__((__format__(FORMAT_ARCHETYPE, 1, 2))); // Appends a printf-like formatting of the arguments to 'dst'. void StringAppendF(std::string* dst, const char* fmt, ...) - __attribute__((__format__(__printf__, 2, 3))); + __attribute__((__format__(FORMAT_ARCHETYPE, 2, 3))); // Appends a printf-like formatting of the arguments to 'dst'. -void StringAppendV(std::string* dst, const char* format, va_list ap); +void StringAppendV(std::string* dst, const char* format, va_list ap) + __attribute__((__format__(FORMAT_ARCHETYPE, 2, 0))); + +#undef FORMAT_ARCHETYPE } // namespace base } // namespace android