Merge "init: Adding header guard to tokenizer"
diff --git a/adb/adb.cpp b/adb/adb.cpp
index aa9ef55..aa0256d 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -801,11 +801,13 @@
return 1;
}
+ std::string error;
InstallStatus r;
if (kill_forward) {
r = remove_listener(pieces[0].c_str(), transport);
} else {
- r = install_listener(pieces[0], pieces[1].c_str(), transport, no_rebind);
+ r = install_listener(pieces[0], pieces[1].c_str(), transport,
+ no_rebind, &error);
}
if (r == INSTALL_STATUS_OK) {
#if ADB_HOST
@@ -821,7 +823,8 @@
case INSTALL_STATUS_OK: message = "success (!)"; break;
case INSTALL_STATUS_INTERNAL_ERROR: message = "internal error"; break;
case INSTALL_STATUS_CANNOT_BIND:
- message = android::base::StringPrintf("cannot bind to socket: %s", strerror(errno));
+ message = android::base::StringPrintf("cannot bind to socket: %s",
+ error.c_str());
break;
case INSTALL_STATUS_CANNOT_REBIND:
message = android::base::StringPrintf("cannot rebind existing socket");
diff --git a/adb/adb_client.cpp b/adb/adb_client.cpp
index 418662c..6d75966 100644
--- a/adb/adb_client.cpp
+++ b/adb/adb_client.cpp
@@ -153,8 +153,8 @@
}
int fd;
+ std::string reason;
if (__adb_server_name) {
- std::string reason;
fd = network_connect(__adb_server_name, __adb_server_port, SOCK_STREAM, 0, &reason);
if (fd == -1) {
*error = android::base::StringPrintf("can't connect to %s:%d: %s",
@@ -163,9 +163,10 @@
return -2;
}
} else {
- fd = socket_loopback_client(__adb_server_port, SOCK_STREAM);
+ fd = network_loopback_client(__adb_server_port, SOCK_STREAM, &reason);
if (fd == -1) {
- *error = perror_str("cannot connect to daemon");
+ *error = android::base::StringPrintf("cannot connect to daemon: %s",
+ reason.c_str());
return -2;
}
}
diff --git a/adb/adb_io_test.cpp b/adb/adb_io_test.cpp
index 8fd5cbf..0ae21db 100644
--- a/adb/adb_io_test.cpp
+++ b/adb/adb_io_test.cpp
@@ -28,30 +28,7 @@
#include <string>
#include "base/file.h"
-
-class TemporaryFile {
- public:
- TemporaryFile() {
- init("/data/local/tmp");
- if (fd == -1) {
- init("/tmp");
- }
- }
-
- ~TemporaryFile() {
- close(fd);
- unlink(filename);
- }
-
- int fd;
- char filename[1024];
-
- private:
- void init(const char* tmp_dir) {
- snprintf(filename, sizeof(filename), "%s/TemporaryFile-XXXXXX", tmp_dir);
- fd = mkstemp(filename);
- }
-};
+#include "base/test_utils.h"
TEST(io, ReadFdExactly_whole) {
const char expected[] = "Foobar";
diff --git a/adb/adb_listeners.cpp b/adb/adb_listeners.cpp
index bb45022..1e7ce5d 100644
--- a/adb/adb_listeners.cpp
+++ b/adb/adb_listeners.cpp
@@ -110,27 +110,30 @@
free_listener(reinterpret_cast<alistener*>(listener));
}
-static int local_name_to_fd(const char* name) {
+static int local_name_to_fd(const char* name, std::string* error) {
if (!strncmp("tcp:", name, 4)) {
int port = atoi(name + 4);
if (gListenAll > 0) {
- return socket_inaddr_any_server(port, SOCK_STREAM);
+ return network_inaddr_any_server(port, SOCK_STREAM, error);
} else {
- return socket_loopback_server(port, SOCK_STREAM);
+ return network_loopback_server(port, SOCK_STREAM, error);
}
}
#if !defined(_WIN32) // No Unix-domain sockets on Windows.
// It's nonsensical to support the "reserved" space on the adb host side
if (!strncmp(name, "local:", 6)) {
- return socket_local_server(name + 6, ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
+ return network_local_server(name + 6,
+ ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM, error);
} else if (!strncmp(name, "localabstract:", 14)) {
- return socket_local_server(name + 14, ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
+ return network_local_server(name + 14,
+ ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM, error);
} else if (!strncmp(name, "localfilesystem:", 16)) {
- return socket_local_server(name + 16, ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM);
+ return network_local_server(name + 16,
+ ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM, error);
}
#endif
- printf("unknown local portname '%s'\n", name);
+ *error = android::base::StringPrintf("unknown local portname '%s'", name);
return -1;
}
@@ -178,7 +181,8 @@
InstallStatus install_listener(const std::string& local_name,
const char *connect_to,
atransport* transport,
- int no_rebind)
+ int no_rebind,
+ std::string* error)
{
for (alistener* l = listener_list.next; l != &listener_list; l = l->next) {
if (local_name == l->local_name) {
@@ -226,9 +230,9 @@
goto nomem;
}
- listener->fd = local_name_to_fd(listener->local_name);
+ listener->fd = local_name_to_fd(listener->local_name, error);
if (listener->fd < 0) {
- printf("cannot bind '%s': %s\n", listener->local_name, strerror(errno));
+ printf("cannot bind '%s': %s\n", listener->local_name, error->c_str());
free(listener->local_name);
free(listener->connect_to);
free(listener);
diff --git a/adb/adb_listeners.h b/adb/adb_listeners.h
index 67deb21..fa98eed 100644
--- a/adb/adb_listeners.h
+++ b/adb/adb_listeners.h
@@ -33,7 +33,8 @@
InstallStatus install_listener(const std::string& local_name,
const char* connect_to,
atransport* transport,
- int no_rebind);
+ int no_rebind,
+ std::string* error);
std::string format_listeners();
diff --git a/adb/adb_utils.cpp b/adb/adb_utils.cpp
index 6fa6c2e..12208cd 100644
--- a/adb/adb_utils.cpp
+++ b/adb/adb_utils.cpp
@@ -28,17 +28,10 @@
#include <base/logging.h>
#include <base/stringprintf.h>
#include <base/strings.h>
-#include <cutils/sockets.h>
#include "adb_trace.h"
#include "sysdeps.h"
-#if defined(_WIN32)
-#include <ws2tcpip.h>
-#else
-#include <netdb.h>
-#endif
-
bool getcwd(std::string* s) {
char* cwd = getcwd(nullptr, 0);
if (cwd != nullptr) *s = cwd;
@@ -72,24 +65,36 @@
return result;
}
-int mkdirs(const std::string& path) {
- // TODO: rewrite this function and merge it with the *other* mkdirs in adb.
- std::unique_ptr<char> path_rw(strdup(path.c_str()));
- int ret;
- char* x = path_rw.get() + 1;
+std::string adb_basename(const std::string& path) {
+ size_t base = path.find_last_of(OS_PATH_SEPARATORS);
+ return (base != std::string::npos) ? path.substr(base + 1) : path;
+}
- for(;;) {
- x = const_cast<char*>(adb_dirstart(x));
- if(x == 0) return 0;
- *x = 0;
- ret = adb_mkdir(path_rw.get(), 0775);
- *x = OS_PATH_SEPARATOR;
- if((ret < 0) && (errno != EEXIST)) {
- return ret;
+static bool real_mkdirs(const std::string& path) {
+ std::vector<std::string> path_components = android::base::Split(path, OS_PATH_SEPARATOR_STR);
+ // TODO: all the callers do unlink && mkdirs && adb_creat ---
+ // that's probably the operation we should expose.
+ path_components.pop_back();
+ std::string partial_path;
+ for (const auto& path_component : path_components) {
+ if (partial_path.back() != OS_PATH_SEPARATOR) partial_path += OS_PATH_SEPARATOR;
+ partial_path += path_component;
+ if (adb_mkdir(partial_path.c_str(), 0775) == -1 && errno != EEXIST) {
+ return false;
}
- x++;
}
- return 0;
+ return true;
+}
+
+bool mkdirs(const std::string& path) {
+#if defined(_WIN32)
+ // Replace '/' with '\\' so we can share the code.
+ std::string clean_path = path;
+ std::replace(clean_path.begin(), clean_path.end(), '/', '\\');
+ return real_mkdirs(clean_path);
+#else
+ return real_mkdirs(path);
+#endif
}
void dump_hex(const void* data, size_t byte_count) {
@@ -166,18 +171,3 @@
<< " (" << *canonical_address << ")";
return true;
}
-
-int network_connect(const std::string& host, int port, int type, int timeout, std::string* error) {
- int getaddrinfo_error = 0;
- int fd = socket_network_client_timeout(host.c_str(), port, type, timeout, &getaddrinfo_error);
- if (fd != -1) {
- return fd;
- }
- if (getaddrinfo_error != 0) {
- // TODO: gai_strerror is not thread safe on Win32.
- *error = gai_strerror(getaddrinfo_error);
- } else {
- *error = strerror(errno);
- }
- return -1;
-}
diff --git a/adb/adb_utils.h b/adb/adb_utils.h
index 673aaac..8c5208c 100644
--- a/adb/adb_utils.h
+++ b/adb/adb_utils.h
@@ -21,8 +21,9 @@
bool getcwd(std::string* cwd);
bool directory_exists(const std::string& path);
+std::string adb_basename(const std::string& path);
-int mkdirs(const std::string& path);
+bool mkdirs(const std::string& path);
std::string escape_arg(const std::string& s);
@@ -39,6 +40,4 @@
std::string* host, int* port,
std::string* error);
-int network_connect(const std::string& host, int port, int type, int timeout, std::string* error);
-
#endif
diff --git a/adb/adb_utils_test.cpp b/adb/adb_utils_test.cpp
index 7aa610a..309ac02 100644
--- a/adb/adb_utils_test.cpp
+++ b/adb/adb_utils_test.cpp
@@ -18,6 +18,13 @@
#include <gtest/gtest.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "sysdeps.h"
+
+#include <base/test_utils.h>
+
TEST(adb_utils, directory_exists) {
ASSERT_TRUE(directory_exists("/proc"));
ASSERT_FALSE(directory_exists("/proc/self")); // Symbolic link.
@@ -51,6 +58,11 @@
ASSERT_EQ(R"('abc)')", escape_arg("abc)"));
}
+TEST(adb_utils, adb_basename) {
+ EXPECT_EQ("sh", adb_basename("/system/bin/sh"));
+ EXPECT_EQ("sh", adb_basename("sh"));
+}
+
TEST(adb_utils, parse_host_and_port) {
std::string canonical_address;
std::string host;
@@ -132,3 +144,11 @@
EXPECT_FALSE(parse_host_and_port("1.2.3.4:0", &canonical_address, &host, &port, &error));
EXPECT_FALSE(parse_host_and_port("1.2.3.4:65536", &canonical_address, &host, &port, &error));
}
+
+TEST(adb_utils, mkdirs) {
+ TemporaryDir td;
+ std::string path = std::string(td.path) + "/dir/subdir/file";
+ EXPECT_TRUE(mkdirs(path));
+ EXPECT_NE(-1, adb_creat(path.c_str(), 0600));
+ EXPECT_FALSE(mkdirs(path + "/subdir/"));
+}
diff --git a/adb/client/main.cpp b/adb/client/main.cpp
index c018b8a..2b174cd 100644
--- a/adb/client/main.cpp
+++ b/adb/client/main.cpp
@@ -150,9 +150,10 @@
local_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT);
adb_auth_init();
+ std::string error;
std::string local_name = android::base::StringPrintf("tcp:%d", server_port);
- if (install_listener(local_name, "*smartsocket*", nullptr, 0)) {
- LOG(FATAL) << "Could not install *smartsocket* listener";
+ if (install_listener(local_name, "*smartsocket*", nullptr, 0, &error)) {
+ LOG(FATAL) << "Could not install *smartsocket* listener: " << error;
}
if (is_daemon) {
diff --git a/adb/commandline.cpp b/adb/commandline.cpp
index d54faec..d7a0c8d 100644
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -847,25 +847,25 @@
* Given <hint>, try to construct an absolute path to the
* ANDROID_PRODUCT_OUT dir.
*/
-static std::string find_product_out_path(const char* hint) {
- if (hint == NULL || hint[0] == '\0') {
+static std::string find_product_out_path(const std::string& hint) {
+ if (hint.empty()) {
return "";
}
// If it's already absolute, don't bother doing any work.
- if (adb_is_absolute_host_path(hint)) {
+ if (adb_is_absolute_host_path(hint.c_str())) {
return hint;
}
// If there are any slashes in it, assume it's a relative path;
// make it absolute.
- if (adb_dirstart(hint) != nullptr) {
+ if (hint.find_first_of(OS_PATH_SEPARATORS) != std::string::npos) {
std::string cwd;
if (!getcwd(&cwd)) {
fprintf(stderr, "adb: getcwd failed: %s\n", strerror(errno));
return "";
}
- return android::base::StringPrintf("%s%s%s", cwd.c_str(), OS_PATH_SEPARATOR_STR, hint);
+ return android::base::StringPrintf("%s%c%s", cwd.c_str(), OS_PATH_SEPARATOR, hint.c_str());
}
// It's a string without any slashes. Try to do something with it.
@@ -889,7 +889,7 @@
path += hint;
if (!directory_exists(path)) {
fprintf(stderr, "adb: Couldn't find a product dir based on -p %s; "
- "\"%s\" doesn't exist\n", hint, path.c_str());
+ "\"%s\" doesn't exist\n", hint.c_str(), path.c_str());
return "";
}
return path;
@@ -990,7 +990,7 @@
/* this is a special flag used only when the ADB client launches the ADB Server */
is_daemon = 1;
} else if (!strncmp(argv[0], "-p", 2)) {
- const char *product = NULL;
+ const char* product = nullptr;
if (argv[0][2] == '\0') {
if (argc < 2) return usage();
product = argv[1];
@@ -1462,22 +1462,11 @@
return pm_command(transport, serial, argc, argv);
}
-static int delete_file(TransportType transport, const char* serial, char* filename) {
+static int delete_file(TransportType transport, const char* serial, const std::string& filename) {
std::string cmd = "shell:rm -f " + escape_arg(filename);
return send_shell_command(transport, serial, cmd);
}
-static const char* get_basename(const char* filename)
-{
- const char* basename = adb_dirstop(filename);
- if (basename) {
- basename++;
- return basename;
- } else {
- return filename;
- }
-}
-
static int install_app(TransportType transport, const char* serial, int argc, const char** argv) {
static const char *const DATA_DEST = "/data/local/tmp/%s";
static const char *const SD_DEST = "/sdcard/tmp/%s";
@@ -1514,13 +1503,12 @@
}
const char* apk_file = argv[last_apk];
- char apk_dest[PATH_MAX];
- snprintf(apk_dest, sizeof apk_dest, where, get_basename(apk_file));
- int err = do_sync_push(apk_file, apk_dest, 0 /* no show progress */);
+ std::string apk_dest = android::base::StringPrintf(where, adb_basename(apk_file).c_str());
+ int err = do_sync_push(apk_file, apk_dest.c_str(), 0 /* no show progress */);
if (err) {
goto cleanup_apk;
} else {
- argv[last_apk] = apk_dest; /* destination name, not source location */
+ argv[last_apk] = apk_dest.c_str(); /* destination name, not source location */
}
err = pm_command(transport, serial, argc, argv);
@@ -1604,7 +1592,7 @@
std::string cmd = android::base::StringPrintf(
"exec:pm install-write -S %" PRIu64 " %d %d_%s -",
- static_cast<uint64_t>(sb.st_size), session_id, i, get_basename(file));
+ static_cast<uint64_t>(sb.st_size), session_id, i, adb_basename(file).c_str());
int localFd = adb_open(file, O_RDONLY);
if (localFd < 0) {
diff --git a/adb/console.cpp b/adb/console.cpp
index b7f5345..ba5a72b 100644
--- a/adb/console.cpp
+++ b/adb/console.cpp
@@ -71,9 +71,11 @@
return -1;
}
- int fd = socket_loopback_client(port, SOCK_STREAM);
+ std::string error;
+ int fd = network_loopback_client(port, SOCK_STREAM, &error);
if (fd == -1) {
- fprintf(stderr, "error: could not connect to TCP port %d\n", port);
+ fprintf(stderr, "error: could not connect to TCP port %d: %s\n", port,
+ error.c_str());
return -1;
}
return fd;
diff --git a/adb/daemon/main.cpp b/adb/daemon/main.cpp
index 157c97b..a63d67e 100644
--- a/adb/daemon/main.cpp
+++ b/adb/daemon/main.cpp
@@ -177,10 +177,13 @@
LOG(FATAL) << "Could not set selinux context";
}
}
+ std::string error;
std::string local_name =
android::base::StringPrintf("tcp:%d", server_port);
- if (install_listener(local_name, "*smartsocket*", nullptr, 0)) {
- LOG(FATAL) << "Could not install *smartsocket* listener";
+ if (install_listener(local_name, "*smartsocket*", nullptr, 0,
+ &error)) {
+ LOG(FATAL) << "Could not install *smartsocket* listener: "
+ << error;
}
}
diff --git a/adb/file_sync_client.cpp b/adb/file_sync_client.cpp
index 49d42a3..da80013 100644
--- a/adb/file_sync_client.cpp
+++ b/adb/file_sync_client.cpp
@@ -35,6 +35,8 @@
#include "adb_utils.h"
#include "file_sync_service.h"
+#include <base/stringprintf.h>
+
static unsigned long long total_bytes;
static long long start_time;
@@ -92,36 +94,30 @@
typedef void (*sync_ls_cb)(unsigned mode, unsigned size, unsigned time, const char *name, void *cookie);
static int sync_ls(int fd, const char* path, sync_ls_cb func, void* cookie) {
+ int len = strlen(path);
+ if (len > 1024) goto fail;
+
syncmsg msg;
- char buf[257];
- int len;
-
- len = strlen(path);
- if(len > 1024) goto fail;
-
msg.req.id = ID_LIST;
msg.req.namelen = htoll(len);
- if(!WriteFdExactly(fd, &msg.req, sizeof(msg.req)) ||
- !WriteFdExactly(fd, path, len)) {
+ if (!WriteFdExactly(fd, &msg.req, sizeof(msg.req)) || !WriteFdExactly(fd, path, len)) {
goto fail;
}
- for(;;) {
- if(!ReadFdExactly(fd, &msg.dent, sizeof(msg.dent))) break;
- if(msg.dent.id == ID_DONE) return 0;
- if(msg.dent.id != ID_DENT) break;
+ for (;;) {
+ if (!ReadFdExactly(fd, &msg.dent, sizeof(msg.dent))) break;
+ if (msg.dent.id == ID_DONE) return 0;
+ if (msg.dent.id != ID_DENT) break;
len = ltohl(msg.dent.namelen);
- if(len > 256) break;
+ if (len > 256) break;
- if(!ReadFdExactly(fd, buf, len)) break;
+ char buf[257];
+ if (!ReadFdExactly(fd, buf, len)) break;
buf[len] = 0;
- func(ltohl(msg.dent.mode),
- ltohl(msg.dent.size),
- ltohl(msg.dent.time),
- buf, cookie);
+ func(ltohl(msg.dent.mode), ltohl(msg.dent.size), ltohl(msg.dent.time), buf, cookie);
}
fail:
@@ -220,7 +216,7 @@
return 0;
}
-static int write_data_file(int fd, const char *path, syncsendbuf *sbuf, int show_progress)
+static int write_data_file(int fd, const char *path, syncsendbuf *sbuf, bool show_progress)
{
int lfd, err = 0;
unsigned long long size = 0;
@@ -274,7 +270,7 @@
}
static int write_data_buffer(int fd, char* file_buffer, int size, syncsendbuf *sbuf,
- int show_progress)
+ bool show_progress)
{
int err = 0;
int total = 0;
@@ -308,10 +304,8 @@
#else
static int write_data_link(int fd, const char *path, syncsendbuf *sbuf)
{
- int len, ret;
-
- len = readlink(path, sbuf->data, SYNC_DATA_MAX-1);
- if(len < 0) {
+ int len = readlink(path, sbuf->data, SYNC_DATA_MAX-1);
+ if (len < 0) {
fprintf(stderr, "error reading link '%s': %s\n", path, strerror(errno));
return -1;
}
@@ -320,9 +314,9 @@
sbuf->size = htoll(len + 1);
sbuf->id = ID_DATA;
- ret = !WriteFdExactly(fd, sbuf, sizeof(unsigned) * 2 + len + 1);
- if(ret)
+ if (!WriteFdExactly(fd, sbuf, sizeof(unsigned) * 2 + len + 1)) {
return -1;
+ }
total_bytes += len + 1;
@@ -331,7 +325,7 @@
#endif
static int sync_send(int fd, const char *lpath, const char *rpath,
- unsigned mtime, mode_t mode, int show_progress)
+ unsigned mtime, mode_t mode, bool show_progress)
{
syncmsg msg;
int len, r;
@@ -396,7 +390,7 @@
return -1;
}
-static int sync_recv(int fd, const char* rpath, const char* lpath, int show_progress) {
+static int sync_recv(int fd, const char* rpath, const char* lpath, bool show_progress) {
syncmsg msg;
int len;
int lfd = -1;
@@ -523,12 +517,12 @@
return 1;
}
- if(sync_ls(fd, path, do_sync_ls_cb, 0)) {
+ if (sync_ls(fd, path, do_sync_ls_cb, 0)) {
return 1;
- } else {
- sync_quit(fd);
- return 0;
}
+
+ sync_quit(fd);
+ return 0;
}
struct copyinfo
@@ -712,11 +706,7 @@
}
-int do_sync_push(const char *lpath, const char *rpath, int show_progress)
-{
- struct stat st;
- unsigned mode;
-
+int do_sync_push(const char* lpath, const char* rpath, bool show_progress) {
std::string error;
int fd = adb_connect("sync:", &error);
if (fd < 0) {
@@ -724,51 +714,38 @@
return 1;
}
- if(stat(lpath, &st)) {
+ struct stat st;
+ if (stat(lpath, &st)) {
fprintf(stderr,"cannot stat '%s': %s\n", lpath, strerror(errno));
sync_quit(fd);
return 1;
}
- if(S_ISDIR(st.st_mode)) {
+ if (S_ISDIR(st.st_mode)) {
BEGIN();
- if(copy_local_dir_remote(fd, lpath, rpath, 0, 0)) {
+ if (copy_local_dir_remote(fd, lpath, rpath, 0, 0)) {
return 1;
- } else {
- END();
- sync_quit(fd);
}
} else {
- if(sync_readmode(fd, rpath, &mode)) {
+ unsigned mode;
+ if (sync_readmode(fd, rpath, &mode)) {
return 1;
}
- if((mode != 0) && S_ISDIR(mode)) {
- /* if we're copying a local file to a remote directory,
- ** we *really* want to copy to remotedir + "/" + localfilename
- */
- const char *name = adb_dirstop(lpath);
- if(name == 0) {
- name = lpath;
- } else {
- name++;
- }
- int tmplen = strlen(name) + strlen(rpath) + 2;
- char *tmp = reinterpret_cast<char*>(
- malloc(strlen(name) + strlen(rpath) + 2));
- if(tmp == 0) return 1;
- snprintf(tmp, tmplen, "%s/%s", rpath, name);
- rpath = tmp;
+ std::string path_holder;
+ if ((mode != 0) && S_ISDIR(mode)) {
+ // If we're copying a local file to a remote directory,
+ // we really want to copy to remote_dir + "/" + local_filename.
+ path_holder = android::base::StringPrintf("%s/%s", rpath, adb_basename(lpath).c_str());
+ rpath = path_holder.c_str();
}
BEGIN();
- if(sync_send(fd, lpath, rpath, st.st_mtime, st.st_mode, show_progress)) {
+ if (sync_send(fd, lpath, rpath, st.st_mtime, st.st_mode, show_progress)) {
return 1;
- } else {
- END();
- sync_quit(fd);
- return 0;
}
}
+ END();
+ sync_quit(fd);
return 0;
}
@@ -934,11 +911,7 @@
return ret;
}
-int do_sync_pull(const char *rpath, const char *lpath, int show_progress, int copy_attrs)
-{
- unsigned mode, time;
- struct stat st;
-
+int do_sync_pull(const char* rpath, const char* lpath, bool show_progress, int copy_attrs) {
std::string error;
int fd = adb_connect("sync:", &error);
if (fd < 0) {
@@ -946,56 +919,46 @@
return 1;
}
- if(sync_readtime(fd, rpath, &time, &mode)) {
+ unsigned mode, time;
+ if (sync_readtime(fd, rpath, &time, &mode)) {
return 1;
}
- if(mode == 0) {
+ if (mode == 0) {
fprintf(stderr,"remote object '%s' does not exist\n", rpath);
return 1;
}
- if(S_ISREG(mode) || S_ISLNK(mode) || S_ISCHR(mode) || S_ISBLK(mode)) {
- if(stat(lpath, &st) == 0) {
- if(S_ISDIR(st.st_mode)) {
- /* if we're copying a remote file to a local directory,
- ** we *really* want to copy to localdir + "/" + remotefilename
- */
- const char *name = adb_dirstop(rpath);
- if(name == 0) {
- name = rpath;
- } else {
- name++;
- }
- int tmplen = strlen(name) + strlen(lpath) + 2;
- char *tmp = reinterpret_cast<char*>(malloc(tmplen));
- if(tmp == 0) return 1;
- snprintf(tmp, tmplen, "%s/%s", lpath, name);
- lpath = tmp;
+ if (S_ISREG(mode) || S_ISLNK(mode) || S_ISCHR(mode) || S_ISBLK(mode)) {
+ std::string path_holder;
+ struct stat st;
+ if (stat(lpath, &st) == 0) {
+ if (S_ISDIR(st.st_mode)) {
+ // If we're copying a remote file to a local directory,
+ // we really want to copy to local_dir + "/" + basename(remote).
+ path_holder = android::base::StringPrintf("%s/%s", lpath, adb_basename(rpath).c_str());
+ lpath = path_holder.c_str();
}
}
BEGIN();
if (sync_recv(fd, rpath, lpath, show_progress)) {
return 1;
} else {
- if (copy_attrs && set_time_and_mode(lpath, time, mode))
+ if (copy_attrs && set_time_and_mode(lpath, time, mode)) {
return 1;
- END();
- sync_quit(fd);
- return 0;
+ }
}
} else if(S_ISDIR(mode)) {
BEGIN();
if (copy_remote_dir_local(fd, rpath, lpath, copy_attrs)) {
return 1;
- } else {
- END();
- sync_quit(fd);
- return 0;
}
} else {
fprintf(stderr,"remote object '%s' not a file or directory\n", rpath);
return 1;
}
+ END();
+ sync_quit(fd);
+ return 0;
}
int do_sync_sync(const std::string& lpath, const std::string& rpath, bool list_only)
@@ -1012,9 +975,8 @@
BEGIN();
if (copy_local_dir_remote(fd, lpath.c_str(), rpath.c_str(), 1, list_only)) {
return 1;
- } else {
- END();
- sync_quit(fd);
- return 0;
}
+ END();
+ sync_quit(fd);
+ return 0;
}
diff --git a/adb/file_sync_service.cpp b/adb/file_sync_service.cpp
index 2067836..ea019f4 100644
--- a/adb/file_sync_service.cpp
+++ b/adb/file_sync_service.cpp
@@ -34,47 +34,46 @@
#include "adb_io.h"
#include "private/android_filesystem_config.h"
-static bool should_use_fs_config(const char* path) {
+#include <base/strings.h>
+
+static bool should_use_fs_config(const std::string& path) {
// TODO: use fs_config to configure permissions on /data.
- return strncmp("/system/", path, strlen("/system/")) == 0 ||
- strncmp("/vendor/", path, strlen("/vendor/")) == 0 ||
- strncmp("/oem/", path, strlen("/oem/")) == 0;
+ return android::base::StartsWith(path, "/system/") ||
+ android::base::StartsWith(path, "/vendor/") ||
+ android::base::StartsWith(path, "/oem/");
}
-static int mkdirs(char *name)
-{
- int ret;
- char *x = name + 1;
+static bool secure_mkdirs(const std::string& path) {
uid_t uid = -1;
gid_t gid = -1;
unsigned int mode = 0775;
uint64_t cap = 0;
- if(name[0] != '/') return -1;
+ if (path[0] != '/') return false;
- for(;;) {
- x = const_cast<char*>(adb_dirstart(x));
- if(x == 0) return 0;
- *x = 0;
- if (should_use_fs_config(name)) {
- fs_config(name, 1, &uid, &gid, &mode, &cap);
+ std::vector<std::string> path_components = android::base::Split(path, "/");
+ path_components.pop_back(); // For "/system/bin/sh", only create "/system/bin".
+
+ std::string partial_path;
+ for (auto& path_component : path_components) {
+ if (partial_path.back() != OS_PATH_SEPARATOR) partial_path += OS_PATH_SEPARATOR;
+ partial_path += path_component;
+
+ if (should_use_fs_config(partial_path)) {
+ fs_config(partial_path.c_str(), 1, &uid, &gid, &mode, &cap);
}
- ret = adb_mkdir(name, mode);
- if((ret < 0) && (errno != EEXIST)) {
- D("mkdir(\"%s\") -> %s\n", name, strerror(errno));
- *x = '/';
- return ret;
- } else if(ret == 0) {
- ret = chown(name, uid, gid);
- if (ret < 0) {
- *x = '/';
- return ret;
+ if (adb_mkdir(partial_path.c_str(), mode) == -1) {
+ if (errno != EEXIST) {
+ return false;
}
- selinux_android_restorecon(name, 0);
+ } else {
+ if (chown(partial_path.c_str(), uid, gid) == -1) {
+ return false;
+ }
+ selinux_android_restorecon(partial_path.c_str(), 0);
}
- *x++ = '/';
}
- return 0;
+ return true;
}
static int do_stat(int s, const char *path)
@@ -99,26 +98,24 @@
static int do_list(int s, const char *path)
{
- DIR *d;
struct dirent *de;
struct stat st;
- syncmsg msg;
- int len;
char tmp[1024 + 256 + 1];
char *fname;
- len = strlen(path);
+ size_t len = strlen(path);
memcpy(tmp, path, len);
tmp[len] = '/';
fname = tmp + len + 1;
+ syncmsg msg;
msg.dent.id = ID_DENT;
- d = opendir(path);
- if(d == 0) goto done;
+ std::unique_ptr<DIR, int(*)(DIR*)> d(opendir(path), closedir);
+ if (!d) goto done;
- while((de = readdir(d))) {
+ while ((de = readdir(d.get()))) {
int len = strlen(de->d_name);
/* not supposed to be possible, but
@@ -134,14 +131,11 @@
if(!WriteFdExactly(s, &msg.dent, sizeof(msg.dent)) ||
!WriteFdExactly(s, de->d_name, len)) {
- closedir(d);
return -1;
}
}
}
- closedir(d);
-
done:
msg.dent.id = ID_DONE;
msg.dent.mode = 0;
@@ -182,7 +176,7 @@
fd = adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, mode);
if(fd < 0 && errno == ENOENT) {
- if(mkdirs(path) != 0) {
+ if (!secure_mkdirs(path)) {
if(fail_errno(s))
return -1;
fd = -1;
@@ -294,7 +288,7 @@
ret = symlink(buffer, path);
if(ret && errno == ENOENT) {
- if(mkdirs(path) != 0) {
+ if (!secure_mkdirs(path)) {
fail_errno(s);
return -1;
}
diff --git a/adb/file_sync_service.h b/adb/file_sync_service.h
index 344eb98..1d3e3bd 100644
--- a/adb/file_sync_service.h
+++ b/adb/file_sync_service.h
@@ -68,9 +68,9 @@
void file_sync_service(int fd, void *cookie);
int do_sync_ls(const char *path);
-int do_sync_push(const char *lpath, const char *rpath, int show_progress);
+int do_sync_push(const char *lpath, const char *rpath, bool show_progress);
int do_sync_sync(const std::string& lpath, const std::string& rpath, bool list_only);
-int do_sync_pull(const char *rpath, const char *lpath, int show_progress, int pullTime);
+int do_sync_pull(const char *rpath, const char *lpath, bool show_progress, int pullTime);
#define SYNC_DATA_MAX (64*1024)
diff --git a/adb/services.cpp b/adb/services.cpp
index 708ef42..63a0a76 100644
--- a/adb/services.cpp
+++ b/adb/services.cpp
@@ -432,7 +432,8 @@
int port = atoi(name + 4);
name = strchr(name + 4, ':');
if(name == 0) {
- ret = socket_loopback_client(port, SOCK_STREAM);
+ std::string error;
+ ret = network_loopback_client(port, SOCK_STREAM, &error);
if (ret >= 0)
disable_tcp_nagle(ret);
} else {
diff --git a/adb/sysdeps.h b/adb/sysdeps.h
index 729bbcb..a57f650 100644
--- a/adb/sysdeps.h
+++ b/adb/sysdeps.h
@@ -26,6 +26,8 @@
#include <errno.h>
+#include <string>
+
/*
* 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
@@ -54,8 +56,11 @@
#include <windows.h>
#include <ws2tcpip.h>
+#include <string>
+
#include "fdevent.h"
+#define OS_PATH_SEPARATORS "\\/"
#define OS_PATH_SEPARATOR '\\'
#define OS_PATH_SEPARATOR_STR "\\"
#define ENV_PATH_SEPARATOR_STR ";"
@@ -120,9 +125,8 @@
#undef unlink
#define unlink ___xxx_unlink
-static __inline__ int adb_mkdir(const char* path, int mode)
-{
- return _mkdir(path);
+static __inline__ int adb_mkdir(const std::string& path, int mode) {
+ return _mkdir(path.c_str());
}
#undef mkdir
#define mkdir ___xxx_mkdir
@@ -210,6 +214,12 @@
Sleep( mseconds );
}
+int network_loopback_client(int port, int type, std::string* error);
+int network_loopback_server(int port, int type, std::string* error);
+int network_inaddr_any_server(int port, int type, std::string* error);
+int network_connect(const std::string& host, int port, int type, int timeout,
+ std::string* error);
+
extern int adb_socket_accept(int serverfd, struct sockaddr* addr, socklen_t *addrlen);
#undef accept
@@ -234,41 +244,18 @@
extern int adb_socketpair( int sv[2] );
-static __inline__ char* adb_dirstart( const char* path )
-{
- char* p = strchr(path, '/');
- char* p2 = strchr(path, '\\');
-
- if ( !p )
- p = p2;
- else if ( p2 && p2 > p )
- p = p2;
-
- return p;
-}
-
-static __inline__ const char* adb_dirstop( const char* path )
-{
- const char* p = strrchr(path, '/');
- const char* p2 = strrchr(path, '\\');
-
- if ( !p )
- p = p2;
- else if ( p2 && p2 > p )
- p = p2;
-
- return p;
-}
-
-static __inline__ int adb_is_absolute_host_path( const char* path )
-{
+static __inline__ int adb_is_absolute_host_path(const char* path) {
return isalpha(path[0]) && path[1] == ':' && path[2] == '\\';
}
+// Like strerror(), but for Win32 error codes.
+std::string SystemErrorCodeToString(DWORD error_code);
+
#else /* !_WIN32 a.k.a. Unix */
#include "fdevent.h"
#include <cutils/misc.h>
+#include <cutils/sockets.h>
#include <cutils/threads.h>
#include <signal.h>
#include <sys/wait.h>
@@ -279,11 +266,15 @@
#include <unistd.h>
#include <fcntl.h>
#include <stdarg.h>
+#include <netdb.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <string.h>
#include <unistd.h>
+#include <string>
+
+#define OS_PATH_SEPARATORS "/"
#define OS_PATH_SEPARATOR '/'
#define OS_PATH_SEPARATOR_STR "/"
#define ENV_PATH_SEPARATOR_STR ":"
@@ -426,6 +417,48 @@
#undef creat
#define creat ___xxx_creat
+// Helper for network_* functions.
+inline int _fd_set_error_str(int fd, std::string* error) {
+ if (fd == -1) {
+ *error = strerror(errno);
+ }
+ return fd;
+}
+
+inline int network_loopback_client(int port, int type, std::string* error) {
+ return _fd_set_error_str(socket_loopback_client(port, type), error);
+}
+
+inline int network_loopback_server(int port, int type, std::string* error) {
+ return _fd_set_error_str(socket_loopback_server(port, type), error);
+}
+
+inline int network_inaddr_any_server(int port, int type, std::string* error) {
+ return _fd_set_error_str(socket_inaddr_any_server(port, type), error);
+}
+
+inline int network_local_server(const char *name, int namespace_id, int type,
+ std::string* error) {
+ return _fd_set_error_str(socket_local_server(name, namespace_id, type),
+ error);
+}
+
+inline int network_connect(const std::string& host, int port, int type,
+ int timeout, std::string* error) {
+ int getaddrinfo_error = 0;
+ int fd = socket_network_client_timeout(host.c_str(), port, type, timeout,
+ &getaddrinfo_error);
+ if (fd != -1) {
+ return fd;
+ }
+ if (getaddrinfo_error != 0) {
+ *error = gai_strerror(getaddrinfo_error);
+ } else {
+ *error = strerror(errno);
+ }
+ return -1;
+}
+
static __inline__ int adb_socket_accept(int serverfd, struct sockaddr* addr, socklen_t *addrlen)
{
int fd;
@@ -510,10 +543,11 @@
usleep( mseconds*1000 );
}
-static __inline__ int adb_mkdir(const char* path, int mode)
+static __inline__ int adb_mkdir(const std::string& path, int mode)
{
- return mkdir(path, mode);
+ return mkdir(path.c_str(), mode);
}
+
#undef mkdir
#define mkdir ___xxx_mkdir
@@ -521,18 +555,7 @@
{
}
-static __inline__ const char* adb_dirstart(const char* path)
-{
- return strchr(path, '/');
-}
-
-static __inline__ const char* adb_dirstop(const char* path)
-{
- return strrchr(path, '/');
-}
-
-static __inline__ int adb_is_absolute_host_path( const char* path )
-{
+static __inline__ int adb_is_absolute_host_path(const char* path) {
return path[0] == '/';
}
diff --git a/adb/sysdeps_win32.cpp b/adb/sysdeps_win32.cpp
index a274892..9fdc24c 100644
--- a/adb/sysdeps_win32.cpp
+++ b/adb/sysdeps_win32.cpp
@@ -25,8 +25,15 @@
#include <stdio.h>
#include <stdlib.h>
+#include <memory>
+#include <string>
+
#include <cutils/sockets.h>
+#include <base/logging.h>
+#include <base/stringprintf.h>
+#include <base/strings.h>
+
#include "adb.h"
extern void fatal(const char *fmt, ...);
@@ -80,6 +87,29 @@
#define assert(cond) do { if (!(cond)) fatal( "assertion failed '%s' on %s:%ld\n", #cond, __FILE__, __LINE__ ); } while (0)
+std::string SystemErrorCodeToString(const DWORD error_code) {
+ const int kErrorMessageBufferSize = 256;
+ char msgbuf[kErrorMessageBufferSize];
+ DWORD flags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS;
+ DWORD len = FormatMessageA(flags, nullptr, error_code, 0, msgbuf,
+ arraysize(msgbuf), nullptr);
+ if (len == 0) {
+ return android::base::StringPrintf(
+ "Error (%lu) while retrieving error. (%lu)", GetLastError(),
+ error_code);
+ }
+
+ std::string msg(msgbuf);
+ // 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;
+}
+
/**************************************************************************/
/**************************************************************************/
/***** *****/
@@ -253,6 +283,23 @@
return 0;
}
+// Deleter for unique_fh.
+class fh_deleter {
+ public:
+ void operator()(struct FHRec_* fh) {
+ // We're called from a destructor and destructors should not overwrite
+ // errno because callers may do:
+ // errno = EBLAH;
+ // return -1; // calls destructor, which should not overwrite errno
+ const int saved_errno = errno;
+ _fh_close(fh);
+ errno = saved_errno;
+ }
+};
+
+// Like std::unique_ptr, but calls _fh_close() instead of operator delete().
+typedef std::unique_ptr<struct FHRec_, fh_deleter> unique_fh;
+
/**************************************************************************/
/**************************************************************************/
/***** *****/
@@ -467,21 +514,6 @@
}
-int adb_shutdown(int fd)
-{
- FH f = _fh_from_int(fd, __func__);
-
- if (!f || f->clazz != &_fh_socket_class) {
- D("adb_shutdown: invalid fd %d\n", fd);
- return -1;
- }
-
- D( "adb_shutdown: %s\n", f->name);
- shutdown( f->fh_socket, SD_BOTH );
- return 0;
-}
-
-
int adb_close(int fd)
{
FH f = _fh_from_int(fd, __func__);
@@ -505,29 +537,63 @@
#undef setsockopt
-static void _socket_set_errno( void ) {
- switch (WSAGetLastError()) {
+static void _socket_set_errno( const DWORD err ) {
+ // The Windows C Runtime (MSVCRT.DLL) strerror() does not support a lot of
+ // POSIX and socket error codes, so this can only meaningfully map so much.
+ switch ( err ) {
case 0: errno = 0; break;
case WSAEWOULDBLOCK: errno = EAGAIN; break;
case WSAEINTR: errno = EINTR; break;
+ case WSAEFAULT: errno = EFAULT; break;
+ case WSAEINVAL: errno = EINVAL; break;
+ case WSAEMFILE: errno = EMFILE; break;
default:
- D( "_socket_set_errno: unhandled value %d\n", WSAGetLastError() );
errno = EINVAL;
+ D( "_socket_set_errno: mapping Windows error code %lu to errno %d\n",
+ err, errno );
}
}
static void _fh_socket_init( FH f ) {
f->fh_socket = INVALID_SOCKET;
f->event = WSACreateEvent();
+ if (f->event == WSA_INVALID_EVENT) {
+ D("WSACreateEvent failed: %s\n",
+ SystemErrorCodeToString(WSAGetLastError()).c_str());
+
+ // _event_socket_start assumes that this field is INVALID_HANDLE_VALUE
+ // on failure, instead of NULL which is what Windows really returns on
+ // error. It might be better to change all the other code to look for
+ // NULL, but that is a much riskier change.
+ f->event = INVALID_HANDLE_VALUE;
+ }
f->mask = 0;
}
static int _fh_socket_close( FH f ) {
- /* gently tell any peer that we're closing the socket */
- shutdown( f->fh_socket, SD_BOTH );
- closesocket( f->fh_socket );
- f->fh_socket = INVALID_SOCKET;
- CloseHandle( f->event );
+ if (f->fh_socket != INVALID_SOCKET) {
+ /* gently tell any peer that we're closing the socket */
+ if (shutdown(f->fh_socket, SD_BOTH) == SOCKET_ERROR) {
+ // If the socket is not connected, this returns an error. We want to
+ // minimize logging spam, so don't log these errors for now.
+#if 0
+ D("socket shutdown failed: %s\n",
+ SystemErrorCodeToString(WSAGetLastError()).c_str());
+#endif
+ }
+ if (closesocket(f->fh_socket) == SOCKET_ERROR) {
+ D("closesocket failed: %s\n",
+ SystemErrorCodeToString(WSAGetLastError()).c_str());
+ }
+ f->fh_socket = INVALID_SOCKET;
+ }
+ if (f->event != NULL) {
+ if (!CloseHandle(f->event)) {
+ D("CloseHandle failed: %s\n",
+ SystemErrorCodeToString(GetLastError()).c_str());
+ }
+ f->event = NULL;
+ }
f->mask = 0;
return 0;
}
@@ -540,7 +606,10 @@
static int _fh_socket_read(FH f, void* buf, int len) {
int result = recv(f->fh_socket, reinterpret_cast<char*>(buf), len, 0);
if (result == SOCKET_ERROR) {
- _socket_set_errno();
+ const DWORD err = WSAGetLastError();
+ D("recv fd %d failed: %s\n", _fh_to_int(f),
+ SystemErrorCodeToString(err).c_str());
+ _socket_set_errno(err);
result = -1;
}
return result;
@@ -549,7 +618,10 @@
static int _fh_socket_write(FH f, const void* buf, int len) {
int result = send(f->fh_socket, reinterpret_cast<const char*>(buf), len, 0);
if (result == SOCKET_ERROR) {
- _socket_set_errno();
+ const DWORD err = WSAGetLastError();
+ D("send fd %d failed: %s\n", _fh_to_int(f),
+ SystemErrorCodeToString(err).c_str());
+ _socket_set_errno(err);
result = -1;
}
return result;
@@ -570,31 +642,39 @@
static void
_cleanup_winsock( void )
{
+ // TODO: WSAStartup() might be called multiple times and this won't properly
+ // cleanup the right number of times. Plus, WSACleanup() probably doesn't
+ // make sense since it might interrupt other threads using Winsock (since
+ // our various threads are not explicitly cleanly shutdown at process exit).
WSACleanup();
}
static void
_init_winsock( void )
{
+ // TODO: Multiple threads calling this may potentially cause multiple calls
+ // to WSAStartup() and multiple atexit() calls.
if (!_winsock_init) {
WSADATA wsaData;
int rc = WSAStartup( MAKEWORD(2,2), &wsaData);
if (rc != 0) {
- fatal( "adb: could not initialize Winsock\n" );
+ fatal( "adb: could not initialize Winsock: %s",
+ SystemErrorCodeToString( rc ).c_str());
}
atexit( _cleanup_winsock );
_winsock_init = 1;
}
}
-int socket_loopback_client(int port, int type)
-{
- FH f = _fh_alloc( &_fh_socket_class );
+int network_loopback_client(int port, int type, std::string* error) {
struct sockaddr_in addr;
SOCKET s;
- if (!f)
+ unique_fh f(_fh_alloc(&_fh_socket_class));
+ if (!f) {
+ *error = strerror(errno);
return -1;
+ }
if (!_winsock_init)
_init_winsock();
@@ -606,32 +686,40 @@
s = socket(AF_INET, type, 0);
if(s == INVALID_SOCKET) {
- D("socket_loopback_client: could not create socket\n" );
- _fh_close(f);
+ *error = SystemErrorCodeToString(WSAGetLastError());
+ D("could not create socket: %s\n", error->c_str());
+ return -1;
+ }
+ f->fh_socket = s;
+
+ if(connect(s, (struct sockaddr *) &addr, sizeof(addr)) == SOCKET_ERROR) {
+ *error = SystemErrorCodeToString(WSAGetLastError());
+ D("could not connect to %s:%d: %s\n",
+ type != SOCK_STREAM ? "udp" : "tcp", port, error->c_str());
return -1;
}
- f->fh_socket = s;
- if(connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
- D("socket_loopback_client: could not connect to %s:%d\n", type != SOCK_STREAM ? "udp" : "tcp", port );
- _fh_close(f);
- return -1;
- }
- snprintf( f->name, sizeof(f->name), "%d(lo-client:%s%d)", _fh_to_int(f), type != SOCK_STREAM ? "udp:" : "", port );
- D( "socket_loopback_client: port %d type %s => fd %d\n", port, type != SOCK_STREAM ? "udp" : "tcp", _fh_to_int(f) );
- return _fh_to_int(f);
+ const int fd = _fh_to_int(f.get());
+ snprintf( f->name, sizeof(f->name), "%d(lo-client:%s%d)", fd,
+ type != SOCK_STREAM ? "udp:" : "", port );
+ D( "port %d type %s => fd %d\n", port, type != SOCK_STREAM ? "udp" : "tcp",
+ fd );
+ f.release();
+ return fd;
}
#define LISTEN_BACKLOG 4
-int socket_loopback_server(int port, int type)
-{
- FH f = _fh_alloc( &_fh_socket_class );
+// interface_address is INADDR_LOOPBACK or INADDR_ANY.
+static int _network_server(int port, int type, u_long interface_address,
+ std::string* error) {
struct sockaddr_in addr;
SOCKET s;
int n;
+ unique_fh f(_fh_alloc(&_fh_socket_class));
if (!f) {
+ *error = strerror(errno);
return -1;
}
@@ -641,149 +729,151 @@
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
- addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ addr.sin_addr.s_addr = htonl(interface_address);
+ // TODO: Consider using dual-stack socket that can simultaneously listen on
+ // IPv4 and IPv6.
s = socket(AF_INET, type, 0);
- if(s == INVALID_SOCKET) return -1;
+ if (s == INVALID_SOCKET) {
+ *error = SystemErrorCodeToString(WSAGetLastError());
+ D("could not create socket: %s\n", error->c_str());
+ return -1;
+ }
f->fh_socket = s;
n = 1;
- setsockopt(s, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (const char*)&n, sizeof(n));
+ if (setsockopt(s, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (const char*)&n,
+ sizeof(n)) == SOCKET_ERROR) {
+ *error = SystemErrorCodeToString(WSAGetLastError());
+ D("setsockopt level %d optname %d failed: %s\n",
+ SOL_SOCKET, SO_EXCLUSIVEADDRUSE, error->c_str());
+ return -1;
+ }
- if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
- _fh_close(f);
+ if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) == SOCKET_ERROR) {
+ *error = SystemErrorCodeToString(WSAGetLastError());
+ D("could not bind to %s:%d: %s\n",
+ type != SOCK_STREAM ? "udp" : "tcp", port, error->c_str());
return -1;
}
if (type == SOCK_STREAM) {
- int ret;
-
- ret = listen(s, LISTEN_BACKLOG);
- if (ret < 0) {
- _fh_close(f);
+ if (listen(s, LISTEN_BACKLOG) == SOCKET_ERROR) {
+ *error = SystemErrorCodeToString(WSAGetLastError());
+ D("could not listen on %s:%d: %s\n",
+ type != SOCK_STREAM ? "udp" : "tcp", port, error->c_str());
return -1;
}
}
- snprintf( f->name, sizeof(f->name), "%d(lo-server:%s%d)", _fh_to_int(f), type != SOCK_STREAM ? "udp:" : "", port );
- D( "socket_loopback_server: port %d type %s => fd %d\n", port, type != SOCK_STREAM ? "udp" : "tcp", _fh_to_int(f) );
- return _fh_to_int(f);
+ const int fd = _fh_to_int(f.get());
+ snprintf( f->name, sizeof(f->name), "%d(%s-server:%s%d)", fd,
+ interface_address == INADDR_LOOPBACK ? "lo" : "any",
+ type != SOCK_STREAM ? "udp:" : "", port );
+ D( "port %d type %s => fd %d\n", port, type != SOCK_STREAM ? "udp" : "tcp",
+ fd );
+ f.release();
+ return fd;
}
+int network_loopback_server(int port, int type, std::string* error) {
+ return _network_server(port, type, INADDR_LOOPBACK, error);
+}
-int socket_network_client_timeout(const char *host, int port, int type, int timeout,
- int* getaddrinfo_error) {
- FH f = _fh_alloc( &_fh_socket_class );
- if (!f) return -1;
+int network_inaddr_any_server(int port, int type, std::string* error) {
+ return _network_server(port, type, INADDR_ANY, error);
+}
+
+int network_connect(const std::string& host, int port, int type, int timeout, std::string* error) {
+ unique_fh f(_fh_alloc(&_fh_socket_class));
+ if (!f) {
+ *error = strerror(errno);
+ return -1;
+ }
if (!_winsock_init) _init_winsock();
- hostent* hp = gethostbyname(host);
- if(hp == 0) {
- _fh_close(f);
+ struct addrinfo hints;
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = type;
+
+ char port_str[16];
+ snprintf(port_str, sizeof(port_str), "%d", port);
+
+ struct addrinfo* addrinfo_ptr = nullptr;
+ if (getaddrinfo(host.c_str(), port_str, &hints, &addrinfo_ptr) != 0) {
+ *error = SystemErrorCodeToString(WSAGetLastError());
+ D("could not resolve host '%s' and port %s: %s\n", host.c_str(),
+ port_str, error->c_str());
return -1;
}
+ std::unique_ptr<struct addrinfo, decltype(freeaddrinfo)*>
+ addrinfo(addrinfo_ptr, freeaddrinfo);
+ addrinfo_ptr = nullptr;
- sockaddr_in addr;
- memset(&addr, 0, sizeof(addr));
- addr.sin_family = hp->h_addrtype;
- addr.sin_port = htons(port);
- memcpy(&addr.sin_addr, hp->h_addr, hp->h_length);
-
- SOCKET s = socket(hp->h_addrtype, type, 0);
+ // TODO: Try all the addresses if there's more than one? This just uses
+ // the first. Or, could call WSAConnectByName() (Windows Vista and newer)
+ // which tries all addresses, takes a timeout and more.
+ SOCKET s = socket(addrinfo->ai_family, addrinfo->ai_socktype,
+ addrinfo->ai_protocol);
if(s == INVALID_SOCKET) {
- _fh_close(f);
+ *error = SystemErrorCodeToString(WSAGetLastError());
+ D("could not create socket: %s\n", error->c_str());
return -1;
}
f->fh_socket = s;
- // TODO: implement timeouts for Windows.
-
- if(connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
- _fh_close(f);
+ // TODO: Implement timeouts for Windows. Seems like the default in theory
+ // (according to http://serverfault.com/a/671453) and in practice is 21 sec.
+ if(connect(s, addrinfo->ai_addr, addrinfo->ai_addrlen) == SOCKET_ERROR) {
+ *error = SystemErrorCodeToString(WSAGetLastError());
+ D("could not connect to %s:%s:%s: %s\n",
+ type != SOCK_STREAM ? "udp" : "tcp", host.c_str(), port_str,
+ error->c_str());
return -1;
}
- snprintf( f->name, sizeof(f->name), "%d(net-client:%s%d)", _fh_to_int(f), type != SOCK_STREAM ? "udp:" : "", port );
- D( "socket_network_client_timeout: host '%s' port %d type %s => fd %d\n", host, port, type != SOCK_STREAM ? "udp" : "tcp", _fh_to_int(f) );
- return _fh_to_int(f);
-}
-
-
-int socket_inaddr_any_server(int port, int type)
-{
- FH f = _fh_alloc( &_fh_socket_class );
- struct sockaddr_in addr;
- SOCKET s;
- int n;
-
- if (!f)
- return -1;
-
- if (!_winsock_init)
- _init_winsock();
-
- memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_port = htons(port);
- addr.sin_addr.s_addr = htonl(INADDR_ANY);
-
- s = socket(AF_INET, type, 0);
- if(s == INVALID_SOCKET) {
- _fh_close(f);
- return -1;
- }
-
- f->fh_socket = s;
- n = 1;
- setsockopt(s, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (const char*)&n, sizeof(n));
-
- if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
- _fh_close(f);
- return -1;
- }
-
- if (type == SOCK_STREAM) {
- int ret;
-
- ret = listen(s, LISTEN_BACKLOG);
- if (ret < 0) {
- _fh_close(f);
- return -1;
- }
- }
- snprintf( f->name, sizeof(f->name), "%d(any-server:%s%d)", _fh_to_int(f), type != SOCK_STREAM ? "udp:" : "", port );
- D( "socket_inaddr_server: port %d type %s => fd %d\n", port, type != SOCK_STREAM ? "udp" : "tcp", _fh_to_int(f) );
- return _fh_to_int(f);
+ const int fd = _fh_to_int(f.get());
+ snprintf( f->name, sizeof(f->name), "%d(net-client:%s%d)", fd,
+ type != SOCK_STREAM ? "udp:" : "", port );
+ D( "host '%s' port %d type %s => fd %d\n", host.c_str(), port,
+ type != SOCK_STREAM ? "udp" : "tcp", fd );
+ f.release();
+ return fd;
}
#undef accept
int adb_socket_accept(int serverfd, struct sockaddr* addr, socklen_t *addrlen)
{
FH serverfh = _fh_from_int(serverfd, __func__);
- FH fh;
if ( !serverfh || serverfh->clazz != &_fh_socket_class ) {
- D( "adb_socket_accept: invalid fd %d\n", serverfd );
+ D("adb_socket_accept: invalid fd %d\n", serverfd);
+ errno = EBADF;
return -1;
}
- fh = _fh_alloc( &_fh_socket_class );
+ unique_fh fh(_fh_alloc( &_fh_socket_class ));
if (!fh) {
- D( "adb_socket_accept: not enough memory to allocate accepted socket descriptor\n" );
+ PLOG(ERROR) << "adb_socket_accept: failed to allocate accepted socket "
+ "descriptor";
return -1;
}
fh->fh_socket = accept( serverfh->fh_socket, addr, addrlen );
if (fh->fh_socket == INVALID_SOCKET) {
const DWORD err = WSAGetLastError();
- _fh_close( fh );
- D( "adb_socket_accept: accept on fd %d return error %ld\n", serverfd, err );
+ LOG(ERROR) << "adb_socket_accept: accept on fd " << serverfd <<
+ " failed: " + SystemErrorCodeToString(err);
+ _socket_set_errno( err );
return -1;
}
- snprintf( fh->name, sizeof(fh->name), "%d(accept:%s)", _fh_to_int(fh), serverfh->name );
- D( "adb_socket_accept on fd %d returns fd %d\n", serverfd, _fh_to_int(fh) );
- return _fh_to_int(fh);
+ const int fd = _fh_to_int(fh.get());
+ snprintf( fh->name, sizeof(fh->name), "%d(accept:%s)", fd, serverfh->name );
+ D( "adb_socket_accept on fd %d returns fd %d\n", serverfd, fd );
+ fh.release();
+ return fd;
}
@@ -793,10 +883,42 @@
if ( !fh || fh->clazz != &_fh_socket_class ) {
D("adb_setsockopt: invalid fd %d\n", fd);
+ errno = EBADF;
+ return -1;
+ }
+ int result = setsockopt( fh->fh_socket, level, optname,
+ reinterpret_cast<const char*>(optval), optlen );
+ if ( result == SOCKET_ERROR ) {
+ const DWORD err = WSAGetLastError();
+ D( "adb_setsockopt: setsockopt on fd %d level %d optname %d "
+ "failed: %s\n", fd, level, optname,
+ SystemErrorCodeToString(err).c_str() );
+ _socket_set_errno( err );
+ result = -1;
+ }
+ return result;
+}
+
+
+int adb_shutdown(int fd)
+{
+ FH f = _fh_from_int(fd, __func__);
+
+ if (!f || f->clazz != &_fh_socket_class) {
+ D("adb_shutdown: invalid fd %d\n", fd);
+ errno = EBADF;
return -1;
}
- return setsockopt( fh->fh_socket, level, optname, reinterpret_cast<const char*>(optval), optlen );
+ D( "adb_shutdown: %s\n", f->name);
+ if (shutdown(f->fh_socket, SD_BOTH) == SOCKET_ERROR) {
+ const DWORD err = WSAGetLastError();
+ D("socket shutdown fd %d failed: %s\n", fd,
+ SystemErrorCodeToString(err).c_str());
+ _socket_set_errno(err);
+ return -1;
+ }
+ return 0;
}
/**************************************************************************/
@@ -1199,16 +1321,19 @@
int adb_socketpair(int sv[2]) {
SocketPair pair;
- FH fa = _fh_alloc(&_fh_socketpair_class);
- FH fb = _fh_alloc(&_fh_socketpair_class);
-
- if (!fa || !fb)
- goto Fail;
+ unique_fh fa(_fh_alloc(&_fh_socketpair_class));
+ if (!fa) {
+ return -1;
+ }
+ unique_fh fb(_fh_alloc(&_fh_socketpair_class));
+ if (!fb) {
+ return -1;
+ }
pair = reinterpret_cast<SocketPair>(malloc(sizeof(*pair)));
if (pair == NULL) {
D("adb_socketpair: not enough memory to allocate pipes\n" );
- goto Fail;
+ return -1;
}
bip_buffer_init( &pair->a2b_bip );
@@ -1217,10 +1342,10 @@
fa->fh_pair = pair;
fb->fh_pair = pair;
pair->used = 2;
- pair->a_fd = fa;
+ pair->a_fd = fa.get();
- sv[0] = _fh_to_int(fa);
- sv[1] = _fh_to_int(fb);
+ sv[0] = _fh_to_int(fa.get());
+ sv[1] = _fh_to_int(fb.get());
pair->a2b_bip.fdin = sv[0];
pair->a2b_bip.fdout = sv[1];
@@ -1230,12 +1355,9 @@
snprintf( fa->name, sizeof(fa->name), "%d(pair:%d)", sv[0], sv[1] );
snprintf( fb->name, sizeof(fb->name), "%d(pair:%d)", sv[1], sv[0] );
D( "adb_socketpair: returns (%d, %d)\n", sv[0], sv[1] );
+ fa.release();
+ fb.release();
return 0;
-
-Fail:
- _fh_close(fb);
- _fh_close(fa);
- return -1;
}
/**************************************************************************/
@@ -2083,6 +2205,7 @@
hook->check = _event_socket_check;
hook->peek = _event_socket_peek;
+ // TODO: check return value?
_event_socket_start( hook );
}
diff --git a/adb/transport.cpp b/adb/transport.cpp
index 87aff88..4a273c4 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -126,19 +126,18 @@
static int
read_packet(int fd, const char* name, apacket** ppacket)
{
- char *p = (char*)ppacket; /* really read a packet address */
- int r;
- int len = sizeof(*ppacket);
- char buff[8];
+ char buff[8];
if (!name) {
snprintf(buff, sizeof buff, "fd=%d", fd);
name = buff;
}
+ char* p = reinterpret_cast<char*>(ppacket); /* really read a packet address */
+ int len = sizeof(apacket*);
while(len > 0) {
- r = adb_read(fd, p, len);
+ int r = adb_read(fd, p, len);
if(r > 0) {
len -= r;
- p += r;
+ p += r;
} else {
D("%s: read_packet (fd=%d), error ret=%d errno=%d: %s\n", name, fd, r, errno, strerror(errno));
if((r < 0) && (errno == EINTR)) continue;
@@ -155,20 +154,18 @@
static int
write_packet(int fd, const char* name, apacket** ppacket)
{
- char *p = (char*) ppacket; /* we really write the packet address */
- int r, len = sizeof(ppacket);
char buff[8];
if (!name) {
snprintf(buff, sizeof buff, "fd=%d", fd);
name = buff;
}
-
if (ADB_TRACING) {
dump_packet(name, "to remote", *ppacket);
}
- len = sizeof(ppacket);
+ char* p = reinterpret_cast<char*>(ppacket); /* we really write the packet address */
+ int len = sizeof(apacket*);
while(len > 0) {
- r = adb_write(fd, p, len);
+ int r = adb_write(fd, p, len);
if(r > 0) {
len -= r;
p += r;
diff --git a/adb/transport_local.cpp b/adb/transport_local.cpp
index 0dc9581..db9bedb 100644
--- a/adb/transport_local.cpp
+++ b/adb/transport_local.cpp
@@ -100,7 +100,7 @@
}
#endif
if (fd < 0) {
- fd = socket_loopback_client(adb_port, SOCK_STREAM);
+ fd = network_loopback_client(adb_port, SOCK_STREAM, error);
}
if (fd >= 0) {
@@ -144,9 +144,10 @@
serverfd = -1;
for(;;) {
if(serverfd == -1) {
- serverfd = socket_inaddr_any_server(port, SOCK_STREAM);
+ std::string error;
+ serverfd = network_inaddr_any_server(port, SOCK_STREAM, &error);
if(serverfd < 0) {
- D("server: cannot bind socket yet: %s\n", strerror(errno));
+ D("server: cannot bind socket yet: %s\n", error.c_str());
adb_sleep_ms(1000);
continue;
}
diff --git a/base/Android.mk b/base/Android.mk
index 7bd317b..4e135f6 100644
--- a/base/Android.mk
+++ b/base/Android.mk
@@ -21,6 +21,7 @@
logging.cpp \
stringprintf.cpp \
strings.cpp \
+ test_utils.cpp \
libbase_test_src_files := \
file_test.cpp \
@@ -28,7 +29,6 @@
stringprintf_test.cpp \
strings_test.cpp \
test_main.cpp \
- test_utils.cpp \
libbase_cppflags := \
-Wall \
diff --git a/base/file_test.cpp b/base/file_test.cpp
index b138094..4056684 100644
--- a/base/file_test.cpp
+++ b/base/file_test.cpp
@@ -24,7 +24,7 @@
#include <string>
-#include "test_utils.h"
+#include "base/test_utils.h"
TEST(file, ReadFileToString_ENOENT) {
std::string s("hello");
@@ -47,10 +47,10 @@
TEST(file, WriteStringToFile) {
TemporaryFile tf;
ASSERT_TRUE(tf.fd != -1);
- ASSERT_TRUE(android::base::WriteStringToFile("abc", tf.filename))
+ ASSERT_TRUE(android::base::WriteStringToFile("abc", tf.path))
<< strerror(errno);
std::string s;
- ASSERT_TRUE(android::base::ReadFileToString(tf.filename, &s))
+ ASSERT_TRUE(android::base::ReadFileToString(tf.path, &s))
<< strerror(errno);
EXPECT_EQ("abc", s);
}
@@ -61,16 +61,16 @@
TEST(file, WriteStringToFile2) {
TemporaryFile tf;
ASSERT_TRUE(tf.fd != -1);
- ASSERT_TRUE(android::base::WriteStringToFile("abc", tf.filename, 0660,
+ ASSERT_TRUE(android::base::WriteStringToFile("abc", tf.path, 0660,
getuid(), getgid()))
<< strerror(errno);
struct stat sb;
- ASSERT_EQ(0, stat(tf.filename, &sb));
+ ASSERT_EQ(0, stat(tf.path, &sb));
ASSERT_EQ(0660U, static_cast<unsigned int>(sb.st_mode & ~S_IFMT));
ASSERT_EQ(getuid(), sb.st_uid);
ASSERT_EQ(getgid(), sb.st_gid);
std::string s;
- ASSERT_TRUE(android::base::ReadFileToString(tf.filename, &s))
+ ASSERT_TRUE(android::base::ReadFileToString(tf.path, &s))
<< strerror(errno);
EXPECT_EQ("abc", s);
}
@@ -109,7 +109,7 @@
ASSERT_TRUE(tf.fd != -1);
ASSERT_TRUE(android::base::WriteFully(tf.fd, "abc", 3));
std::string s;
- ASSERT_TRUE(android::base::ReadFileToString(tf.filename, &s))
+ ASSERT_TRUE(android::base::ReadFileToString(tf.path, &s))
<< strerror(errno);
EXPECT_EQ("abc", s);
}
diff --git a/base/test_utils.h b/base/include/base/test_utils.h
similarity index 68%
rename from base/test_utils.h
rename to base/include/base/test_utils.h
index 132d3a7..83f0f1c 100644
--- a/base/test_utils.h
+++ b/base/include/base/test_utils.h
@@ -17,16 +17,37 @@
#ifndef TEST_UTILS_H
#define TEST_UTILS_H
+#include <string>
+
+#include <base/macros.h>
+
class TemporaryFile {
public:
TemporaryFile();
~TemporaryFile();
int fd;
- char filename[1024];
+ char path[1024];
private:
- void init(const char* tmp_dir);
+ void init(const std::string& tmp_dir);
+
+ DISALLOW_COPY_AND_ASSIGN(TemporaryFile);
};
+#if !defined(_WIN32)
+class TemporaryDir {
+ public:
+ TemporaryDir();
+ ~TemporaryDir();
+
+ char path[1024];
+
+ private:
+ bool init(const std::string& tmp_dir);
+
+ DISALLOW_COPY_AND_ASSIGN(TemporaryDir);
+};
+#endif
+
#endif // TEST_UTILS_H
diff --git a/base/logging_test.cpp b/base/logging_test.cpp
index c91857a..1a92c94 100644
--- a/base/logging_test.cpp
+++ b/base/logging_test.cpp
@@ -21,7 +21,7 @@
#include "base/file.h"
#include "base/stringprintf.h"
-#include "test_utils.h"
+#include "base/test_utils.h"
#include <gtest/gtest.h>
diff --git a/base/test_utils.cpp b/base/test_utils.cpp
index 0517bc7..dceb8b7 100644
--- a/base/test_utils.cpp
+++ b/base/test_utils.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "test_utils.h"
+#include "base/test_utils.h"
#include <fcntl.h>
#include <stdio.h>
@@ -26,34 +26,55 @@
#include <windows.h>
#endif
-TemporaryFile::TemporaryFile() {
+#include <string>
+
+static std::string GetSystemTempDir() {
#if defined(__ANDROID__)
- init("/data/local/tmp");
+ return "/data/local/tmp";
#elif defined(_WIN32)
char wd[MAX_PATH] = {};
_getcwd(wd, sizeof(wd));
- init(wd);
+ return wd;
#else
- init("/tmp");
+ return "/tmp";
#endif
}
+TemporaryFile::TemporaryFile() {
+ init(GetSystemTempDir());
+}
+
TemporaryFile::~TemporaryFile() {
close(fd);
- unlink(filename);
+ unlink(path);
}
-void TemporaryFile::init(const char* tmp_dir) {
- snprintf(filename, sizeof(filename), "%s/TemporaryFile-XXXXXX", tmp_dir);
+void TemporaryFile::init(const std::string& tmp_dir) {
+ snprintf(path, sizeof(path), "%s/TemporaryFile-XXXXXX", tmp_dir.c_str());
#if !defined(_WIN32)
- fd = mkstemp(filename);
+ fd = mkstemp(path);
#else
// Windows doesn't have mkstemp, and tmpfile creates the file in the root
// directory, requiring root (?!) permissions. We have to settle for mktemp.
- if (mktemp(filename) == nullptr) {
+ if (mktemp(path) == nullptr) {
abort();
}
- fd = open(filename, O_RDWR | O_NOINHERIT | O_CREAT, _S_IREAD | _S_IWRITE);
+ fd = open(path, O_RDWR | O_NOINHERIT | O_CREAT, _S_IREAD | _S_IWRITE);
#endif
}
+
+#if !defined(_WIN32)
+TemporaryDir::TemporaryDir() {
+ init(GetSystemTempDir());
+}
+
+TemporaryDir::~TemporaryDir() {
+ rmdir(path);
+}
+
+bool TemporaryDir::init(const std::string& tmp_dir) {
+ snprintf(path, sizeof(path), "%s/TemporaryDir-XXXXXX", tmp_dir.c_str());
+ return (mkdtemp(path) != nullptr);
+}
+#endif