diff options
author | David Pursell <dpursell@google.com> | 2016-01-27 08:52:53 -0800 |
---|---|---|
committer | David Pursell <dpursell@google.com> | 2016-02-01 12:18:26 -0800 |
commit | 5f787ed2b3b9f6cc02aa5923b95d77e2a5865438 (patch) | |
tree | 5be11d6f3a3772a7e1b93ae9969168aa8a7bca88 /base | |
parent | aef26bb1a4adb953f6bbd5a7e01ca964ed3b386d (diff) | |
download | core-5f787ed2b3b9f6cc02aa5923b95d77e2a5865438.tar.gz core-5f787ed2b3b9f6cc02aa5923b95d77e2a5865438.tar.bz2 core-5f787ed2b3b9f6cc02aa5923b95d77e2a5865438.zip |
base: add SystemErrorCodeToString() function.
Pulls the Windows error string generation out of adb into libbase so
that it can be used by fastboot as well. Also makes a Unix equivalent
that just wraps strerror() so that upcoming fastboot error reporting
code can be platform-independent.
The intent here is just to provide a portable way to report an error to
the user. More general cross-platform error handling is out of scope.
Bug: http://b/26236380
Change-Id: I5a784a844775949562d069bb41dcb0ebd13a32bc
Diffstat (limited to 'base')
-rw-r--r-- | base/Android.mk | 13 | ||||
-rw-r--r-- | base/errors_test.cpp | 34 | ||||
-rw-r--r-- | base/errors_unix.cpp | 29 | ||||
-rw-r--r-- | base/errors_windows.cpp | 68 | ||||
-rw-r--r-- | base/include/android-base/errors.h | 46 |
5 files changed, 186 insertions, 4 deletions
diff --git a/base/Android.mk b/base/Android.mk index 18f86866d..d20a81f09 100644 --- a/base/Android.mk +++ b/base/Android.mk @@ -24,10 +24,18 @@ libbase_src_files := \ strings.cpp \ test_utils.cpp \ +libbase_linux_src_files := \ + errors_unix.cpp \ + +libbase_darwin_src_files := \ + errors_unix.cpp \ + libbase_windows_src_files := \ + errors_windows.cpp \ utf8.cpp \ libbase_test_src_files := \ + errors_test.cpp \ file_test.cpp \ logging_test.cpp \ parseint_test.cpp \ @@ -55,10 +63,7 @@ libbase_darwin_cppflags := \ include $(CLEAR_VARS) LOCAL_MODULE := libbase LOCAL_CLANG := true -LOCAL_SRC_FILES := $(libbase_src_files) -LOCAL_SRC_FILES_darwin := $(libbase_darwin_src_files) -LOCAL_SRC_FILES_linux := $(libbase_linux_src_files) -LOCAL_SRC_FILES_windows := $(libbase_windows_src_files) +LOCAL_SRC_FILES := $(libbase_src_files) $(libbase_linux_src_files) LOCAL_C_INCLUDES := $(LOCAL_PATH)/include LOCAL_CPPFLAGS := $(libbase_cppflags) $(libbase_linux_cppflags) LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include diff --git a/base/errors_test.cpp b/base/errors_test.cpp new file mode 100644 index 000000000..8e7cdd1da --- /dev/null +++ b/base/errors_test.cpp @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * 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 "android-base/errors.h" + +#include <gtest/gtest.h> + +namespace android { +namespace base { + +// Error strings aren't consistent enough across systems to test the output, +// just make sure we can compile correctly and nothing crashes even if we send +// it possibly bogus error codes. +TEST(ErrorsTest, TestSystemErrorString) { + SystemErrorCodeToString(-1); + SystemErrorCodeToString(0); + SystemErrorCodeToString(1); +} + +} // namespace base +} // namespace android diff --git a/base/errors_unix.cpp b/base/errors_unix.cpp new file mode 100644 index 000000000..296995efe --- /dev/null +++ b/base/errors_unix.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * 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 "android-base/errors.h" + +#include <errno.h> + +namespace android { +namespace base { + +std::string SystemErrorCodeToString(int error_code) { + return strerror(error_code); +} + +} // namespace base +} // namespace android diff --git a/base/errors_windows.cpp b/base/errors_windows.cpp new file mode 100644 index 000000000..a5ff51188 --- /dev/null +++ b/base/errors_windows.cpp @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * 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 "android-base/errors.h" + +#include <windows.h> + +#include "android-base/stringprintf.h" +#include "android-base/strings.h" +#include "android-base/utf8.h" + +// A Windows error code is a DWORD. It's simpler to use an int error code for +// both Unix and Windows if possible, but if this fails we'll need a different +// function signature for each. +static_assert(sizeof(int) >= sizeof(DWORD), + "Windows system error codes are too large to fit in an int."); + +namespace android { +namespace base { + +static constexpr DWORD kErrorMessageBufferSize = 256; + +std::string SystemErrorCodeToString(int int_error_code) { + WCHAR msgbuf[kErrorMessageBufferSize]; + DWORD error_code = int_error_code; + DWORD flags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS; + DWORD len = FormatMessageW(flags, nullptr, error_code, 0, msgbuf, + kErrorMessageBufferSize, nullptr); + if (len == 0) { + return android::base::StringPrintf( + "Error %lu while retrieving message for error %lu", GetLastError(), + error_code); + } + + // Convert UTF-16 to UTF-8. + std::string msg; + if (!android::base::WideToUTF8(msgbuf, &msg)) { + return android::base::StringPrintf( + "Error %lu while converting message for error %lu from UTF-16 to UTF-8", + GetLastError(), error_code); + } + + // Messages returned by the system end with line breaks. + msg = android::base::Trim(msg); + + // There are many Windows error messages compared to POSIX, so include the + // numeric error code for easier, quicker, accurate identification. Use + // decimal instead of hex because there are decimal ranges like 10000-11999 + // for Winsock. + android::base::StringAppendF(&msg, " (%lu)", error_code); + return msg; +} + +} // namespace base +} // namespace android diff --git a/base/include/android-base/errors.h b/base/include/android-base/errors.h new file mode 100644 index 000000000..ca621fa8b --- /dev/null +++ b/base/include/android-base/errors.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * 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. + */ + +// Portable error handling functions. This is only necessary for host-side +// code that needs to be cross-platform; code that is only run on Unix should +// just use errno and strerror() for simplicity. +// +// There is some complexity since Windows has (at least) three different error +// numbers, not all of which share the same type: +// * errno: for C runtime errors. +// * GetLastError(): Windows non-socket errors. +// * WSAGetLastError(): Windows socket errors. +// errno can be passed to strerror() on all platforms, but the other two require +// special handling to get the error string. Refer to Microsoft documentation +// to determine which error code to check for each function. + +#ifndef BASE_ERRORS_H +#define BASE_ERRORS_H + +#include <string> + +namespace android { +namespace base { + +// Returns a string describing the given system error code. |error_code| must +// be errno on Unix or GetLastError()/WSAGetLastError() on Windows. Passing +// errno on Windows has undefined behavior. +std::string SystemErrorCodeToString(int error_code); + +} // namespace base +} // namespace android + +#endif // BASE_ERRORS_H |