More adb buffer fixes.

This patch factors out a lot of the basic protocol code: sending OKAY,
sending FAIL, and sending a length-prefixed string.

ADB_TRACE has been non-optional for a long time, so let's just remove
the #ifs.

Also actually build the device tracker test tool (and remove its duplicate).

Bug: http://b/20666660
Change-Id: I6c7d59f18707bdc62ca69dea45547617f9f31fc6
This commit is contained in:
Elliott Hughes 2015-04-30 17:32:03 -07:00
parent bacac0f7db
commit e67f1f87d9
22 changed files with 310 additions and 603 deletions

View file

@ -124,6 +124,21 @@ endif
include $(BUILD_HOST_NATIVE_TEST)
# adb device tracker (used by ddms) test tool
# =========================================================
ifeq ($(HOST_OS),linux)
include $(CLEAR_VARS)
LOCAL_CLANG := $(adb_host_clang)
LOCAL_MODULE := adb_device_tracker_test
LOCAL_CFLAGS := -DADB_HOST=1 $(LIBADB_CFLAGS)
LOCAL_SRC_FILES := test_track_devices.cpp
LOCAL_SHARED_LIBRARIES := liblog libbase
LOCAL_STATIC_LIBRARIES := libadb libcrypto_static libcutils
LOCAL_LDLIBS += -lrt -ldl -lpthread
include $(BUILD_HOST_EXECUTABLE)
endif
# adb host tool
# =========================================================
include $(CLEAR_VARS)

View file

