Merge "Revert "liblog: resolve deadlocks""
diff --git a/adb/Android.mk b/adb/Android.mk
index 903d1e1..5ddc937 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -17,10 +17,20 @@
-Wvla \
-DADB_REVISION='"$(adb_version)"' \
+ADB_COMMON_linux_CFLAGS := \
+ -std=c++14 \
+ -Wexit-time-destructors \
+
+ADB_COMMON_darwin_CFLAGS := \
+ -std=c++14 \
+ -Wexit-time-destructors \
+
# Define windows.h and tchar.h Unicode preprocessor symbols so that
# CreateFile(), _tfopen(), etc. map to versions that take wchar_t*, breaking the
# build if you accidentally pass char*. Fix by calling like:
-# CreateFileW(widen(utf8).c_str()).
+# std::wstring path_wide;
+# if (!android::base::UTF8ToWide(path_utf8, &path_wide)) { /* error handling */ }
+# CreateFileW(path_wide.c_str());
ADB_COMMON_windows_CFLAGS := \
-DUNICODE=1 -D_UNICODE=1 \
@@ -55,7 +65,10 @@
-fvisibility=hidden \
LIBADB_linux_CFLAGS := \
- -std=c++14 \
+ $(ADB_COMMON_linux_CFLAGS) \
+
+LIBADB_darwin_CFLAGS := \
+ $(ADB_COMMON_darwin_CFLAGS) \
LIBADB_windows_CFLAGS := \
$(ADB_COMMON_windows_CFLAGS) \
@@ -110,6 +123,7 @@
LOCAL_CFLAGS := $(LIBADB_CFLAGS) -DADB_HOST=1
LOCAL_CFLAGS_windows := $(LIBADB_windows_CFLAGS)
LOCAL_CFLAGS_linux := $(LIBADB_linux_CFLAGS)
+LOCAL_CFLAGS_darwin := $(LIBADB_darwin_CFLAGS)
LOCAL_SRC_FILES := \
$(LIBADB_SRC_FILES) \
adb_auth_host.cpp \
@@ -155,6 +169,7 @@
LOCAL_CFLAGS := -DADB_HOST=1 $(LIBADB_CFLAGS)
LOCAL_CFLAGS_windows := $(LIBADB_windows_CFLAGS)
LOCAL_CFLAGS_linux := $(LIBADB_linux_CFLAGS)
+LOCAL_CFLAGS_darwin := $(LIBADB_darwin_CFLAGS)
LOCAL_SRC_FILES := \
$(LIBADB_TEST_SRCS) \
services.cpp \
@@ -189,6 +204,7 @@
LOCAL_CFLAGS := -DADB_HOST=1 $(LIBADB_CFLAGS)
LOCAL_CFLAGS_windows := $(LIBADB_windows_CFLAGS)
LOCAL_CFLAGS_linux := $(LIBADB_linux_CFLAGS)
+LOCAL_CFLAGS_darwin := $(LIBADB_darwin_CFLAGS)
LOCAL_SRC_FILES := test_track_devices.cpp
LOCAL_SANITIZE := $(adb_host_sanitize)
LOCAL_SHARED_LIBRARIES := libbase
@@ -204,7 +220,6 @@
LOCAL_LDLIBS_linux := -lrt -ldl -lpthread
LOCAL_LDLIBS_darwin := -lpthread -framework CoreFoundation -framework IOKit -framework Carbon
-LOCAL_CFLAGS_darwin := -Wno-sizeof-pointer-memaccess -Wno-unused-parameter
# Use wmain instead of main
LOCAL_LDFLAGS_windows := -municode
@@ -230,6 +245,13 @@
LOCAL_CFLAGS_windows := \
$(ADB_COMMON_windows_CFLAGS)
+LOCAL_CFLAGS_linux := \
+ $(ADB_COMMON_linux_CFLAGS) \
+
+LOCAL_CFLAGS_darwin := \
+ $(ADB_COMMON_darwin_CFLAGS) \
+ -Wno-sizeof-pointer-memaccess -Wno-unused-parameter \
+
LOCAL_MODULE := adb
LOCAL_MODULE_TAGS := debug
LOCAL_MODULE_HOST_OS := darwin linux windows
@@ -273,6 +295,7 @@
LOCAL_CFLAGS := \
$(ADB_COMMON_CFLAGS) \
+ $(ADB_COMMON_linux_CFLAGS) \
-DADB_HOST=0 \
-D_GNU_SOURCE \
-Wno-deprecated-declarations \
diff --git a/adb/adb_auth_host.cpp b/adb/adb_auth_host.cpp
index 5309519..e11bff0 100644
--- a/adb/adb_auth_host.cpp
+++ b/adb/adb_auth_host.cpp
@@ -311,7 +311,9 @@
SystemErrorCodeToString(hr).c_str());
return -1;
}
- home_str = narrow(path);
+ if (!android::base::WideToUTF8(path, &home_str)) {
+ return -1;
+ }
home = home_str.c_str();
}
format = "%s\\%s";
diff --git a/adb/client/main.cpp b/adb/client/main.cpp
index a225a53..8d01af3 100644
--- a/adb/client/main.cpp
+++ b/adb/client/main.cpp
@@ -58,7 +58,12 @@
SystemErrorCodeToString(GetLastError()).c_str());
}
- return narrow(temp_path) + log_name;
+ std::string temp_path_utf8;
+ if (!android::base::WideToUTF8(temp_path, &temp_path_utf8)) {
+ fatal_errno("cannot convert temporary file path from UTF-16 to UTF-8");
+ }
+
+ return temp_path_utf8 + log_name;
}
#else
static const char kNullFileName[] = "/dev/null";
diff --git a/adb/commandline.cpp b/adb/commandline.cpp
index 6e4c4e8..5113eb8 100644
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -62,7 +62,7 @@
static int install_app_legacy(TransportType t, const char* serial, int argc, const char** argv);
static int uninstall_app_legacy(TransportType t, const char* serial, int argc, const char** argv);
-static std::string gProductOutPath;
+static auto& gProductOutPath = *new std::string();
extern int gListenAll;
static std::string product_file(const char *extra) {
@@ -1080,8 +1080,8 @@
for (int i = 1; i < argc; i++) {
if (!strcmp("-f", argv[i])) {
if (i == argc-1) {
- fprintf(stderr, "adb: -f passed with no filename\n");
- return usage();
+ fprintf(stderr, "adb: backup -f passed with no filename.\n");
+ return EXIT_FAILURE;
}
filename = argv[i+1];
for (int j = i+2; j <= argc; ) {
@@ -1092,14 +1092,18 @@
}
}
- /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
- if (argc < 2) return usage();
+ // Bare "adb backup" or "adb backup -f filename" are not valid invocations ---
+ // a list of packages is required.
+ if (argc < 2) {
+ fprintf(stderr, "adb: backup either needs a list of packages or -all/-shared.\n");
+ return EXIT_FAILURE;
+ }
adb_unlink(filename);
int outFd = adb_creat(filename, 0640);
if (outFd < 0) {
- fprintf(stderr, "adb: unable to open file %s\n", filename);
- return -1;
+ fprintf(stderr, "adb: backup unable to create file '%s': %s\n", filename, strerror(errno));
+ return EXIT_FAILURE;
}
std::string cmd = "backup:";
@@ -1115,15 +1119,17 @@
if (fd < 0) {
fprintf(stderr, "adb: unable to connect for backup: %s\n", error.c_str());
adb_close(outFd);
- return -1;
+ return EXIT_FAILURE;
}
- printf("Now unlock your device and confirm the backup operation.\n");
+ printf("Now unlock your device and confirm the backup operation...\n");
+ fflush(stdout);
+
copy_to_file(fd, outFd);
adb_close(fd);
adb_close(outFd);
- return 0;
+ return EXIT_SUCCESS;
}
static int restore(int argc, const char** argv) {
diff --git a/adb/fdevent.cpp b/adb/fdevent.cpp
index 06eb34d..46547b9 100644
--- a/adb/fdevent.cpp
+++ b/adb/fdevent.cpp
@@ -70,8 +70,8 @@
// All operations to fdevent should happen only in the main thread.
// That's why we don't need a lock for fdevent.
-static std::unordered_map<int, PollNode> g_poll_node_map;
-static std::list<fdevent*> g_pending_list;
+static auto& g_poll_node_map = *new std::unordered_map<int, PollNode>();
+static auto& g_pending_list = *new std::list<fdevent*>();
static bool main_thread_valid;
static pthread_t main_thread;
diff --git a/adb/file_sync_client.cpp b/adb/file_sync_client.cpp
index 736411c..a2d2a66 100644
--- a/adb/file_sync_client.cpp
+++ b/adb/file_sync_client.cpp
@@ -478,34 +478,34 @@
struct copyinfo
{
- std::string src;
- std::string dst;
+ std::string lpath;
+ std::string rpath;
unsigned int time;
unsigned int mode;
uint64_t size;
bool skip;
};
-static copyinfo mkcopyinfo(const std::string& spath, const std::string& dpath,
+static void ensure_trailing_separator(std::string& lpath, std::string& rpath) {
+ if (!adb_is_separator(lpath.back())) {
+ lpath.push_back(OS_PATH_SEPARATOR);
+ }
+ if (rpath.back() != '/') {
+ rpath.push_back('/');
+ }
+}
+
+static copyinfo mkcopyinfo(std::string lpath, std::string rpath,
const std::string& name, unsigned int mode) {
copyinfo result;
- result.src = spath;
- result.dst = dpath;
+ result.lpath = std::move(lpath);
+ result.rpath = std::move(rpath);
+ ensure_trailing_separator(result.lpath, result.rpath);
+ result.lpath.append(name);
+ result.rpath.append(name);
- // FIXME(b/25573669): This is probably broken on win32?
- if (result.src.back() != '/') {
- result.src.push_back('/');
- }
- if (result.dst.back() != '/') {
- result.dst.push_back('/');
- }
- result.src.append(name);
- result.dst.append(name);
-
- bool isdir = S_ISDIR(mode);
- if (isdir) {
- result.src.push_back('/');
- result.dst.push_back('/');
+ if (S_ISDIR(mode)) {
+ ensure_trailing_separator(result.lpath, result.rpath);
}
result.time = 0;
@@ -577,7 +577,7 @@
}
for (const copyinfo& ci : dirlist) {
- local_build_list(sc, filelist, ci.src.c_str(), ci.dst.c_str());
+ local_build_list(sc, filelist, ci.lpath, ci.rpath);
}
return true;
@@ -587,15 +587,8 @@
std::string rpath, bool check_timestamps,
bool list_only) {
// Make sure that both directory paths end in a slash.
- // Both paths are known to be nonempty.
- //
- // FIXME(b/25573669): This is probably broken on win32?
- if (lpath.back() != '/') {
- lpath.push_back('/');
- }
- if (rpath.back() != '/') {
- rpath.push_back('/');
- }
+ // Both paths are known to be nonempty, so we don't need to check.
+ ensure_trailing_separator(lpath, rpath);
// Recursively build the list of files to copy.
std::vector<copyinfo> filelist;
@@ -607,7 +600,7 @@
if (check_timestamps) {
for (const copyinfo& ci : filelist) {
- if (!sc.SendRequest(ID_STAT, ci.dst.c_str())) {
+ if (!sc.SendRequest(ID_STAT, ci.rpath.c_str())) {
return false;
}
}
@@ -629,10 +622,10 @@
for (const copyinfo& ci : filelist) {
if (!ci.skip) {
if (list_only) {
- sc.Error("would push: %s -> %s", ci.src.c_str(),
- ci.dst.c_str());
+ sc.Error("would push: %s -> %s", ci.lpath.c_str(),
+ ci.rpath.c_str());
} else {
- if (!sync_send(sc, ci.src.c_str(), ci.dst.c_str(), ci.time,
+ if (!sync_send(sc, ci.lpath.c_str(), ci.rpath.c_str(), ci.time,
ci.mode)) {
return false;
}
@@ -739,7 +732,7 @@
// We found a child that isn't '.' or '..'.
empty_dir = false;
- copyinfo ci = mkcopyinfo(rpath, lpath, name, mode);
+ copyinfo ci = mkcopyinfo(lpath, rpath, name, mode);
if (S_ISDIR(mode)) {
dirlist.push_back(ci);
} else if (S_ISREG(mode) || S_ISLNK(mode)) {
@@ -758,11 +751,7 @@
// Add the current directory to the list if it was empty, to ensure that
// it gets created.
if (empty_dir) {
- auto rdname = adb_dirname(rpath);
- auto ldname = adb_dirname(lpath);
- auto rbasename = adb_basename(rpath);
- auto lbasename = adb_basename(lpath);
- filelist->push_back(mkcopyinfo(adb_dirname(rpath), adb_dirname(lpath),
+ filelist->push_back(mkcopyinfo(adb_dirname(lpath), adb_dirname(rpath),
adb_basename(rpath), S_IFDIR));
return true;
}
@@ -771,8 +760,7 @@
while (!dirlist.empty()) {
copyinfo current = dirlist.back();
dirlist.pop_back();
- if (!remote_build_list(sc, filelist, current.src.c_str(),
- current.dst.c_str())) {
+ if (!remote_build_list(sc, filelist, current.rpath, current.lpath)) {
return false;
}
}
@@ -780,15 +768,15 @@
return true;
}
-static int set_time_and_mode(const char *lpath, time_t time, unsigned int mode)
-{
+static int set_time_and_mode(const std::string& lpath, time_t time,
+ unsigned int mode) {
struct utimbuf times = { time, time };
- int r1 = utime(lpath, ×);
+ int r1 = utime(lpath.c_str(), ×);
/* use umask for permissions */
mode_t mask = umask(0000);
umask(mask);
- int r2 = chmod(lpath, mode & ~mask);
+ int r2 = chmod(lpath.c_str(), mode & ~mask);
return r1 ? r1 : r2;
}
@@ -797,14 +785,7 @@
std::string lpath, bool copy_attrs) {
// Make sure that both directory paths end in a slash.
// Both paths are known to be nonempty, so we don't need to check.
- if (rpath.back() != '/') {
- rpath.push_back('/');
- }
-
- // FIXME(b/25573669): This is probably broken on win32?
- if (lpath.back() != '/') {
- lpath.push_back('/');
- }
+ ensure_trailing_separator(lpath, rpath);
// Recursively build the list of files to copy.
sc.Print("pull: building file list...");
@@ -817,26 +798,25 @@
int skipped = 0;
for (const copyinfo &ci : filelist) {
if (!ci.skip) {
- sc.Printf("pull: %s -> %s", ci.src.c_str(), ci.dst.c_str());
+ sc.Printf("pull: %s -> %s", ci.rpath.c_str(), ci.lpath.c_str());
if (S_ISDIR(ci.mode)) {
// Entry is for an empty directory, create it and continue.
// TODO(b/25457350): We don't preserve permissions on directories.
- if (!mkdirs(ci.dst)) {
+ if (!mkdirs(ci.lpath)) {
sc.Error("failed to create directory '%s': %s",
- ci.dst.c_str(), strerror(errno));
+ ci.lpath.c_str(), strerror(errno));
return false;
}
pulled++;
continue;
}
- if (!sync_recv(sc, ci.src.c_str(), ci.dst.c_str())) {
+ if (!sync_recv(sc, ci.rpath.c_str(), ci.lpath.c_str())) {
return false;
}
- if (copy_attrs &&
- set_time_and_mode(ci.dst.c_str(), ci.time, ci.mode)) {
+ if (copy_attrs && set_time_and_mode(ci.lpath, ci.time, ci.mode)) {
return false;
}
pulled++;
@@ -888,7 +868,7 @@
// A path that ends with a slash doesn't have to be a directory if
// it doesn't exist yet.
- if (dst[dst_len - 1] == '/' && dst_exists) {
+ if (adb_is_separator(dst[dst_len - 1]) && dst_exists) {
sc.Error("failed to access '%s': Not a directory", dst);
return false;
}
@@ -907,14 +887,15 @@
continue;
}
- if (S_ISREG(src_mode) || S_ISLNK(src_mode)) {
- // TODO(b/25601283): symlinks shouldn't be handled as files.
+ if (S_ISREG(src_mode)) {
std::string path_holder;
if (dst_isdir) {
// If we're copying a remote file to a local directory, we
- // really want to copy to local_dir + "/" + basename(remote).
+ // really want to copy to local_dir + OS_PATH_SEPARATOR +
+ // basename(remote).
path_holder = android::base::StringPrintf(
- "%s/%s", dst_path, adb_basename(src_path).c_str());
+ "%s%c%s", dst_path, OS_PATH_SEPARATOR,
+ adb_basename(src_path).c_str());
dst_path = path_holder.c_str();
}
if (!sync_recv(sc, src_path, dst_path)) {
diff --git a/adb/line_printer.cpp b/adb/line_printer.cpp
index aa332f7..4c57c7e 100644
--- a/adb/line_printer.cpp
+++ b/adb/line_printer.cpp
@@ -77,7 +77,7 @@
CONSOLE_SCREEN_BUFFER_INFO csbi;
GetConsoleScreenBufferInfo(console_, &csbi);
- // TODO: const std::wstring to_print_wide = widen(to_print);
+ // TODO: std::wstring to_print_wide; if (!android::base::UTF8ToWide(to_print, &to_print_wide)...
// TODO: wstring ElideMiddle.
to_print = ElideMiddle(to_print, static_cast<size_t>(csbi.dwSize.X));
// We don't want to have the cursor spamming back and forth, so instead of
diff --git a/adb/remount_service.cpp b/adb/remount_service.cpp
index 35ba056..8f1c9b0 100644
--- a/adb/remount_service.cpp
+++ b/adb/remount_service.cpp
@@ -35,8 +35,6 @@
#include "cutils/properties.h"
#include "fs_mgr.h"
-const std::string kFstab_Prefix = "/fstab.";
-
// Returns the device used to mount a directory in /proc/mounts.
static std::string find_proc_mount(const char* dir) {
std::unique_ptr<FILE, int(*)(FILE*)> fp(setmntent("/proc/mounts", "r"), endmntent);
@@ -58,7 +56,7 @@
char propbuf[PROPERTY_VALUE_MAX];
property_get("ro.hardware", propbuf, "");
- std::string fstab_filename = kFstab_Prefix + propbuf;
+ std::string fstab_filename = std::string("/fstab.") + propbuf;
struct fstab* fstab = fs_mgr_read_fstab(fstab_filename.c_str());
struct fstab_rec* rec = fs_mgr_get_entry_for_mount_point(fstab, dir);
std::string dev = rec ? std::string(rec->blk_device) : "";
diff --git a/adb/sysdeps.h b/adb/sysdeps.h
index e40fbbc..cba66fc 100644
--- a/adb/sysdeps.h
+++ b/adb/sysdeps.h
@@ -28,6 +28,9 @@
#include <string>
+// Include this before open/unlink are defined as macros below.
+#include <base/utf8.h>
+
/*
* TEMP_FAILURE_RETRY is defined by some, but not all, versions of
* <unistd.h>. (Alas, it is not as standard as we'd hoped!) So, if it's
@@ -72,7 +75,7 @@
#include <ws2tcpip.h>
#include <memory> // unique_ptr
-#include <string> // Prototypes for narrow() and widen() use std::(w)string.
+#include <string>
#include "fdevent.h"
@@ -342,18 +345,6 @@
char* adb_strerror(int err);
#define strerror adb_strerror
-// Convert from UTF-8 to UTF-16, typically used to convert char strings into
-// wchar_t strings that can be passed to wchar_t-based OS and C Runtime APIs
-// on Windows.
-extern std::wstring widen(const std::string& utf8);
-extern std::wstring widen(const char* utf8);
-
-// Convert from UTF-16 to UTF-8, typically used to convert strings from OS and
-// C Runtime APIs that return wchar_t, to a format for our char-based data
-// structures.
-extern std::string narrow(const std::wstring& utf16);
-extern std::string narrow(const wchar_t* utf16);
-
// Helper class to convert UTF-16 argv from wmain() to UTF-8 args that can be
// passed to main().
class NarrowArgs {
diff --git a/adb/sysdeps_win32.cpp b/adb/sysdeps_win32.cpp
index 0634da5..81dcb41 100644
--- a/adb/sysdeps_win32.cpp
+++ b/adb/sysdeps_win32.cpp
@@ -103,7 +103,13 @@
}
// Convert UTF-16 to UTF-8.
- std::string msg(narrow(msgbuf));
+ std::string msg;
+ if (!android::base::WideToUTF8(msgbuf, &msg)) {
+ return android::base::StringPrintf(
+ "Error (%d) converting from UTF-16 to UTF-8 while retrieving error. (%lu)", errno,
+ 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
@@ -144,7 +150,11 @@
char *data;
DWORD file_size;
- file = CreateFileW( widen(fn).c_str(),
+ std::wstring fn_wide;
+ if (!android::base::UTF8ToWide(fn, &fn_wide))
+ return NULL;
+
+ file = CreateFileW( fn_wide.c_str(),
GENERIC_READ,
FILE_SHARE_READ,
NULL,
@@ -434,7 +444,11 @@
return -1;
}
- f->fh_handle = CreateFileW( widen(path).c_str(), desiredAccess, shareMode,
+ std::wstring path_wide;
+ if (!android::base::UTF8ToWide(path, &path_wide)) {
+ return -1;
+ }
+ f->fh_handle = CreateFileW( path_wide.c_str(), desiredAccess, shareMode,
NULL, OPEN_EXISTING, 0, NULL );
if ( f->fh_handle == INVALID_HANDLE_VALUE ) {
@@ -475,7 +489,11 @@
return -1;
}
- f->fh_handle = CreateFileW( widen(path).c_str(), GENERIC_WRITE,
+ std::wstring path_wide;
+ if (!android::base::UTF8ToWide(path, &path_wide)) {
+ return -1;
+ }
+ f->fh_handle = CreateFileW( path_wide.c_str(), GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
NULL );
@@ -981,7 +999,7 @@
#if (NTDDI_VERSION >= NTDDI_WINXPSP2) || (_WIN32_WINNT >= _WIN32_WINNT_WS03)
// TODO: When the Android SDK tools increases the Windows system
- // requirements >= WinXP SP2, switch to GetAddrInfoW(widen(host).c_str()).
+ // requirements >= WinXP SP2, switch to android::base::UTF8ToWide() + GetAddrInfoW().
#else
// Otherwise, keep using getaddrinfo(), or do runtime API detection
// with GetProcAddress("GetAddrInfoW").
@@ -2925,7 +2943,7 @@
}
// Internal buffer to satisfy future _console_read() calls.
-static std::vector<char> g_console_input_buffer;
+static auto& g_console_input_buffer = *new std::vector<char>();
// Writes to buffer buf (of length len), returning number of bytes written or -1 on error. Never
// returns zero on console closure because Win32 consoles are never 'closed' (as far as I can tell).
@@ -3405,11 +3423,11 @@
// The Choice
// ----------
//
-// The code below chooses option 3, the UTF-8 everywhere strategy. It
-// introduces narrow() which converts UTF-16 to UTF-8. This is used by the
+// The code below chooses option 3, the UTF-8 everywhere strategy. It uses
+// android::base::WideToUTF8() which converts UTF-16 to UTF-8. This is used by the
// NarrowArgs helper class that is used to convert wmain() args into UTF-8
-// args that are passed to main() at the beginning of program startup. We also
-// introduce widen() which converts from UTF-8 to UTF-16. This is used to
+// args that are passed to main() at the beginning of program startup. We also use
+// android::base::UTF8ToWide() which converts from UTF-8 to UTF-16. This is used to
// implement wrappers below that call UTF-16 OS and C Runtime APIs.
//
// Unicode console output
@@ -3439,101 +3457,17 @@
// to UTF-16 and then calls WriteConsoleW().
-// Function prototype because attributes cannot be placed on func definitions.
-static void _widen_fatal(const char *fmt, ...)
- __attribute__((__format__(ADB_FORMAT_ARCHETYPE, 1, 2)));
-
-// A version of fatal() that does not call adb_(v)fprintf(), so it can be
-// called from those functions.
-static void _widen_fatal(const char *fmt, ...) {
- va_list ap;
- va_start(ap, fmt);
- // If (v)fprintf are macros that point to adb_(v)fprintf, when random adb
- // code calls (v)fprintf, it may end up calling adb_(v)fprintf, which then
- // calls _widen_fatal(). So then how does _widen_fatal() output a error?
- // By directly calling real C Runtime APIs that don't properly output
- // Unicode, but will be able to get a comprehendible message out. To do
- // this, make sure we don't call (v)fprintf macros by undefining them.
-#pragma push_macro("fprintf")
-#pragma push_macro("vfprintf")
-#undef fprintf
-#undef vfprintf
- fprintf(stderr, "error: ");
- vfprintf(stderr, fmt, ap);
- fprintf(stderr, "\n");
-#pragma pop_macro("vfprintf")
-#pragma pop_macro("fprintf")
- va_end(ap);
- exit(-1);
-}
-
-// Convert size number of UTF-8 char's to UTF-16. Fatal exit on error.
-std::wstring widen(const char* utf8, const size_t size) {
- std::wstring utf16;
- if (!android::base::UTF8ToWide(utf8, size, &utf16)) {
- // If we call fatal() here and fatal() calls widen(), then there may be
- // infinite recursion. To avoid this, call _widen_fatal() instead.
- _widen_fatal("cannot convert from UTF-8 to UTF-16");
- }
-
- return utf16;
-}
-
-// Convert a NULL-terminated string of UTF-8 characters to UTF-16. Fatal exit
-// on error.
-std::wstring widen(const char* utf8) {
- std::wstring utf16;
- if (!android::base::UTF8ToWide(utf8, &utf16)) {
- // If we call fatal() here and fatal() calls widen(), then there may be
- // infinite recursion. To avoid this, call _widen_fatal() instead.
- _widen_fatal("cannot convert from UTF-8 to UTF-16");
- }
-
- return utf16;
-}
-
-// Convert a UTF-8 std::string (including any embedded NULL characters) to
-// UTF-16. Fatal exit on error.
-std::wstring widen(const std::string& utf8) {
- std::wstring utf16;
- if (!android::base::UTF8ToWide(utf8, &utf16)) {
- // If we call fatal() here and fatal() calls widen(), then there may be
- // infinite recursion. To avoid this, call _widen_fatal() instead.
- _widen_fatal("cannot convert from UTF-8 to UTF-16");
- }
-
- return utf16;
-}
-
-// Convert a UTF-16 std::wstring (including any embedded NULL characters) to
-// UTF-8. Fatal exit on error.
-std::string narrow(const std::wstring& utf16) {
- std::string utf8;
- if (!android::base::WideToUTF8(utf16, &utf8)) {
- fatal("cannot convert from UTF-16 to UTF-8");
- }
-
- return utf8;
-}
-
-// Convert a NULL-terminated string of UTF-16 characters to UTF-8. Fatal exit
-// on error.
-std::string narrow(const wchar_t* utf16) {
- std::string utf8;
- if (!android::base::WideToUTF8(utf16, &utf8)) {
- fatal("cannot convert from UTF-16 to UTF-8");
- }
-
- return utf8;
-}
-
// Constructor for helper class to convert wmain() UTF-16 args to UTF-8 to
// be passed to main().
NarrowArgs::NarrowArgs(const int argc, wchar_t** const argv) {
narrow_args = new char*[argc + 1];
for (int i = 0; i < argc; ++i) {
- narrow_args[i] = strdup(narrow(argv[i]).c_str());
+ std::string arg_narrow;
+ if (!android::base::WideToUTF8(argv[i], &arg_narrow)) {
+ fatal_errno("cannot convert argument from UTF-16 to UTF-8");
+ }
+ narrow_args[i] = strdup(arg_narrow.c_str());
}
narrow_args[argc] = nullptr; // terminate
}
@@ -3549,20 +3483,24 @@
}
int unix_open(const char* path, int options, ...) {
+ std::wstring path_wide;
+ if (!android::base::UTF8ToWide(path, &path_wide)) {
+ return -1;
+ }
if ((options & O_CREAT) == 0) {
- return _wopen(widen(path).c_str(), options);
+ return _wopen(path_wide.c_str(), options);
} else {
int mode;
va_list args;
va_start(args, options);
mode = va_arg(args, int);
va_end(args);
- return _wopen(widen(path).c_str(), options, mode);
+ return _wopen(path_wide.c_str(), options, mode);
}
}
// Version of stat() that takes a UTF-8 path.
-int adb_stat(const char* f, struct adb_stat* s) {
+int adb_stat(const char* path, struct adb_stat* s) {
#pragma push_macro("wstat")
// This definition of wstat seems to be missing from <sys/stat.h>.
#if defined(_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS == 64)
@@ -3575,17 +3513,27 @@
// <sys/stat.h> has a function prototype for wstat() that should be available.
#endif
- return wstat(widen(f).c_str(), s);
+ std::wstring path_wide;
+ if (!android::base::UTF8ToWide(path, &path_wide)) {
+ return -1;
+ }
+
+ return wstat(path_wide.c_str(), s);
#pragma pop_macro("wstat")
}
// Version of opendir() that takes a UTF-8 path.
-DIR* adb_opendir(const char* name) {
+DIR* adb_opendir(const char* path) {
+ std::wstring path_wide;
+ if (!android::base::UTF8ToWide(path, &path_wide)) {
+ return nullptr;
+ }
+
// Just cast _WDIR* to DIR*. This doesn't work if the caller reads any of
// the fields, but right now all the callers treat the structure as
// opaque.
- return reinterpret_cast<DIR*>(_wopendir(widen(name).c_str()));
+ return reinterpret_cast<DIR*>(_wopendir(path_wide.c_str()));
}
// Version of readdir() that returns UTF-8 paths.
@@ -3595,8 +3543,12 @@
if (went == nullptr) {
return nullptr;
}
+
// Convert from UTF-16 to UTF-8.
- const std::string name_utf8(narrow(went->d_name));
+ std::string name_utf8;
+ if (!android::base::WideToUTF8(went->d_name, &name_utf8)) {
+ return nullptr;
+ }
// Cast the _wdirent* to dirent* and overwrite the d_name field (which has
// space for UTF-16 wchar_t's) with UTF-8 char's.
@@ -3628,7 +3580,10 @@
// Version of unlink() that takes a UTF-8 path.
int adb_unlink(const char* path) {
- const std::wstring wpath(widen(path));
+ std::wstring wpath;
+ if (!android::base::UTF8ToWide(path, &wpath)) {
+ return -1;
+ }
int rc = _wunlink(wpath.c_str());
@@ -3644,20 +3599,35 @@
// Version of mkdir() that takes a UTF-8 path.
int adb_mkdir(const std::string& path, int mode) {
- return _wmkdir(widen(path.c_str()).c_str());
+ std::wstring path_wide;
+ if (!android::base::UTF8ToWide(path, &path_wide)) {
+ return -1;
+ }
+
+ return _wmkdir(path_wide.c_str());
}
// Version of utime() that takes a UTF-8 path.
int adb_utime(const char* path, struct utimbuf* u) {
+ std::wstring path_wide;
+ if (!android::base::UTF8ToWide(path, &path_wide)) {
+ return -1;
+ }
+
static_assert(sizeof(struct utimbuf) == sizeof(struct _utimbuf),
"utimbuf and _utimbuf should be the same size because they both "
"contain the same types, namely time_t");
- return _wutime(widen(path).c_str(), reinterpret_cast<struct _utimbuf*>(u));
+ return _wutime(path_wide.c_str(), reinterpret_cast<struct _utimbuf*>(u));
}
// Version of chmod() that takes a UTF-8 path.
int adb_chmod(const char* path, int mode) {
- return _wchmod(widen(path).c_str(), mode);
+ std::wstring path_wide;
+ if (!android::base::UTF8ToWide(path, &path_wide)) {
+ return -1;
+ }
+
+ return _wchmod(path_wide.c_str(), mode);
}
// Internal helper function to write UTF-8 bytes to a console. Returns -1
@@ -3819,8 +3789,18 @@
// Version of fopen() that takes a UTF-8 filename and can access a file with
// a Unicode filename.
-FILE* adb_fopen(const char* f, const char* m) {
- return _wfopen(widen(f).c_str(), widen(m).c_str());
+FILE* adb_fopen(const char* path, const char* mode) {
+ std::wstring path_wide;
+ if (!android::base::UTF8ToWide(path, &path_wide)) {
+ return nullptr;
+ }
+
+ std::wstring mode_wide;
+ if (!android::base::UTF8ToWide(mode, &mode_wide)) {
+ return nullptr;
+ }
+
+ return _wfopen(path_wide.c_str(), mode_wide.c_str());
}
// Return a lowercase version of the argument. Uses C Runtime tolower() on
@@ -3851,7 +3831,7 @@
// currently updated if putenv, setenv, unsetenv are called. Note that no
// thread synchronization is done, but we're called early enough in
// single-threaded startup that things work ok.
-static std::unordered_map<std::string, char*> g_environ_utf8;
+static auto& g_environ_utf8 = *new std::unordered_map<std::string, char*>();
// Make sure that shadow UTF-8 environment variables are setup.
static void _ensure_env_setup() {
@@ -3880,15 +3860,27 @@
continue;
}
+ // If we encounter an error converting UTF-16, don't error-out on account of a single env
+ // var because the program might never even read this particular variable.
+ std::string name_utf8;
+ if (!android::base::WideToUTF8(*env, equal - *env, &name_utf8)) {
+ continue;
+ }
+
// Store lowercase name so that we can do case-insensitive searches.
- const std::string name_utf8(ToLower(narrow(
- std::wstring(*env, equal - *env))));
- char* const value_utf8 = strdup(narrow(equal + 1).c_str());
+ name_utf8 = ToLower(name_utf8);
+
+ std::string value_utf8;
+ if (!android::base::WideToUTF8(equal + 1, &value_utf8)) {
+ continue;
+ }
+
+ char* const value_dup = strdup(value_utf8.c_str());
// Don't overwrite a previus env var with the same name. In reality,
// the system probably won't let two env vars with the same name exist
// in _wenviron.
- g_environ_utf8.insert({name_utf8, value_utf8});
+ g_environ_utf8.insert({name_utf8, value_dup});
}
}
@@ -3914,10 +3906,15 @@
return nullptr;
}
- const std::string buf_utf8(narrow(wbuf));
+ std::string buf_utf8;
+ const bool narrow_result = android::base::WideToUTF8(wbuf, &buf_utf8);
free(wbuf);
wbuf = nullptr;
+ if (!narrow_result) {
+ return nullptr;
+ }
+
// If size was specified, make sure all the chars will fit.
if (size != 0) {
if (size < static_cast<int>(buf_utf8.length() + 1)) {
diff --git a/adb/transport.cpp b/adb/transport.cpp
index 4066889..2f18f20 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -38,8 +38,8 @@
static void transport_unref(atransport *t);
-static std::list<atransport*> transport_list;
-static std::list<atransport*> pending_list;
+static auto& transport_list = *new std::list<atransport*>();
+static auto& pending_list = *new std::list<atransport*>();
ADB_MUTEX_DEFINE( transport_lock );
diff --git a/adb/usb_linux.cpp b/adb/usb_linux.cpp
index c633f7f..0358b62 100644
--- a/adb/usb_linux.cpp
+++ b/adb/usb_linux.cpp
@@ -81,8 +81,8 @@
pthread_t reaper_thread = 0;
};
-static std::mutex g_usb_handles_mutex;
-static std::list<usb_handle*> g_usb_handles;
+static auto& g_usb_handles_mutex = *new std::mutex();
+static auto& g_usb_handles = *new std::list<usb_handle*>();
static int is_known_device(const char* dev_name) {
std::lock_guard<std::mutex> lock(g_usb_handles_mutex);
diff --git a/adb/usb_windows.cpp b/adb/usb_windows.cpp
index d811b24..8d3501e 100644
--- a/adb/usb_windows.cpp
+++ b/adb/usb_windows.cpp
@@ -55,7 +55,7 @@
ADBAPIHANDLE adb_write_pipe;
/// Interface name
- char* interface_name;
+ wchar_t* interface_name;
/// Mask for determining when to use zero length packets
unsigned zero_mask;
@@ -74,11 +74,11 @@
ADB_MUTEX_DEFINE( usb_lock );
/// Checks if there is opened usb handle in handle_list for this device.
-int known_device(const char* dev_name);
+int known_device(const wchar_t* dev_name);
/// Checks if there is opened usb handle in handle_list for this device.
/// usb_lock mutex must be held before calling this routine.
-int known_device_locked(const char* dev_name);
+int known_device_locked(const wchar_t* dev_name);
/// Registers opened usb handle (adds it to handle_list).
int register_new_device(usb_handle* handle);
@@ -118,7 +118,7 @@
/// Closes opened usb handle
int usb_close(usb_handle* handle);
-int known_device_locked(const char* dev_name) {
+int known_device_locked(const wchar_t* dev_name) {
usb_handle* usb;
if (NULL != dev_name) {
@@ -126,7 +126,7 @@
for(usb = handle_list.next; usb != &handle_list; usb = usb->next) {
// In Windows names are not case sensetive!
if((NULL != usb->interface_name) &&
- (0 == stricmp(usb->interface_name, dev_name))) {
+ (0 == wcsicmp(usb->interface_name, dev_name))) {
return 1;
}
}
@@ -135,7 +135,7 @@
return 0;
}
-int known_device(const char* dev_name) {
+int known_device(const wchar_t* dev_name) {
int ret = 0;
if (NULL != dev_name) {
@@ -316,17 +316,16 @@
AdbGetInterfaceName(ret->adb_interface,
NULL,
&name_len,
- true);
+ false);
if (0 == name_len) {
D("AdbGetInterfaceName returned name length of zero: %s",
SystemErrorCodeToString(GetLastError()).c_str());
goto fail;
}
- ret->interface_name = (char*)malloc(name_len);
+ ret->interface_name = (wchar_t*)malloc(name_len * sizeof(ret->interface_name[0]));
if (NULL == ret->interface_name) {
- D("Could not allocate %lu bytes for interface_name: %s", name_len,
- strerror(errno));
+ D("Could not allocate %lu characters for interface_name: %s", name_len, strerror(errno));
goto fail;
}
@@ -334,7 +333,7 @@
if (!AdbGetInterfaceName(ret->adb_interface,
ret->interface_name,
&name_len,
- true)) {
+ false)) {
D("AdbGetInterfaceName failed: %s",
SystemErrorCodeToString(GetLastError()).c_str());
goto fail;
@@ -581,12 +580,10 @@
}
void find_devices() {
- usb_handle* handle = NULL;
+ usb_handle* handle = NULL;
char entry_buffer[2048];
- char interf_name[2048];
AdbInterfaceInfo* next_interface = (AdbInterfaceInfo*)(&entry_buffer[0]);
unsigned long entry_buffer_size = sizeof(entry_buffer);
- char* copy_name;
// Enumerate all present and active interfaces.
ADBAPIHANDLE enum_handle =
@@ -599,25 +596,21 @@
}
while (AdbNextInterface(enum_handle, next_interface, &entry_buffer_size)) {
- // TODO: FIXME - temp hack converting wchar_t into char.
- // It would be better to change AdbNextInterface so it will return
- // interface name as single char string.
- const wchar_t* wchar_name = next_interface->device_name;
- for(copy_name = interf_name;
- L'\0' != *wchar_name;
- wchar_name++, copy_name++) {
- *copy_name = (char)(*wchar_name);
- }
- *copy_name = '\0';
-
// Lets see if we already have this device in the list
- if (!known_device(interf_name)) {
+ if (!known_device(next_interface->device_name)) {
// This seems to be a new device. Open it!
- handle = do_usb_open(next_interface->device_name);
- if (NULL != handle) {
+ handle = do_usb_open(next_interface->device_name);
+ if (NULL != handle) {
// Lets see if this interface (device) belongs to us
if (recognized_device(handle)) {
- D("adding a new device %s", interf_name);
+ D("adding a new device %ls", next_interface->device_name);
+
+ // We don't request a wchar_t string from AdbGetSerialNumber() because of a bug in
+ // adb_winusb_interface.cpp:CopyMemory(buffer, ser_num->bString, bytes_written) where the
+ // last parameter should be (str_len * sizeof(wchar_t)). The bug reads 2 bytes past the
+ // end of a stack buffer in the best case, and in the unlikely case of a long serial
+ // number, it will read 2 bytes past the end of a heap allocation. This doesn't affect the
+ // resulting string, but we should avoid the bad reads in the first place.
char serial_number[512];
unsigned long serial_number_len = sizeof(serial_number);
if (AdbGetSerialNumber(handle->adb_interface,
@@ -628,7 +621,7 @@
if (register_new_device(handle)) {
register_usb_transport(handle, serial_number, NULL, 1);
} else {
- D("register_new_device failed for %s", interf_name);
+ D("register_new_device failed for %ls", next_interface->device_name);
usb_cleanup_handle(handle);
free(handle);
}
diff --git a/base/Android.mk b/base/Android.mk
index 4e6bd10..cba70d4 100644
--- a/base/Android.mk
+++ b/base/Android.mk
@@ -42,6 +42,12 @@
-Wextra \
-Werror \
+libbase_linux_cppflags := \
+ -Wexit-time-destructors \
+
+libbase_darwin_cppflags := \
+ -Wexit-time-destructors \
+
# Device
# ------------------------------------------------------------------------------
include $(CLEAR_VARS)
@@ -52,7 +58,7 @@
LOCAL_SRC_FILES_linux := $(libbase_linux_src_files)
LOCAL_SRC_FILES_windows := $(libbase_windows_src_files)
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
-LOCAL_CPPFLAGS := $(libbase_cppflags)
+LOCAL_CPPFLAGS := $(libbase_cppflags) $(libbase_linux_cppflags)
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
LOCAL_STATIC_LIBRARIES := libcutils
LOCAL_MULTILIB := both
@@ -78,6 +84,8 @@
LOCAL_SRC_FILES_windows := $(libbase_windows_src_files)
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_CPPFLAGS := $(libbase_cppflags)
+LOCAL_CPPFLAGS_darwin := $(libbase_darwin_cppflags)
+LOCAL_CPPFLAGS_linux := $(libbase_linux_cppflags)
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
LOCAL_STATIC_LIBRARIES := libcutils
LOCAL_MULTILIB := both
diff --git a/base/include/base/utf8.h b/base/include/base/utf8.h
index 3cc168d..3b0ed0a 100755
--- a/base/include/base/utf8.h
+++ b/base/include/base/utf8.h
@@ -19,6 +19,10 @@
#ifdef _WIN32
#include <string>
+#else
+// Bring in prototypes for standard APIs so that we can import them into the utf8 namespace.
+#include <fcntl.h> // open
+#include <unistd.h> // unlink
#endif
namespace android {
diff --git a/base/logging.cpp b/base/logging.cpp
index 01a046a..85f8b3f 100644
--- a/base/logging.cpp
+++ b/base/logging.cpp
@@ -154,17 +154,17 @@
namespace android {
namespace base {
-static mutex logging_lock;
+static auto& logging_lock = *new mutex();
#ifdef __ANDROID__
-static LogFunction gLogger = LogdLogger();
+static auto& gLogger = *new LogFunction(LogdLogger());
#else
-static LogFunction gLogger = StderrLogger;
+static auto& gLogger = *new LogFunction(StderrLogger);
#endif
static bool gInitialized = false;
static LogSeverity gMinimumLogSeverity = INFO;
-static std::unique_ptr<std::string> gProgramInvocationName;
+static auto& gProgramInvocationName = *new std::unique_ptr<std::string>();
LogSeverity GetMinimumLogSeverity() {
return gMinimumLogSeverity;
diff --git a/base/utf8.cpp b/base/utf8.cpp
index 62a118f..99f0f54 100755
--- a/base/utf8.cpp
+++ b/base/utf8.cpp
@@ -27,6 +27,18 @@
namespace android {
namespace base {
+// Helper to set errno based on GetLastError() after WideCharToMultiByte()/MultiByteToWideChar().
+static void SetErrnoFromLastError() {
+ switch (GetLastError()) {
+ case ERROR_NO_UNICODE_TRANSLATION:
+ errno = EILSEQ;
+ break;
+ default:
+ errno = EINVAL;
+ break;
+ }
+}
+
bool WideToUTF8(const wchar_t* utf16, const size_t size, std::string* utf8) {
utf8->clear();
@@ -49,6 +61,7 @@
const int chars_required = WideCharToMultiByte(CP_UTF8, flags, utf16, size,
NULL, 0, NULL, NULL);
if (chars_required <= 0) {
+ SetErrnoFromLastError();
return false;
}
@@ -59,6 +72,7 @@
&(*utf8)[0], chars_required, NULL,
NULL);
if (result != chars_required) {
+ SetErrnoFromLastError();
CHECK_LE(result, chars_required) << "WideCharToMultiByte wrote " << result
<< " chars to buffer of " << chars_required << " chars";
utf8->clear();
@@ -80,8 +94,8 @@
}
// Internal helper function that takes MultiByteToWideChar() flags.
-static bool _UTF8ToWideWithFlags(const char* utf8, const size_t size,
- std::wstring* utf16, const DWORD flags) {
+static bool UTF8ToWideWithFlags(const char* utf8, const size_t size, std::wstring* utf16,
+ const DWORD flags) {
utf16->clear();
if (size == 0) {
@@ -93,6 +107,7 @@
const int chars_required = MultiByteToWideChar(CP_UTF8, flags, utf8, size,
NULL, 0);
if (chars_required <= 0) {
+ SetErrnoFromLastError();
return false;
}
@@ -102,6 +117,7 @@
const int result = MultiByteToWideChar(CP_UTF8, flags, utf8, size,
&(*utf16)[0], chars_required);
if (result != chars_required) {
+ SetErrnoFromLastError();
CHECK_LE(result, chars_required) << "MultiByteToWideChar wrote " << result
<< " chars to buffer of " << chars_required << " chars";
utf16->clear();
@@ -113,13 +129,16 @@
bool UTF8ToWide(const char* utf8, const size_t size, std::wstring* utf16) {
// If strictly interpreting as UTF-8 succeeds, return success.
- if (_UTF8ToWideWithFlags(utf8, size, utf16, MB_ERR_INVALID_CHARS)) {
+ if (UTF8ToWideWithFlags(utf8, size, utf16, MB_ERR_INVALID_CHARS)) {
return true;
}
+ const int saved_errno = errno;
+
// Fallback to non-strict interpretation, allowing invalid characters and
// converting as best as possible, and return false to signify a problem.
- (void)_UTF8ToWideWithFlags(utf8, size, utf16, 0);
+ (void)UTF8ToWideWithFlags(utf8, size, utf16, 0);
+ errno = saved_errno;
return false;
}
@@ -140,7 +159,6 @@
int open(const char* name, int flags, ...) {
std::wstring name_utf16;
if (!UTF8ToWide(name, &name_utf16)) {
- errno = EINVAL;
return -1;
}
@@ -158,7 +176,6 @@
int unlink(const char* name) {
std::wstring name_utf16;
if (!UTF8ToWide(name, &name_utf16)) {
- errno = EINVAL;
return -1;
}
diff --git a/base/utf8_test.cpp b/base/utf8_test.cpp
index bbb54b1..13f6431 100755
--- a/base/utf8_test.cpp
+++ b/base/utf8_test.cpp
@@ -26,12 +26,16 @@
TEST(UTFStringConversionsTest, ConvertInvalidUTF8) {
std::wstring wide;
+ errno = 0;
+
// Standalone \xa2 is an invalid UTF-8 sequence, so this should return an
// error. Concatenate two C/C++ literal string constants to prevent the
// compiler from giving an error about "\xa2af" containing a "hex escape
// sequence out of range".
EXPECT_FALSE(android::base::UTF8ToWide("before\xa2" "after", &wide));
+ EXPECT_EQ(EILSEQ, errno);
+
// Even if an invalid character is encountered, UTF8ToWide() should still do
// its best to convert the rest of the string. sysdeps_win32.cpp:
// _console_write_utf8() depends on this behavior.
@@ -161,6 +165,7 @@
for (size_t i = 0; i < arraysize(convert_cases); i++) {
std::wstring converted;
+ errno = 0;
const bool success = UTF8ToWide(convert_cases[i].utf8,
strlen(convert_cases[i].utf8),
&converted);
@@ -171,6 +176,8 @@
if (success) {
std::wstring expected(convert_cases[i].wide);
EXPECT_EQ(expected, converted);
+ } else {
+ EXPECT_EQ(EILSEQ, errno);
}
}
@@ -227,6 +234,7 @@
for (size_t i = 0; i < arraysize(convert_cases); i++) {
std::string converted;
+ errno = 0;
const bool success = WideToUTF8(convert_cases[i].utf16,
wcslen(convert_cases[i].utf16),
&converted);
@@ -237,6 +245,8 @@
if (success) {
std::string expected(convert_cases[i].utf8);
EXPECT_EQ(expected, converted);
+ } else {
+ EXPECT_EQ(EILSEQ, errno);
}
}
}
diff --git a/crash_reporter/user_collector.cc b/crash_reporter/user_collector.cc
index 56e7bb9..6714f52 100644
--- a/crash_reporter/user_collector.cc
+++ b/crash_reporter/user_collector.cc
@@ -90,9 +90,9 @@
directory_failure_ = directory_failure;
filter_in_ = filter_in;
- gid_t groups[] = { AID_ROOT, AID_SYSTEM, AID_DBUS };
+ gid_t groups[] = { AID_ROOT, AID_SYSTEM, AID_DBUS, AID_READPROC };
if (setgroups(arraysize(groups), groups) != 0) {
- PLOG(FATAL) << "Unable to set groups to root, system, and dbus";
+ PLOG(FATAL) << "Unable to set groups to root, system, dbus, and readproc";
}
}
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index b9d03e5..9f72c83 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -277,8 +277,6 @@
" override the fs type and/or size\n"
" the bootloader reports.\n"
" getvar <variable> Display a bootloader variable.\n"
- " set_active <suffix> Sets the active slot. If slots are\n"
- " not supported, this does nothing.\n"
" boot <kernel> [ <ramdisk> [ <second> ] ] Download and boot kernel.\n"
" flash:raw boot <kernel> [ <ramdisk> [ <second> ] ]\n"
" Create bootimage and flash it.\n"
@@ -299,9 +297,15 @@
" -p <product> Specify product name.\n"
" -c <cmdline> Override kernel commandline.\n"
" -i <vendor id> Specify a custom USB vendor id.\n"
- " -b <base_addr> Specify a custom kernel base\n"
+ " -b, --base <base_addr> Specify a custom kernel base\n"
" address (default: 0x10000000).\n"
- " -n <page size> Specify the nand page size\n"
+ " --kernel-offset Specify a custom kernel offset.\n"
+ " (default: 0x00008000)\n"
+ " --ramdisk-offset Specify a custom ramdisk offset.\n"
+ " (default: 0x01000000)\n"
+ " --tags-offset Specify a custom tags offset.\n"
+ " (default: 0x00000100)\n"
+ " -n, --page-size <page size> Specify the nand page size\n"
" (default: 2048).\n"
" -S <size>[K|M|G] Automatically sparse files greater\n"
" than 'size'. 0 to disable.\n"
@@ -312,9 +316,15 @@
" to all slots. If this is not given,\n"
" slotted partitions will default to\n"
" the current active slot.\n"
+ " -a, --set-active[=<suffix>] Sets the active slot. If no suffix is\n"
+ " provided, this will default to the value\n"
+ " given by --slot. If slots are not\n"
+ " supported, this does nothing.\n"
+ " --unbuffered Do not buffer input or output.\n"
+ " --version Display version.\n"
+ " -h, --help show this message.\n"
);
}
-
static void* load_bootable_image(const char* kernel, const char* ramdisk,
const char* secondstage, int64_t* sz,
const char* cmdline) {
@@ -721,7 +731,7 @@
if (suffix == slot)
return slot;
}
- fprintf(stderr, "Slot %s does not exist. supported slots are:", slot);
+ fprintf(stderr, "Slot %s does not exist. supported slots are:\n", slot);
for (const std::string &suffix : suffixes) {
fprintf(stderr, "%s\n", suffix.c_str());
}
@@ -729,21 +739,21 @@
}
static void do_for_partition(usb_handle* usb, const char *part, const char *slot, std::function<void(const std::string&)> func, bool force_slot) {
- std::string partition_slot;
+ std::string has_slot;
std::string current_slot;
- if (!fb_getvar(usb, std::string("partition-slot:")+part, &partition_slot)) {
- /* If partition-slot is not supported, the answer is no. */
- partition_slot = "";
+ if (!fb_getvar(usb, std::string("has-slot:")+part, &has_slot)) {
+ /* If has-slot is not supported, the answer is no. */
+ has_slot = "no";
}
- if (partition_slot == "1") {
+ if (has_slot == "yes") {
if (!slot || slot[0] == 0) {
if (!fb_getvar(usb, "current-slot", ¤t_slot)) {
die("Failed to identify current slot.\n");
}
- func(std::string(part) + '-' + current_slot);
+ func(std::string(part) + current_slot);
} else {
- func(std::string(part) + '-' + slot);
+ func(std::string(part) + slot);
}
} else {
if (force_slot && slot && slot[0]) {
@@ -758,13 +768,13 @@
* If force_slot is true, it will fail if a slot is specified, and the given partition does not support slots.
*/
static void do_for_partitions(usb_handle* usb, const char *part, const char *slot, std::function<void(const std::string&)> func, bool force_slot) {
- std::string partition_slot;
+ std::string has_slot;
if (slot && strcmp(slot, "all") == 0) {
- if (!fb_getvar(usb, std::string("partition-slot:") + part, &partition_slot)) {
+ if (!fb_getvar(usb, std::string("has-slot:") + part, &has_slot)) {
die("Could not check if partition %s has slot.", part);
}
- if (partition_slot == "1") {
+ if (has_slot == "yes") {
std::vector<std::string> suffixes = get_suffixes(usb);
for (std::string &suffix : suffixes) {
do_for_partition(usb, part, suffix.c_str(), func, force_slot);
@@ -1066,37 +1076,50 @@
int main(int argc, char **argv)
{
- int wants_wipe = 0;
- int wants_reboot = 0;
- int wants_reboot_bootloader = 0;
+ bool wants_wipe = false;
+ bool wants_reboot = false;
+ bool wants_reboot_bootloader = false;
+ bool wants_set_active = false;
bool erase_first = true;
void *data;
int64_t sz;
int longindex;
std::string slot_override;
+ std::string next_active;
const struct option longopts[] = {
{"base", required_argument, 0, 'b'},
{"kernel_offset", required_argument, 0, 'k'},
+ {"kernel-offset", required_argument, 0, 'k'},
{"page_size", required_argument, 0, 'n'},
+ {"page-size", required_argument, 0, 'n'},
{"ramdisk_offset", required_argument, 0, 'r'},
+ {"ramdisk-offset", required_argument, 0, 'r'},
{"tags_offset", required_argument, 0, 't'},
+ {"tags-offset", required_argument, 0, 't'},
{"help", no_argument, 0, 'h'},
{"unbuffered", no_argument, 0, 0},
{"version", no_argument, 0, 0},
{"slot", required_argument, 0, 0},
+ {"set_active", optional_argument, 0, 'a'},
+ {"set-active", optional_argument, 0, 'a'},
{0, 0, 0, 0}
};
serial = getenv("ANDROID_SERIAL");
while (1) {
- int c = getopt_long(argc, argv, "wub:k:n:r:t:s:S:lp:c:i:m:h", longopts, &longindex);
+ int c = getopt_long(argc, argv, "wub:k:n:r:t:s:S:lp:c:i:m:ha::", longopts, &longindex);
if (c < 0) {
break;
}
/* Alphabetical cases */
switch (c) {
+ case 'a':
+ wants_set_active = true;
+ if (optarg)
+ next_active = optarg;
+ break;
case 'b':
base_addr = strtoul(optarg, 0, 16);
break;
@@ -1148,7 +1171,7 @@
erase_first = false;
break;
case 'w':
- wants_wipe = 1;
+ wants_wipe = true;
break;
case '?':
return 1;
@@ -1171,7 +1194,7 @@
argc -= optind;
argv += optind;
- if (argc == 0 && !wants_wipe) {
+ if (argc == 0 && !wants_wipe && !wants_set_active) {
usage();
return 1;
}
@@ -1190,6 +1213,18 @@
usb_handle* usb = open_device();
if (slot_override != "")
slot_override = verify_slot(usb, slot_override.c_str());
+ if (next_active != "")
+ next_active = verify_slot(usb, next_active.c_str());
+
+ if (wants_set_active) {
+ if (next_active == "") {
+ if (slot_override == "") {
+ wants_set_active = false;
+ } else {
+ next_active = slot_override;
+ }
+ }
+ }
while (argc > 0) {
if (!strcmp(*argv, "getvar")) {
@@ -1255,18 +1290,18 @@
fb_queue_command("signature", "installing signature");
skip(2);
} else if(!strcmp(*argv, "reboot")) {
- wants_reboot = 1;
+ wants_reboot = true;
skip(1);
if (argc > 0) {
if (!strcmp(*argv, "bootloader")) {
- wants_reboot = 0;
- wants_reboot_bootloader = 1;
+ wants_reboot = false;
+ wants_reboot_bootloader = true;
skip(1);
}
}
require(0);
} else if(!strcmp(*argv, "reboot-bootloader")) {
- wants_reboot_bootloader = 1;
+ wants_reboot_bootloader = true;
skip(1);
} else if (!strcmp(*argv, "continue")) {
fb_queue_command("continue", "resuming boot");
@@ -1335,7 +1370,7 @@
} else if(!strcmp(*argv, "flashall")) {
skip(1);
do_flashall(usb, slot_override.c_str(), erase_first);
- wants_reboot = 1;
+ wants_reboot = true;
} else if(!strcmp(*argv, "update")) {
if (argc > 1) {
do_update(usb, argv[1], slot_override.c_str(), erase_first);
@@ -1344,11 +1379,7 @@
do_update(usb, "update.zip", slot_override.c_str(), erase_first);
skip(1);
}
- wants_reboot = 1;
- } else if(!strcmp(*argv, "set_active")) {
- require(2);
- fb_set_active(argv[1]);
- skip(2);
+ wants_reboot = true;
} else if(!strcmp(*argv, "oem")) {
argc = do_oem_command(argc, argv);
} else if(!strcmp(*argv, "flashing")) {
@@ -1385,6 +1416,9 @@
fb_perform_format(usb, "cache", 1, nullptr, nullptr);
}
}
+ if (wants_set_active) {
+ fb_set_active(next_active.c_str());
+ }
if (wants_reboot) {
fb_queue_reboot();
fb_queue_wait_for_disconnect();
diff --git a/healthd/BatteryMonitor.cpp b/healthd/BatteryMonitor.cpp
index cb77a8e..63904b6 100644
--- a/healthd/BatteryMonitor.cpp
+++ b/healthd/BatteryMonitor.cpp
@@ -136,6 +136,9 @@
{ "USB_DCP", ANDROID_POWER_SUPPLY_TYPE_AC },
{ "USB_CDP", ANDROID_POWER_SUPPLY_TYPE_AC },
{ "USB_ACA", ANDROID_POWER_SUPPLY_TYPE_AC },
+ { "USB_C", ANDROID_POWER_SUPPLY_TYPE_AC },
+ { "USB_PD", ANDROID_POWER_SUPPLY_TYPE_AC },
+ { "USB_PD_DRP", ANDROID_POWER_SUPPLY_TYPE_USB },
{ "Wireless", ANDROID_POWER_SUPPLY_TYPE_WIRELESS },
{ NULL, 0 },
};
diff --git a/libcutils/fs_config.c b/libcutils/fs_config.c
index 2a178aa..f4454bb 100644
--- a/libcutils/fs_config.c
+++ b/libcutils/fs_config.c
@@ -88,6 +88,8 @@
{ 00771, AID_SHARED_RELRO, AID_SHARED_RELRO, 0, "data/misc/shared_relro" },
{ 00775, AID_MEDIA_RW, AID_MEDIA_RW, 0, "data/media" },
{ 00775, AID_MEDIA_RW, AID_MEDIA_RW, 0, "data/media/Music" },
+ { 00750, AID_ROOT, AID_SHELL, 0, "data/nativetest" },
+ { 00750, AID_ROOT, AID_SHELL, 0, "data/nativetest64" },
{ 00771, AID_SYSTEM, AID_SYSTEM, 0, "data" },
{ 00755, AID_ROOT, AID_SYSTEM, 0, "mnt" },
{ 00755, AID_ROOT, AID_ROOT, 0, "root" },
@@ -125,6 +127,8 @@
{ 00644, AID_MEDIA_RW, AID_MEDIA_RW, 0, "data/media/*" },
{ 00644, AID_SYSTEM, AID_SYSTEM, 0, "data/app-private/*" },
{ 00644, AID_APP, AID_APP, 0, "data/data/*" },
+ { 00640, AID_ROOT, AID_SHELL, 0, "data/nativetest/tests.txt" },
+ { 00640, AID_ROOT, AID_SHELL, 0, "data/nativetest64/tests.txt" },
{ 00750, AID_ROOT, AID_SHELL, 0, "data/nativetest/*" },
{ 00750, AID_ROOT, AID_SHELL, 0, "data/nativetest64/*" },
diff --git a/logd/LogKlog.cpp b/logd/LogKlog.cpp
index da5e78d..2a3f52f 100644
--- a/logd/LogKlog.cpp
+++ b/logd/LogKlog.cpp
@@ -582,7 +582,7 @@
// Some may view the following as an ugly heuristic, the desire is to
// beautify the kernel logs into an Android Logging format; the goal is
// admirable but costly.
- while ((isspace(*p) || !*p) && (p < &buf[len])) {
+ while ((p < &buf[len]) && (isspace(*p) || !*p)) {
++p;
}
if (p >= &buf[len]) { // timestamp, no content
@@ -596,7 +596,7 @@
const char *bt, *et, *cp;
bt = p;
- if (!fast<strncmp>(p, "[INFO]", 6)) {
+ if ((taglen >= 6) && !fast<strncmp>(p, "[INFO]", 6)) {
// <PRI>[<TIME>] "[INFO]"<tag> ":" message
bt = p + 6;
taglen -= 6;
@@ -620,7 +620,9 @@
p = cp + 1;
} else if (taglen) {
size = et - bt;
- if ((*bt == *cp) && fast<strncmp>(bt + 1, cp + 1, size - 1)) {
+ if ((taglen > size) && // enough space for match plus trailing :
+ (*bt == *cp) && // ubber fast<strncmp> pair
+ fast<strncmp>(bt + 1, cp + 1, size - 1)) {
// <PRI>[<TIME>] <tag>_host '<tag>.<num>' : message
if (!fast<strncmp>(bt + size - 5, "_host", 5)
&& !fast<strncmp>(bt + 1, cp + 1, size - 6)) {
@@ -694,7 +696,7 @@
p = cp + 1;
}
}
- }
+ } /* else no tag */
size = etag - tag;
if ((size <= 1)
// register names like x9
@@ -721,8 +723,12 @@
taglen = mp - tag;
}
}
+ // Deal with sloppy and simplistic harmless p = cp + 1 etc above.
+ if (len < (size_t)(p - buf)) {
+ p = &buf[len];
+ }
// skip leading space
- while ((isspace(*p) || !*p) && (p < &buf[len])) {
+ while ((p < &buf[len]) && (isspace(*p) || !*p)) {
++p;
}
// truncate trailing space or nuls
@@ -735,16 +741,26 @@
p = " ";
b = 1;
}
+ // paranoid sanity check, can not happen ...
if (b > LOGGER_ENTRY_MAX_PAYLOAD) {
b = LOGGER_ENTRY_MAX_PAYLOAD;
}
+ if (taglen > LOGGER_ENTRY_MAX_PAYLOAD) {
+ taglen = LOGGER_ENTRY_MAX_PAYLOAD;
+ }
+ // calculate buffer copy requirements
size_t n = 1 + taglen + 1 + b + 1;
- int rc = n;
- if ((taglen > n) || (b > n)) { // Can not happen ...
- rc = -EINVAL;
- return rc;
+ // paranoid sanity check, first two just can not happen ...
+ if ((taglen > n) || (b > n) || (n > USHRT_MAX)) {
+ return -EINVAL;
}
+ // Careful.
+ // We are using the stack to house the log buffer for speed reasons.
+ // If we malloc'd this buffer, we could get away without n's USHRT_MAX
+ // test above, but we would then required a max(n, USHRT_MAX) as
+ // truncating length argument to logbuf->log() below. Gain is protection
+ // of stack sanity and speedup, loss is truncated long-line content.
char newstr[n];
char *np = newstr;
@@ -763,8 +779,8 @@
np[b] = '\0';
// Log message
- rc = logbuf->log(LOG_ID_KERNEL, now, uid, pid, tid, newstr,
- (n <= USHRT_MAX) ? (unsigned short) n : USHRT_MAX);
+ int rc = logbuf->log(LOG_ID_KERNEL, now, uid, pid, tid, newstr,
+ (unsigned short) n);
// notify readers
if (!rc) {
diff --git a/metricsd/metrics_daemon.rc b/metricsd/metrics_daemon.rc
index 0ee577e..8b24749 100644
--- a/metricsd/metrics_daemon.rc
+++ b/metricsd/metrics_daemon.rc
@@ -1,7 +1,7 @@
on post-fs-data
mkdir /data/misc/metrics 0770 system system
-service metrics_daemon /system/bin/metrics_daemon --uploader -nodaemon
+service metrics_daemon /system/bin/metrics_daemon --uploader --foreground --logtosyslog
class late_start
user system
group system dbus inet
diff --git a/metricsd/metrics_daemon_main.cc b/metricsd/metrics_daemon_main.cc
index 50c279d..8573f68 100644
--- a/metricsd/metrics_daemon_main.cc
+++ b/metricsd/metrics_daemon_main.cc
@@ -53,7 +53,7 @@
}
int main(int argc, char** argv) {
- DEFINE_bool(daemon, true, "run as daemon (use -nodaemon for debugging)");
+ DEFINE_bool(foreground, false, "Don't daemonize");
// The uploader is disabled by default on ChromeOS as Chrome is responsible
// for sending the metrics.
@@ -79,13 +79,28 @@
metrics::kMetricsDirectory,
"Root of the configuration files (testing only)");
+ DEFINE_bool(logtostderr, false, "Log to standard error");
+ DEFINE_bool(logtosyslog, false, "Log to syslog");
+
brillo::FlagHelper::Init(argc, argv, "Chromium OS Metrics Daemon");
- // Also log to stderr when not running as daemon.
- brillo::InitLog(brillo::kLogToSyslog | brillo::kLogHeader |
- (FLAGS_daemon ? 0 : brillo::kLogToStderr));
+ int logging_location = (FLAGS_foreground ? brillo::kLogToStderr
+ : brillo::kLogToSyslog);
+ if (FLAGS_logtosyslog)
+ logging_location = brillo::kLogToSyslog;
- if (FLAGS_daemon && daemon(0, 0) != 0) {
+ if (FLAGS_logtostderr)
+ logging_location = brillo::kLogToStderr;
+
+ // Also log to stderr when not running as daemon.
+ brillo::InitLog(logging_location | brillo::kLogHeader);
+
+ if (FLAGS_logtostderr && FLAGS_logtosyslog) {
+ LOG(ERROR) << "only one of --logtosyslog and --logtostderr can be set";
+ return 1;
+ }
+
+ if (!FLAGS_foreground && daemon(0, 0) != 0) {
return errno;
}
diff --git a/metricsd/uploader/system_profile_cache.cc b/metricsd/uploader/system_profile_cache.cc
index f7060a2..637cf9e 100644
--- a/metricsd/uploader/system_profile_cache.cc
+++ b/metricsd/uploader/system_profile_cache.cc
@@ -179,13 +179,13 @@
metrics::SystemProfileProto_Channel SystemProfileCache::ProtoChannelFromString(
const std::string& channel) {
- if (channel == "stable") {
+ if (channel == "stable-channel") {
return metrics::SystemProfileProto::CHANNEL_STABLE;
- } else if (channel == "dev") {
+ } else if (channel == "dev-channel") {
return metrics::SystemProfileProto::CHANNEL_DEV;
- } else if (channel == "beta") {
+ } else if (channel == "beta-channel") {
return metrics::SystemProfileProto::CHANNEL_BETA;
- } else if (channel == "canary") {
+ } else if (channel == "canary-channel") {
return metrics::SystemProfileProto::CHANNEL_CANARY;
}
diff --git a/metricsd/uploader/upload_service_test.cc b/metricsd/uploader/upload_service_test.cc
index 236376a..47e7b91 100644
--- a/metricsd/uploader/upload_service_test.cc
+++ b/metricsd/uploader/upload_service_test.cc
@@ -214,10 +214,10 @@
metrics::SystemProfileProto::CHANNEL_UNKNOWN);
EXPECT_EQ(metrics::SystemProfileProto::CHANNEL_DEV,
- SystemProfileCache::ProtoChannelFromString("dev"));
+ SystemProfileCache::ProtoChannelFromString("dev-channel"));
EXPECT_EQ(metrics::SystemProfileProto::CHANNEL_STABLE,
- SystemProfileCache::ProtoChannelFromString("stable"));
+ SystemProfileCache::ProtoChannelFromString("stable-channel"));
EXPECT_EQ(metrics::SystemProfileProto::CHANNEL_UNKNOWN,
SystemProfileCache::ProtoChannelFromString("this is a test"));
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 7fa4b95..a0b1acf 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -342,7 +342,6 @@
# create dalvik-cache, so as to enforce our permissions
mkdir /data/dalvik-cache 0771 root root
- mkdir /data/dalvik-cache/profiles 0711 system system
# create resource-cache and double-check the perms
mkdir /data/resource-cache 0771 system system
diff --git a/toolbox/top.c b/toolbox/top.c
index 1e99d4c..0ea5a5e 100644
--- a/toolbox/top.c
+++ b/toolbox/top.c
@@ -158,7 +158,7 @@
fprintf(stderr, "Invalid argument \"%s\" for option -s.\n", argv[i]);
exit(EXIT_FAILURE);
}
- if (!strcmp(argv[i], "-t")) { threads = 1; continue; }
+ if (!strcmp(argv[i], "-H") || !strcmp(argv[i], "-t")) { threads = 1; continue; }
if (!strcmp(argv[i], "-h")) {
usage(argv[0]);
exit(EXIT_SUCCESS);
@@ -187,6 +187,7 @@
read_procs();
print_procs();
free_old_procs();
+ fflush(stdout);
}
return 0;
@@ -566,7 +567,7 @@
" -n num Updates to show before exiting.\n"
" -d num Seconds to wait between updates.\n"
" -s col Column to sort by (cpu,vss,rss,thr).\n"
- " -t Show threads instead of processes.\n"
+ " -H Show threads instead of processes.\n"
" -h Display this help screen.\n",
cmd);
}