@ -48,9 +48,7 @@
#include <sys/mount.h>
#endif
#if ADB_TRACE
ADB_MUTEX_DEFINE( D_lock );
#endif
int HOST = 0;
@ -322,28 +320,6 @@ static size_t fill_connect_data(char *buf, size_t bufsize)
#endif
}
#if !ADB_HOST
static void send_msg_with_header(int fd, const char* msg, size_t msglen) {
char header[5];
if (msglen > 0xffff)
msglen = 0xffff;
snprintf(header, sizeof(header), "%04x", (unsigned)msglen);
WriteFdExactly(fd, header, 4);
WriteFdExactly(fd, msg, msglen);
}
#endif
#if ADB_HOST
static void send_msg_with_okay(int fd, const char* msg, size_t msglen) {
char header[9];
if (msglen > 0xffff)
msglen = 0xffff;
snprintf(header, sizeof(header), "OKAY%04x", (unsigned)msglen);
WriteFdExactly(fd, header, 8);
WriteFdExactly(fd, msg, msglen);
}
#endif // ADB_HOST
void send_connect(atransport *t)
{
D("Calling send_connect \n");
@ -356,32 +332,6 @@ void send_connect(atransport *t)
send_packet(cp, t);
}
#if ADB_HOST
static const char* connection_state_name(atransport *t)
{
if (t == NULL) {
return "unknown";
}
switch(t->connection_state) {
case CS_BOOTLOADER:
return "bootloader";
case CS_DEVICE:
return "device";
case CS_RECOVERY:
return "recovery";
case CS_SIDELOAD:
return "sideload";
case CS_OFFLINE:
return "offline";
case CS_UNAUTHORIZED:
return "unauthorized";
default:
return "unknown";
}
}
#endif // ADB_HOST
// qual_overwrite is used to overwrite a qualifier string. dst is a
// pointer to a char pointer. It is assumed that if *dst is non-NULL, it
// was malloc'ed and needs to freed. *dst will be set to a dup of src.
@ -752,20 +702,11 @@ int handle_forward_request(const char* service, transport_type ttype, char* seri
{
if (!strcmp(service, "list-forward")) {
// Create the list of forward redirections.
int buffer_size = format_listeners(NULL, 0);
// Add one byte for the trailing zero.
char* buffer = reinterpret_cast<char*>(malloc(buffer_size + 1));
if (buffer == nullptr) {
sendfailmsg(reply_fd, "not enough memory");
return 1;
}
(void) format_listeners(buffer, buffer_size + 1);
std::string listeners = format_listeners();
#if ADB_HOST
send_msg_with_okay(reply_fd, buffer, buffer_size);
#else
send_msg_with_header(reply_fd, buffer, buffer_size);
SendOkay(reply_fd);
#endif
free(buffer);
SendProtocolString(reply_fd, listeners);
return 1;
}
@ -773,9 +714,9 @@ int handle_forward_request(const char* service, transport_type ttype, char* seri
remove_all_listeners();
#if ADB_HOST
/* On the host: 1st OKAY is connect, 2nd OKAY is status */
adb_write(reply_fd, "OKAY", 4);
SendOkay(reply_fd);
#endif
adb_write(reply_fd, "OKAY", 4);
SendOkay(reply_fd);
return 1;
}
@ -800,19 +741,19 @@ int handle_forward_request(const char* service, transport_type ttype, char* seri
if (createForward) {
// Check forward: parameter format: '<local>;<remote>'
if(remote == 0) {
sendfailmsg(reply_fd, "malformed forward spec");
SendFail(reply_fd, "malformed forward spec");
return 1;
}
*remote++ = 0;
if((local[0] == 0) || (remote[0] == 0) || (remote[0] == '*')) {
sendfailmsg(reply_fd, "malformed forward spec");
SendFail(reply_fd, "malformed forward spec");
return 1;
}
} else {
// Check killforward: parameter format: '<local>'
if (local[0] == 0) {
sendfailmsg(reply_fd, "malformed forward spec");
SendFail(reply_fd, "malformed forward spec");
return 1;
}
}
@ -820,7 +761,7 @@ int handle_forward_request(const char* service, transport_type ttype, char* seri
std::string error_msg;
transport = acquire_one_transport(CS_ANY, ttype, serial, &error_msg);
if (!transport) {
sendfailmsg(reply_fd, error_msg.c_str());
SendFail(reply_fd, error_msg);
return 1;
}
@ -833,9 +774,9 @@ int handle_forward_request(const char* service, transport_type ttype, char* seri
if (r == INSTALL_STATUS_OK) {
#if ADB_HOST
/* On the host: 1st OKAY is connect, 2nd OKAY is status */
WriteFdExactly(reply_fd, "OKAY", 4);
SendOkay(reply_fd);
#endif
WriteFdExactly(reply_fd, "OKAY", 4);
SendOkay(reply_fd);
return 1;
}
@ -851,7 +792,7 @@ int handle_forward_request(const char* service, transport_type ttype, char* seri
break;
case INSTALL_STATUS_LISTENER_NOT_FOUND: message = "listener not found"; break;
}
sendfailmsg(reply_fd, message.c_str());
SendFail(reply_fd, message);
return 1;
}
return 0;
@ -862,7 +803,7 @@ int handle_host_request(char *service, transport_type ttype, char* serial, int r
if(!strcmp(service, "kill")) {
fprintf(stderr,"adb server killed by remote request\n");
fflush(stdout);
adb_write(reply_fd, "OKAY", 4);
SendOkay(reply_fd);
usb_cleanup();
exit(0);
}
@ -892,25 +833,25 @@ int handle_host_request(char *service, transport_type ttype, char* serial, int r
if (transport) {
s->transport = transport;
adb_write(reply_fd, "OKAY", 4);
SendOkay(reply_fd);
} else {
sendfailmsg(reply_fd, error_msg.c_str());
SendFail(reply_fd, error_msg);
}
return 1;
}
// return a list of all connected devices
if (!strncmp(service, "devices", 7)) {
char buffer[4096];
int use_long = !strcmp(service+7, "-l");
if (use_long || service[7] == 0) {
memset(buffer, 0, sizeof(buffer));
D("Getting device list \n");
list_transports(buffer, sizeof(buffer), use_long);
D("Wrote device list \n");
send_msg_with_okay(reply_fd, buffer, strlen(buffer));
bool long_listing = (strcmp(service+7, "-l") == 0);
if (long_listing || service[7] == 0) {
D("Getting device list...\n");
std::string device_list = list_transports(long_listing);
D("Sending device list...\n");
SendOkay(reply_fd);
SendProtocolString(reply_fd, device_list);
return 0;
}
return 1;
}
// remove TCP transport
@ -937,15 +878,15 @@ int handle_host_request(char *service, transport_type ttype, char* serial, int r
}
}
send_msg_with_okay(reply_fd, buffer, strlen(buffer));
SendOkay(reply_fd);
SendProtocolString(reply_fd, buffer);
return 0;
}
// returns our value for ADB_SERVER_VERSION
if (!strcmp(service, "version")) {
char version[12];
snprintf(version, sizeof version, "%04x", ADB_SERVER_VERSION);
send_msg_with_okay(reply_fd, version, strlen(version));
SendOkay(reply_fd);
SendProtocolString(reply_fd, android::base::StringPrintf("%04x", ADB_SERVER_VERSION));
return 0;
}
@ -955,7 +896,8 @@ int handle_host_request(char *service, transport_type ttype, char* serial, int r
if (transport && transport->serial) {
out = transport->serial;
}
send_msg_with_okay(reply_fd, out, strlen(out));
SendOkay(reply_fd);
SendProtocolString(reply_fd, out);
return 0;
}
if(!strncmp(service,"get-devpath",strlen("get-devpath"))) {
@ -964,7 +906,8 @@ int handle_host_request(char *service, transport_type ttype, char* serial, int r
if (transport && transport->devpath) {
out = transport->devpath;
}
send_msg_with_okay(reply_fd, out, strlen(out));
SendOkay(reply_fd);
SendProtocolString(reply_fd, out);
return 0;
}
// indicates a new emulator instance has started
@ -977,8 +920,8 @@ int handle_host_request(char *service, transport_type ttype, char* serial, int r
if(!strncmp(service,"get-state",strlen("get-state"))) {
transport = acquire_one_transport(CS_ANY, ttype, serial, NULL);
const char *state = connection_state_name(transport);
send_msg_with_okay(reply_fd, state, strlen(state));
SendOkay(reply_fd);
SendProtocolString(reply_fd, transport->connection_state_name());
return 0;
}
#endif // ADB_HOST

View file

@ -209,6 +209,8 @@ struct atransport
unsigned char token[TOKEN_SIZE];
fdevent auth_fde;
unsigned failed_auth_attempts;
const char* connection_state_name() const;
};
@ -369,7 +371,6 @@ enum subproc_mode {
#define USB_FFS_ADB_IN USB_FFS_ADB_EP(ep2)
#endif
int sendfailmsg(int fd, const char *reason);
int handle_host_request(char *service, transport_type ttype, char* serial, int reply_fd, asocket *s);
void handle_online(atransport *t);

View file

@ -56,7 +56,7 @@ static bool ReadProtocolString(int fd, std::string* s, std::string* error) {
buf[4] = 0;
unsigned long len = strtoul(buf, 0, 16);
s->resize(len + 1, '\0'); // Ensure NUL-termination.
s->resize(len, '\0');
if (!ReadFdExactly(fd, &(*s)[0], len)) {
*error = perror_str("protocol fault (couldn't read status message)");
return false;
@ -136,9 +136,7 @@ static int switch_socket_transport(int fd, std::string* error) {
service += transport_type;
}
char tmp[5];
snprintf(tmp, sizeof(tmp), "%04zx", service.size());
if (!WriteFdExactly(fd, tmp, 4) || !WriteFdExactly(fd, service.c_str(), service.size())) {
if (!SendProtocolString(fd, service)) {
*error = perror_str("write failure during connection");
adb_close(fd);
return -1;
@ -199,9 +197,7 @@ int _adb_connect(const std::string& service, std::string* error) {
return -1;
}
char tmp[5];
snprintf(tmp, sizeof(tmp), "%04zx", service.size());
if(!WriteFdExactly(fd, tmp, 4) || !WriteFdExactly(fd, &service[0], service.size())) {
if(!SendProtocolString(fd, service)) {
*error = perror_str("write failure during connection");
adb_close(fd);
return -1;

View file

@ -22,14 +22,31 @@
#include <unistd.h>
#include "adb_trace.h"
#include "transport.h"
#include "adb_utils.h"
bool SendProtocolString(int fd, const std::string& s) {
int length = s.size();
if (length > 0xffff) {
length = 0xffff;
}
char buf[5];
snprintf(buf, sizeof(buf), "%04x", length);
return WriteFdExactly(fd, buf, 4) && WriteFdExactly(fd, s);
}
bool SendOkay(int fd) {
return WriteFdExactly(fd, "OKAY", 4);
}
bool SendFail(int fd, const std::string& reason) {
return WriteFdExactly(fd, "FAIL", 4) && SendProtocolString(fd, reason);
}
bool ReadFdExactly(int fd, void* buf, size_t len) {
char* p = reinterpret_cast<char*>(buf);
#if ADB_TRACE
size_t len0 = len;
#endif
D("readx: fd=%d wanted=%zu\n", fd, len);
while (len > 0) {
@ -47,12 +64,10 @@ bool ReadFdExactly(int fd, void* buf, size_t len) {
}
}
#if ADB_TRACE
D("readx: fd=%d wanted=%zu got=%zu\n", fd, len0, len0 - len);
if (ADB_TRACING) {
dump_hex(reinterpret_cast<const unsigned char*>(buf), len0);
}
#endif
return true;
}
@ -61,12 +76,10 @@ bool WriteFdExactly(int fd, const void* buf, size_t len) {
const char* p = reinterpret_cast<const char*>(buf);
int r;
#if ADB_TRACE
D("writex: fd=%d len=%d: ", fd, (int)len);
if (ADB_TRACING) {
dump_hex(reinterpret_cast<const unsigned char*>(buf), len);
}
#endif
while (len > 0) {
r = adb_write(fd, p, len);
@ -90,6 +103,14 @@ bool WriteFdExactly(int fd, const void* buf, size_t len) {
return true;
}
bool WriteFdExactly(int fd, const char* str) {
return WriteFdExactly(fd, str, strlen(str));
}
bool WriteFdExactly(int fd, const std::string& str) {
return WriteFdExactly(fd, str.c_str(), str.size());
}
bool WriteStringFully(int fd, const char* str) {
return WriteFdExactly(fd, str, strlen(str));
}

View file

@ -17,9 +17,19 @@
#ifndef ADB_IO_H
#define ADB_IO_H
#include <stdbool.h>
#include <sys/types.h>
#include <string>
// Sends the protocol "OKAY" message.
bool SendOkay(int fd);
// Sends the protocol "FAIL" message, with the given failure reason.
bool SendFail(int fd, const std::string& reason);
// Writes a protocol-format string; a four hex digit length followed by the string data.
bool SendProtocolString(int fd, const std::string& s);
/*
* Reads exactly len bytes from fd into buf.
*
@ -37,9 +47,13 @@ bool ReadFdExactly(int fd, void *buf, size_t len);
* completed. If the other end of the fd (such as in a socket, pipe, or fifo),
* is closed, errno will be set to 0.
*/
bool WriteFdExactly(int fd, const void *buf, size_t len);
bool WriteFdExactly(int fd, const void* buf, size_t len);
/* Same as WriteFdExactly, but with an implicit len = strlen(buf). */
/* Same as above, but with an implicit len = strlen(buf). */
bool WriteFdExactly(int fd, const char* s);
bool WriteFdExactly(int fd, const std::string& s);
// TODO: move minadb off this and remove it.
bool WriteStringFully(int fd, const char* str);
#endif /* ADB_IO_H */

View file

@ -139,13 +139,13 @@ TEST(io, WriteFdExactly_ENOSPC) {
ASSERT_EQ(ENOSPC, errno);
}
TEST(io, WriteStringFully) {
TEST(io, WriteFdExactly_string) {
const char str[] = "Foobar";
TemporaryFile tf;
ASSERT_NE(-1, tf.fd);
// Test writing a partial string to the file.
ASSERT_TRUE(WriteStringFully(tf.fd, str)) << strerror(errno);
ASSERT_TRUE(WriteFdExactly(tf.fd, str)) << strerror(errno);
ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0));
std::string s;

View file

@ -19,6 +19,8 @@
#include <stdio.h>
#include <stdlib.h>
#include <base/stringprintf.h>
#include "sysdeps.h"
#include "transport.h"
@ -143,49 +145,17 @@ int local_name_to_fd(const char *name)
return -1;
}
// Write a single line describing a listener to a user-provided buffer.
// Appends a trailing zero, even in case of truncation, but the function
// returns the full line length.
// If |buffer| is NULL, does not write but returns required size.
static int format_listener(alistener* l, char* buffer, size_t buffer_len) {
// Format is simply:
//
// <device-serial> " " <local-name> " " <remote-name> "\n"
//
int local_len = strlen(l->local_name);
int connect_len = strlen(l->connect_to);
int serial_len = strlen(l->transport->serial);
if (buffer != NULL) {
snprintf(buffer, buffer_len, "%s %s %s\n",
l->transport->serial, l->local_name, l->connect_to);
}
// NOTE: snprintf() on Windows returns -1 in case of truncation, so
// return the computed line length instead.
return local_len + connect_len + serial_len + 3;
}
// Write the list of current listeners (network redirections) into a
// user-provided buffer. Appends a trailing zero, even in case of
// trunctaion, but return the full size in bytes.
// If |buffer| is NULL, does not write but returns required size.
int format_listeners(char* buf, size_t buflen)
{
alistener* l;
int result = 0;
for (l = listener_list.next; l != &listener_list; l = l->next) {
// Write the list of current listeners (network redirections) into a string.
std::string format_listeners() {
std::string result;
for (alistener* l = listener_list.next; l != &listener_list; l = l->next) {
// Ignore special listeners like those for *smartsocket*
if (l->connect_to[0] == '*')
continue;
int len = format_listener(l, buf, buflen);
// Ensure there is space for the trailing zero.
result += len;
if (buf != NULL) {
buf += len;
buflen -= len;
if (buflen <= 0)
break;
if (l->connect_to[0] == '*') {
continue;
}
// <device-serial> " " <local-name> " " <remote-name> "\n"
android::base::StringAppendF(&result, "%s %s %s\n",
l->transport->serial, l->local_name, l->connect_to);
}
return result;
}

View file

@ -19,6 +19,8 @@
#include "adb.h"
#include <string>
// error/status codes for install_listener.
enum install_status_t {
INSTALL_STATUS_OK = 0,
@ -39,7 +41,7 @@ install_status_t install_listener(const char *local_name,
atransport* transport,
int no_rebind);
int format_listeners(char* buf, size_t buflen);
std::string format_listeners();
install_status_t remove_listener(const char* local_name, atransport* transport);
void remove_all_listeners(void);

View file

@ -23,9 +23,6 @@
#include <stdio.h>
#endif
/* define ADB_TRACE to 1 to enable tracing support, or 0 to disable it */
#define ADB_TRACE 1
/* IMPORTANT: if you change the following list, don't
* forget to update the corresponding 'tags' table in
* the adb_trace_init() function implemented in adb.c
@ -45,8 +42,6 @@ enum AdbTrace {
TRACE_FDEVENT,
} ;
#if ADB_TRACE
#if !ADB_HOST
/*
* When running inside the emulator, guest's adbd can connect to 'adb-debug'
@ -97,19 +92,6 @@ void adb_trace_init(void);
errno = save_errno; \
} \
} while (0)
# define DD(...) \
do { \
int save_errno = errno; \
adb_mutex_lock(&D_lock); \
fprintf(stderr, "%16s: %5d:%5lu | ", \
__FUNCTION__, \
getpid(), adb_thread_id()); \
errno = save_errno; \
fprintf(stderr, __VA_ARGS__ ); \
fflush(stderr); \
adb_mutex_unlock(&D_lock); \
errno = save_errno; \
} while (0)
#else
# define D(...) \
do { \
@ -129,19 +111,6 @@ void adb_trace_init(void);
__VA_ARGS__ ); \
} \
} while (0)
# define DD(...) \
do { \
__android_log_print( \
ANDROID_LOG_INFO, \
__FUNCTION__, \
__VA_ARGS__ ); \
} while (0)
#endif /* ADB_HOST */
#else
# define D(...) ((void)0)
# define DR(...) ((void)0)
# define DD(...) ((void)0)
# define ADB_TRACING 0
#endif /* ADB_TRACE */
#endif /* __ADB_TRACE_H */

View file

@ -14,6 +14,8 @@
* limitations under the License.
*/
#define TRACE_TAG TRACE_ADB
#include "adb_utils.h"
#include <stdlib.h>
@ -21,6 +23,11 @@
#include <sys/types.h>
#include <unistd.h>
#include <algorithm>
#include <base/stringprintf.h>
#include "adb_trace.h"
#include "sysdeps.h"
bool getcwd(std::string* s) {
@ -50,3 +57,25 @@ std::string escape_arg(const std::string& s) {
result.push_back('\'');
return result;
}
void dump_hex(const void* data, size_t byte_count) {
byte_count = std::min(byte_count, size_t(16));
const uint8_t* p = reinterpret_cast<const uint8_t*>(data);
std::string line;
for (size_t i = 0; i < byte_count; ++i) {
android::base::StringAppendF(&line, "%02x", p[i]);
}
line.push_back(' ');
for (size_t i = 0; i < byte_count; ++i) {
int c = p[i];
if (c < 32 || c > 127) {
c = '.';
}
line.push_back(c);
}
DR("%s\n", line.c_str());
}

View file

@ -24,4 +24,6 @@ bool directory_exists(const std::string& path);
std::string escape_arg(const std::string& s);
void dump_hex(const void* ptr, size_t byte_count);
#endif

View file

@ -490,17 +490,8 @@ static int adb_download_buffer(const char *service, const char *fn, const void*
printf("\n");
}
// TODO: should this be adb_status?
char buf[5];
if(!ReadFdExactly(fd, buf, 4)){
fprintf(stderr,"* error reading response *\n");
adb_close(fd);
return -1;
}
if(memcmp(buf, "OKAY", 4)) {
buf[4] = 0;
fprintf(stderr,"* error response '%s' *\n", buf);
adb_close(fd);
if (!adb_status(fd, &error)) {
fprintf(stderr,"* error response '%s' *\n", error.c_str());
return -1;
}

View file

@ -92,7 +92,7 @@ static bool remount_partition(int fd, const char* partition, int* ro) {
if (remount(partition, ro)) {
char buf[200];
snprintf(buf, sizeof(buf), "remount of %s failed: %s\n", partition, strerror(errno));
WriteStringFully(fd, buf);
WriteFdExactly(fd, buf);
return false;
}
return true;
@ -102,7 +102,7 @@ void remount_service(int fd, void* cookie) {
char prop_buf[PROPERTY_VALUE_MAX];
if (getuid() != 0) {
WriteStringFully(fd, "Not running as root. Try \"adb root\" first.\n");
WriteFdExactly(fd, "Not running as root. Try \"adb root\" first.\n");
adb_close(fd);
return;
}
@ -128,12 +128,11 @@ void remount_service(int fd, void* cookie) {
both ? " and " : "",
vendor_verified ? "vendor" : "",
both ? "s" : "");
WriteStringFully(fd, buffer);
snprintf(buffer, sizeof(buffer),
"Use \"adb disable-verity\" to disable verity.\n"
"If you do not, remount may succeed, however, you will still "
"not be able to write to these volumes.\n");
WriteStringFully(fd, buffer);
WriteFdExactly(fd, buffer);
WriteFdExactly(fd,
"Use \"adb disable-verity\" to disable verity.\n"
"If you do not, remount may succeed, however, you will still "
"not be able to write to these volumes.\n");
}
bool success = true;
@ -141,7 +140,7 @@ void remount_service(int fd, void* cookie) {
success &= remount_partition(fd, "/vendor", &vendor_ro);
success &= remount_partition(fd, "/oem", &oem_ro);
WriteStringFully(fd, success ? "remount succeeded\n" : "remount failed\n");
WriteFdExactly(fd, success ? "remount succeeded\n" : "remount failed\n");
adb_close(fd);
}

View file

@ -31,10 +31,11 @@
#include <unistd.h>
#endif
#include <base/file.h>
#include <base/stringprintf.h>
#include <base/strings.h>
#if !ADB_HOST
#include "base/file.h"
#include "cutils/android_reboot.h"
#include "cutils/properties.h"
#endif
@ -147,8 +148,7 @@ static bool reboot_service_impl(int fd, const char* arg) {
// in the command file.
if (strcmp(reboot_arg, "sideload") == 0) {
if (getuid() != 0) {
snprintf(buf, sizeof(buf), "'adb root' is required for 'adb reboot sideload'.\n");
WriteStringFully(fd, buf);
WriteFdExactly(fd, "'adb root' is required for 'adb reboot sideload'.\n");
return false;
}
@ -175,14 +175,14 @@ static bool reboot_service_impl(int fd, const char* arg) {
int ret = snprintf(property_val, sizeof(property_val), "reboot,%s", reboot_arg);
if (ret >= static_cast<int>(sizeof(property_val))) {
snprintf(buf, sizeof(buf), "reboot string too long. length=%d\n", ret);
WriteStringFully(fd, buf);
WriteFdExactly(fd, buf);
return false;
}
ret = property_set(ANDROID_RB_PROPERTY, property_val);
if (ret < 0) {
snprintf(buf, sizeof(buf), "reboot failed: %d\n", ret);
WriteStringFully(fd, buf);
WriteFdExactly(fd, buf);
return false;
}
@ -208,7 +208,7 @@ void reverse_service(int fd, void* arg)
const char* command = reinterpret_cast<const char*>(arg);
if (handle_forward_request(command, kTransportAny, NULL, fd) < 0) {
sendfailmsg(fd, "not a reverse forwarding command");
SendFail(fd, "not a reverse forwarding command");
}
free(arg);
adb_close(fd);
@ -551,9 +551,9 @@ static void wait_for_state(int fd, void* cookie)
std::string error_msg = "unknown error";
atransport* t = acquire_one_transport(sinfo->state, sinfo->transport, sinfo->serial, &error_msg);
if (t != 0) {
WriteFdExactly(fd, "OKAY", 4);
SendOkay(fd);
} else {
sendfailmsg(fd, error_msg.c_str());
SendFail(fd, error_msg);
}
if (sinfo->serial)
@ -563,35 +563,31 @@ static void wait_for_state(int fd, void* cookie)
D("wait_for_state is done\n");
}
static void connect_device(char* host, char* buffer, int buffer_size)
{
int port, fd;
char* portstr = strchr(host, ':');
char hostbuf[100];
char serial[100];
int ret;
strncpy(hostbuf, host, sizeof(hostbuf) - 1);
if (portstr) {
if (portstr - host >= (ptrdiff_t)sizeof(hostbuf)) {
snprintf(buffer, buffer_size, "bad host name %s", host);
return;
}
// zero terminate the host at the point we found the colon
hostbuf[portstr - host] = 0;
if (sscanf(portstr + 1, "%d", &port) != 1) {
snprintf(buffer, buffer_size, "bad port number %s", portstr);
return;
}
} else {
port = DEFAULT_ADB_LOCAL_TRANSPORT_PORT;
static void connect_device(const std::string& host, std::string* response) {
if (host.empty()) {
*response = "empty host name";
return;
}
snprintf(serial, sizeof(serial), "%s:%d", hostbuf, port);
std::vector<std::string> pieces = android::base::Split(host, ":");
const std::string& hostname = pieces[0];
fd = socket_network_client_timeout(hostbuf, port, SOCK_STREAM, 10);
int port = DEFAULT_ADB_LOCAL_TRANSPORT_PORT;
if (pieces.size() > 1) {
if (sscanf(pieces[1].c_str(), "%d", &port) != 1) {
*response = android::base::StringPrintf("bad port number %s", pieces[1].c_str());
return;
}
}
// This may look like we're putting 'host' back together,
// but we're actually inserting the default port if necessary.
std::string serial = android::base::StringPrintf("%s:%d", hostname.c_str(), port);
int fd = socket_network_client_timeout(hostname.c_str(), port, SOCK_STREAM, 10);
if (fd < 0) {
snprintf(buffer, buffer_size, "unable to connect to %s:%d", host, port);
*response = android::base::StringPrintf("unable to connect to %s:%d",
hostname.c_str(), port);
return;
}
@ -599,85 +595,74 @@ static void connect_device(char* host, char* buffer, int buffer_size)
close_on_exec(fd);
disable_tcp_nagle(fd);
ret = register_socket_transport(fd, serial, port, 0);
int ret = register_socket_transport(fd, serial.c_str(), port, 0);
if (ret < 0) {
adb_close(fd);
snprintf(buffer, buffer_size, "already connected to %s", serial);
*response = android::base::StringPrintf("already connected to %s", serial.c_str());
} else {
snprintf(buffer, buffer_size, "connected to %s", serial);
*response = android::base::StringPrintf("connected to %s", serial.c_str());
}
}
void connect_emulator(char* port_spec, char* buffer, int buffer_size)
{
char* port_separator = strchr(port_spec, ',');
if (!port_separator) {
snprintf(buffer, buffer_size,
"unable to parse '%s' as <console port>,<adb port>",
port_spec);
void connect_emulator(const std::string& port_spec, std::string* response) {
std::vector<std::string> pieces = android::base::Split(port_spec, ",");
if (pieces.size() != 2) {
*response = android::base::StringPrintf("unable to parse '%s' as <console port>,<adb port>",
port_spec.c_str());
return;
}
// Zero-terminate console port and make port_separator point to 2nd port.
*port_separator++ = 0;
int console_port = strtol(port_spec, NULL, 0);
int adb_port = strtol(port_separator, NULL, 0);
if (!(console_port > 0 && adb_port > 0)) {
*(port_separator - 1) = ',';
snprintf(buffer, buffer_size,
"Invalid port numbers: Expected positive numbers, got '%s'",
port_spec);
int console_port = strtol(pieces[0].c_str(), NULL, 0);
int adb_port = strtol(pieces[1].c_str(), NULL, 0);
if (console_port <= 0 || adb_port <= 0) {
*response = android::base::StringPrintf("Invalid port numbers: %s", port_spec.c_str());
return;
}
/* Check if the emulator is already known.
* Note: There's a small but harmless race condition here: An emulator not
* present just yet could be registered by another invocation right
* after doing this check here. However, local_connect protects
* against double-registration too. From here, a better error message
* can be produced. In the case of the race condition, the very specific
* error message won't be shown, but the data doesn't get corrupted. */
// Check if the emulator is already known.
// Note: There's a small but harmless race condition here: An emulator not
// present just yet could be registered by another invocation right
// after doing this check here. However, local_connect protects
// against double-registration too. From here, a better error message
// can be produced. In the case of the race condition, the very specific
// error message won't be shown, but the data doesn't get corrupted.
atransport* known_emulator = find_emulator_transport_by_adb_port(adb_port);
if (known_emulator != NULL) {
snprintf(buffer, buffer_size,
"Emulator on port %d already registered.", adb_port);
if (known_emulator != nullptr) {
*response = android::base::StringPrintf("Emulator already registered on port %d", adb_port);
return;
}
/* Check if more emulators can be registered. Similar unproblematic
* race condition as above. */
// Check if more emulators can be registered. Similar unproblematic
// race condition as above.
int candidate_slot = get_available_local_transport_index();
if (candidate_slot < 0) {
snprintf(buffer, buffer_size, "Cannot accept more emulators.");
*response = "Cannot accept more emulators";
return;
}
/* Preconditions met, try to connect to the emulator. */
// Preconditions met, try to connect to the emulator.
if (!local_connect_arbitrary_ports(console_port, adb_port)) {
snprintf(buffer, buffer_size,
"Connected to emulator on ports %d,%d", console_port, adb_port);
*response = android::base::StringPrintf("Connected to emulator on ports %d,%d",
console_port, adb_port);
} else {
snprintf(buffer, buffer_size,
"Could not connect to emulator on ports %d,%d",
console_port, adb_port);
*response = android::base::StringPrintf("Could not connect to emulator on ports %d,%d",
console_port, adb_port);
}
}
static void connect_service(int fd, void* cookie)
{
char buf[4096];
char resp[4096];
char *host = reinterpret_cast<char*>(cookie);
std::string response;
if (!strncmp(host, "emu:", 4)) {
connect_emulator(host + 4, buf, sizeof(buf));
connect_emulator(host + 4, &response);
} else {
connect_device(host, buf, sizeof(buf));
connect_device(host, &response);
}
// Send response for emulator and device
snprintf(resp, sizeof(resp), "%04x%s",(unsigned)strlen(buf), buf);
WriteFdExactly(fd, resp, strlen(resp));
SendProtocolString(fd, response);
adb_close(fd);
}
#endif

View file

@ -21,7 +21,6 @@
#include <fcntl.h>
#include <inttypes.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <sys/stat.h>

View file

@ -37,23 +37,6 @@ ADB_MUTEX_DEFINE( socket_list_lock );
static void local_socket_close_locked(asocket *s);
int sendfailmsg(int fd, const char *reason)
{
char buf[9];
int len;
len = strlen(reason);
if (len > 0xffff) {
len = 0xffff;
}
snprintf(buf, sizeof buf, "FAIL%04x", len);
if (!WriteFdExactly(fd, buf, 8)) {
return -1;
}
return WriteFdExactly(fd, reason, len) ? 0 : -1;
}
static unsigned local_socket_next_id = 1;
static asocket local_socket_list = {
@ -608,7 +591,7 @@ static void local_socket_ready_notify(asocket *s)
s->ready = local_socket_ready;
s->shutdown = NULL;
s->close = local_socket_close;
adb_write(s->fd, "OKAY", 4);
SendOkay(s->fd);
s->ready(s);
}
@ -620,11 +603,11 @@ static void local_socket_close_notify(asocket *s)
s->ready = local_socket_ready;
s->shutdown = NULL;
s->close = local_socket_close;
sendfailmsg(s->fd, "closed");
SendFail(s->fd, "closed");
s->close(s);
}
unsigned unhex(unsigned char *s, int len)
static unsigned unhex(unsigned char *s, int len)
{
unsigned n = 0, c;
@ -654,6 +637,8 @@ unsigned unhex(unsigned char *s, int len)
return n;
}
#if ADB_HOST
#define PREFIX(str) { str, sizeof(str) - 1 }
static const struct prefix_struct {
const char *str;
@ -670,7 +655,7 @@ static const int num_prefixes = (sizeof(prefixes) / sizeof(prefixes[0]));
skipping over the 'serial' parameter in the ADB protocol,
where parameter string may be a host:port string containing
the protocol delimiter (colon). */
char *skip_host_serial(char *service) {
static char *skip_host_serial(char *service) {
char *first_colon, *serial_end;
int i;
@ -698,6 +683,8 @@ char *skip_host_serial(char *service) {
return serial_end;
}
#endif // ADB_HOST
static int smart_socket_enqueue(asocket *s, apacket *p)
{
unsigned len;
@ -799,7 +786,7 @@ static int smart_socket_enqueue(asocket *s, apacket *p)
s2 = create_host_service_socket(service, serial);
if(s2 == 0) {
D( "SS(%d): couldn't create host service '%s'\n", s->id, service );
sendfailmsg(s->peer->fd, "unknown host service");
SendFail(s->peer->fd, "unknown host service");
goto fail;
}
@ -810,7 +797,7 @@ static int smart_socket_enqueue(asocket *s, apacket *p)
** connection, and close this smart socket now
** that its work is done.
*/
adb_write(s->peer->fd, "OKAY", 4);
SendOkay(s->peer->fd);
s->peer->ready = local_socket_ready;
s->peer->shutdown = NULL;
@ -831,7 +818,7 @@ static int smart_socket_enqueue(asocket *s, apacket *p)
s->transport = acquire_one_transport(CS_ANY, kTransportAny, NULL, &error_msg);
if (s->transport == NULL) {
sendfailmsg(s->peer->fd, error_msg.c_str());
SendFail(s->peer->fd, error_msg);
goto fail;
}
}
@ -841,7 +828,7 @@ static int smart_socket_enqueue(asocket *s, apacket *p)
/* if there's no remote we fail the connection
** right here and terminate it
*/
sendfailmsg(s->peer->fd, "device offline (x)");
SendFail(s->peer->fd, "device offline (x)");
goto fail;
}

View file

@ -22,7 +22,6 @@
#include <windows.h>
#include <errno.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>

View file

@ -1,3 +1,5 @@
// TODO: replace this with a shell/python script.
/* a simple test program, connects to ADB server, and opens a track-devices session */
#include <netdb.h>
#include <sys/socket.h>
@ -6,6 +8,8 @@
#include <errno.h>
#include <memory.h>
#include <base/file.h>
static void
panic( const char* msg )
{
@ -13,82 +17,49 @@ panic( const char* msg )
exit(1);
}
static int
unix_write( int fd, const char* buf, int len )
{
int result = 0;
while (len > 0) {
int len2 = write(fd, buf, len);
if (len2 < 0) {
if (errno == EINTR || errno == EAGAIN)
continue;
return -1;
}
result += len2;
len -= len2;
buf += len2;
int main(int argc, char* argv[]) {
const char* request = "host:track-devices";
if (argv[1] && strcmp(argv[1], "--jdwp") == 0) {
request = "track-jdwp";
}
return result;
}
static int
unix_read( int fd, char* buf, int len )
{
int result = 0;
while (len > 0) {
int len2 = read(fd, buf, len);
if (len2 < 0) {
if (errno == EINTR || errno == EAGAIN)
continue;
return -1;
}
result += len2;
len -= len2;
buf += len2;
}
return result;
}
int main( void )
{
int ret, s;
int ret;
struct sockaddr_in server;
char buffer[1024];
const char* request = "host:track-devices";
int len;
memset( &server, 0, sizeof(server) );
server.sin_family = AF_INET;
server.sin_port = htons(5037);
server.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
s = socket( PF_INET, SOCK_STREAM, 0 );
int s = socket( PF_INET, SOCK_STREAM, 0 );
ret = connect( s, (struct sockaddr*) &server, sizeof(server) );
if (ret < 0) panic( "could not connect to server" );
/* send the request */
len = snprintf( buffer, sizeof buffer, "%04x%s", strlen(request), request );
if (unix_write(s, buffer, len) < 0)
int len = snprintf(buffer, sizeof(buffer), "%04zx%s", strlen(request), request);
if (!android::base::WriteFully(s, buffer, len))
panic( "could not send request" );
/* read the OKAY answer */
if (unix_read(s, buffer, 4) != 4)
if (!android::base::ReadFully(s, buffer, 4))
panic( "could not read request" );
printf( "server answer: %.*s\n", 4, buffer );
/* now loop */
for (;;) {
while (true) {
char head[5] = "0000";
if (unix_read(s, head, 4) < 0)
if (!android::base::ReadFully(s, head, 4))
panic("could not read length");
if ( sscanf( head, "%04x", &len ) != 1 )
int len;
if (sscanf(head, "%04x", &len) != 1 )
panic("could not decode length");
if (unix_read(s, buffer, len) != len)
if (!android::base::ReadFully(s, buffer, len))
panic("could not read data");
printf( "received header %.*s (%d bytes):\n%.*s", 4, head, len, len, buffer );

View file

@ -1,97 +0,0 @@
/* a simple test program, connects to ADB server, and opens a track-devices session */
#include <netdb.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <memory.h>
static void
panic( const char* msg )
{
fprintf(stderr, "PANIC: %s: %s\n", msg, strerror(errno));
exit(1);
}
static int
unix_write( int fd, const char* buf, int len )
{
int result = 0;
while (len > 0) {
int len2 = write(fd, buf, len);
if (len2 < 0) {
if (errno == EINTR || errno == EAGAIN)
continue;
return -1;
}
result += len2;
len -= len2;
buf += len2;
}
return result;
}
static int
unix_read( int fd, char* buf, int len )
{
int result = 0;
while (len > 0) {
int len2 = read(fd, buf, len);
if (len2 < 0) {
if (errno == EINTR || errno == EAGAIN)
continue;
return -1;
}
result += len2;
len -= len2;
buf += len2;
}
return result;
}
int main( void )
{
int ret, s;
struct sockaddr_in server;
char buffer[1024];
const char* request = "track-jdwp";
int len;
memset( &server, 0, sizeof(server) );
server.sin_family = AF_INET;
server.sin_port = htons(5037);
server.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
s = socket( PF_INET, SOCK_STREAM, 0 );
ret = connect( s, (struct sockaddr*) &server, sizeof(server) );
if (ret < 0) panic( "could not connect to server" );
/* send the request */
len = snprintf( buffer, sizeof buffer, "%04x%s", strlen(request), request );
if (unix_write(s, buffer, len) < 0)
panic( "could not send request" );
/* read the OKAY answer */
if (unix_read(s, buffer, 4) != 4)
panic( "could not read request" );
printf( "server answer: %.*s\n", 4, buffer );
/* now loop */
for (;;) {
char head[5] = "0000";
if (unix_read(s, head, 4) < 0)
panic("could not read length");
if ( sscanf( head, "%04x", &len ) != 1 )
panic("could not decode length");
if (unix_read(s, buffer, len) != len)
panic("could not read data");
printf( "received header %.*s (%d bytes):\n%.*s", 4, head, len, len, buffer );
}
close(s);
}

View file

@ -26,7 +26,10 @@
#include <string.h>
#include <unistd.h>
#include <base/stringprintf.h>
#include "adb.h"
#include "adb_utils.h"
static void transport_unref(atransport *t);
@ -42,34 +45,6 @@ static atransport pending_list = {
ADB_MUTEX_DEFINE( transport_lock );
#if ADB_TRACE
#define MAX_DUMP_HEX_LEN 16
void dump_hex(const unsigned char* ptr, size_t len)
{
int nn, len2 = len;
// Build a string instead of logging each character.
// MAX chars in 2 digit hex, one space, MAX chars, one '\0'.
char buffer[MAX_DUMP_HEX_LEN *2 + 1 + MAX_DUMP_HEX_LEN + 1 ], *pb = buffer;
if (len2 > MAX_DUMP_HEX_LEN) len2 = MAX_DUMP_HEX_LEN;
for (nn = 0; nn < len2; nn++) {
sprintf(pb, "%02x", ptr[nn]);
pb += 2;
}
sprintf(pb++, " ");
for (nn = 0; nn < len2; nn++) {
int c = ptr[nn];
if (c < 32 || c > 127)
c = '.';
*pb++ = c;
}
*pb++ = '\0';
DR("%s\n", buffer);
}
#endif
void kick_transport(atransport* t)
{
if (t && !t->kicked)
@ -117,10 +92,7 @@ void run_transport_disconnects(atransport* t)
}
}
#if ADB_TRACE
static void
dump_packet(const char* name, const char* func, apacket* p)
{
static void dump_packet(const char* name, const char* func, apacket* p) {
unsigned command = p->msg.command;
int len = p->msg.data_length;
char cmd[9];
@ -155,7 +127,6 @@ dump_packet(const char* name, const char* func, apacket* p)
name, func, cmd, arg0, arg1, len);
dump_hex(p->data, len);
}
#endif /* ADB_TRACE */
static int
read_packet(int fd, const char* name, apacket** ppacket)
@ -180,11 +151,9 @@ read_packet(int fd, const char* name, apacket** ppacket)
}
}
#if ADB_TRACE
if (ADB_TRACING) {
dump_packet(name, "from remote", *ppacket);
}
#endif
return 0;
}
@ -199,11 +168,9 @@ write_packet(int fd, const char* name, apacket** ppacket)
name = buff;
}
#if ADB_TRACE
if (ADB_TRACING) {
dump_packet(name, "to remote", *ppacket);
}
#endif
len = sizeof(ppacket);
while(len > 0) {
r = adb_write(fd, p, len);
@ -389,17 +356,6 @@ static fdevent transport_registration_fde;
#if ADB_HOST
static int list_transports_msg(char* buffer, size_t bufferlen)
{
char head[5];
int len;
len = list_transports(buffer+4, bufferlen-4, 0);
snprintf(head, sizeof(head), "%04x", len);
memcpy(buffer, head, 4);
len += 4;
return len;
}
/* this adds support required by the 'track-devices' service.
* this is used to send the content of "list_transport" to any
@ -457,39 +413,29 @@ device_tracker_enqueue( asocket* socket, apacket* p )
return -1;
}
static int
device_tracker_send( device_tracker* tracker,
const char* buffer,
int len )
{
apacket* p = get_apacket();
asocket* peer = tracker->socket.peer;
static int device_tracker_send(device_tracker* tracker, const std::string& string) {
apacket* p = get_apacket();
asocket* peer = tracker->socket.peer;
memcpy(p->data, buffer, len);
p->len = len;
return peer->enqueue( peer, p );
snprintf(reinterpret_cast<char*>(p->data), 5, "%04x", static_cast<int>(string.size()));
memcpy(&p->data[4], string.data(), string.size());
p->len = 4 + string.size();
return peer->enqueue(peer, p);
}
static void device_tracker_ready(asocket* socket) {
device_tracker* tracker = reinterpret_cast<device_tracker*>(socket);
static void
device_tracker_ready( asocket* socket )
{
device_tracker* tracker = (device_tracker*) socket;
/* we want to send the device list when the tracker connects
* for the first time, even if no update occured */
// We want to send the device list when the tracker connects
// for the first time, even if no update occurred.
if (tracker->update_needed > 0) {
char buffer[1024];
int len;
tracker->update_needed = 0;
len = list_transports_msg(buffer, sizeof(buffer));
device_tracker_send(tracker, buffer, len);
std::string transports = list_transports(false);
device_tracker_send(tracker, transports);
}
}
asocket*
create_device_tracker(void)
{
@ -510,27 +456,25 @@ create_device_tracker(void)
}
/* call this function each time the transport list has changed */
void update_transports(void) {
char buffer[1024];
int len;
device_tracker* tracker;
// Call this function each time the transport list has changed.
void update_transports() {
std::string transports = list_transports(false);
len = list_transports_msg(buffer, sizeof(buffer));
tracker = device_tracker_list;
while (tracker != NULL) {
device_tracker* next = tracker->next;
/* note: this may destroy the tracker if the connection is closed */
device_tracker_send(tracker, buffer, len);
device_tracker* tracker = device_tracker_list;
while (tracker != nullptr) {
device_tracker* next = tracker->next;
// This may destroy the tracker if the connection is closed.
device_tracker_send(tracker, transports);
tracker = next;
}
}
#else
void update_transports(void)
{
// nothing to do on the device side
void update_transports() {
// Nothing to do on the device side.
}
#endif // ADB_HOST
struct tmsg
@ -895,100 +839,71 @@ retry:
return result;
}
#if ADB_HOST
static const char *statename(atransport *t)
{
switch(t->connection_state){
const char* atransport::connection_state_name() const {
switch (connection_state) {
case CS_OFFLINE: return "offline";
case CS_BOOTLOADER: return "bootloader";
case CS_DEVICE: return "device";
case CS_HOST: return "host";
case CS_RECOVERY: return "recovery";
case CS_SIDELOAD: return "sideload";
case CS_NOPERM: return "no permissions";
case CS_SIDELOAD: return "sideload";
case CS_UNAUTHORIZED: return "unauthorized";
default: return "unknown";
}
}
static void add_qual(char **buf, size_t *buf_size,
const char *prefix, const char *qual, bool sanitize_qual)
{
if (!buf || !*buf || !buf_size || !*buf_size || !qual || !*qual)
#if ADB_HOST
static void append_transport_info(std::string* result, const char* key, const char* value, bool sanitize) {
if (value == nullptr || *value == '\0') {
return;
int prefix_len;
size_t len = snprintf(*buf, *buf_size, "%s%n%s", prefix, &prefix_len, qual);
if (sanitize_qual) {
for (char* cp = *buf + prefix_len; cp < *buf + len; cp++) {
if (!isalnum(*cp))
*cp = '_';
}
}
*buf_size -= len;
*buf += len;
*result += ' ';
*result += key;
for (const char* p = value; *p; ++p) {
result->push_back((!sanitize || isalnum(*p)) ? *p : '_');
}
}
static size_t format_transport(atransport *t, char *buf, size_t bufsize,
int long_listing)
{
static void append_transport(atransport* t, std::string* result, bool long_listing) {
const char* serial = t->serial;
if (!serial || !serial[0])
if (!serial || !serial[0]) {
serial = "????????????";
}
if (!long_listing) {
return snprintf(buf, bufsize, "%s\t%s\n", serial, statename(t));
*result += serial;
*result += '\t';
*result += t->connection_state_name();
} else {
size_t len, remaining = bufsize;
android::base::StringAppendF(result, "%-22s %s", serial, t->connection_state_name());
len = snprintf(buf, remaining, "%-22s %s", serial, statename(t));
remaining -= len;
buf += len;
add_qual(&buf, &remaining, " ", t->devpath, false);
add_qual(&buf, &remaining, " product:", t->product, false);
add_qual(&buf, &remaining, " model:", t->model, true);
add_qual(&buf, &remaining, " device:", t->device, false);
len = snprintf(buf, remaining, "\n");
remaining -= len;
return bufsize - remaining;
append_transport_info(result, "", t->devpath, false);
append_transport_info(result, "product:", t->product, false);
append_transport_info(result, "model:", t->model, true);
append_transport_info(result, "device:", t->device, false);
}
*result += '\n';
}
int list_transports(char *buf, size_t bufsize, int long_listing)
{
char* p = buf;
char* end = buf + bufsize;
int len;
atransport *t;
/* XXX OVERRUN PROBLEMS XXX */
std::string list_transports(bool long_listing) {
std::string result;
adb_mutex_lock(&transport_lock);
for(t = transport_list.next; t != &transport_list; t = t->next) {
len = format_transport(t, p, end - p, long_listing);
if (p + len >= end) {
/* discard last line if buffer is too short */
break;
}
p += len;
for (atransport* t = transport_list.next; t != &transport_list; t = t->next) {
append_transport(t, &result, long_listing);
}
p[0] = 0;
adb_mutex_unlock(&transport_lock);
return p - buf;
return result;
}
/* hack for osx */
void close_usb_devices()
{
atransport *t;
adb_mutex_lock(&transport_lock);
for(t = transport_list.next; t != &transport_list; t = t->next) {
for (atransport* t = transport_list.next; t != &transport_list; t = t->next) {
if ( !t->kicked ) {
t->kicked = 1;
t->kick(t);

View file

@ -23,10 +23,6 @@
#include "adb.h"
#if ADB_TRACE
void dump_hex(const unsigned char* ptr, size_t len);
#endif
/*
* Obtain a transport from the available transports.
* If state is != CS_ANY, only transports in that state are considered.
@ -45,7 +41,7 @@ void update_transports(void);
** get_device_transport does an acquire on your behalf before returning
*/
void init_transport_registration(void);
int list_transports(char* buf, size_t bufsize, int long_listing);
std::string list_transports(bool long_listing);
atransport* find_transport(const char* serial);
void register_usb_transport(usb_handle* h, const char* serial,