diff options
Diffstat (limited to 'adb')
-rw-r--r-- | adb/commandline.cpp | 41 | ||||
-rw-r--r-- | adb/services.cpp | 57 |
2 files changed, 66 insertions, 32 deletions
diff --git a/adb/commandline.cpp b/adb/commandline.cpp index 8575c8636..bc58c9107 100644 --- a/adb/commandline.cpp +++ b/adb/commandline.cpp @@ -204,7 +204,10 @@ static void help() { " adb version - show version num\n" "\n" "scripting:\n" - " adb wait-for-device - block until device is online\n" + " adb wait-for[-<transport>]-<state>\n" + " - wait for device to be in the given state:\n" + " device, recovery, sideload, or bootloader\n" + " Transport is: usb, local or any [default=any]\n" " adb start-server - ensure that there is a server running\n" " adb kill-server - kill the server if it is running\n" " adb get-state - prints: offline | bootloader | device\n" @@ -1010,19 +1013,49 @@ static int ppp(int argc, const char** argv) { #endif /* !defined(_WIN32) */ } +static bool check_wait_for_device_syntax(const char* service) { + // TODO: when we have libc++ for Windows, use a regular expression instead. + // wait-for-((any|local|usb)-)?(bootloader|device|recovery|sideload) + + char type[20]; + char state[20]; + int length = 0; + if (sscanf(service, "wait-for-%20[a-z]-%20[a-z]%n", type, state, &length) < 2 || + length != static_cast<int>(strlen(service))) { + fprintf(stderr, "adb: couldn't parse 'wait-for' command: %s\n", service); + return false; + } + + if (strcmp(type, "any") != 0 && strcmp(type, "local") != 0 && strcmp(type, "usb") != 0) { + fprintf(stderr, "adb: unknown type %s; expected 'any', 'local', or 'usb'\n", type); + return false; + } + if (strcmp(state, "bootloader") != 0 && strcmp(state, "device") != 0 && + strcmp(state, "recovery") != 0 && strcmp(state, "sideload") != 0) { + fprintf(stderr, "adb: unknown state %s; " + "expected 'bootloader', 'device', 'recovery', or 'sideload'\n", state); + return false; + } + return true; +} + static bool wait_for_device(const char* service, TransportType t, const char* serial) { // Was the caller vague about what they'd like us to wait for? // If so, check they weren't more specific in their choice of transport type. if (strcmp(service, "wait-for-device") == 0) { if (t == kTransportUsb) { - service = "wait-for-usb"; + service = "wait-for-usb-device"; } else if (t == kTransportLocal) { - service = "wait-for-local"; + service = "wait-for-local-device"; } else { - service = "wait-for-any"; + service = "wait-for-any-device"; } } + if (!check_wait_for_device_syntax(service)) { + return false; + } + std::string cmd = format_host_command(service, t, serial); return adb_command(cmd); } diff --git a/adb/services.cpp b/adb/services.cpp index 523353a46..20166cef7 100644 --- a/adb/services.cpp +++ b/adb/services.cpp @@ -356,19 +356,19 @@ int service_to_fd(const char* name, const atransport* transport) { #if ADB_HOST struct state_info { TransportType transport_type; - char* serial; + std::string serial; ConnectionState state; }; -static void wait_for_state(int fd, void* cookie) { - state_info* sinfo = reinterpret_cast<state_info*>(cookie); +static void wait_for_state(int fd, void* data) { + std::unique_ptr<state_info> sinfo(reinterpret_cast<state_info*>(data)); D("wait_for_state %d", sinfo->state); while (true) { bool is_ambiguous = false; std::string error = "unknown error"; - atransport* t = acquire_one_transport(sinfo->transport_type, sinfo->serial, + atransport* t = acquire_one_transport(sinfo->transport_type, sinfo->serial.c_str(), &is_ambiguous, &error); if (t != nullptr && t->connection_state == sinfo->state) { SendOkay(fd); @@ -382,10 +382,6 @@ static void wait_for_state(int fd, void* cookie) { } } - if (sinfo->serial) { - free(sinfo->serial); - } - free(sinfo); adb_close(fd); D("wait_for_state is done"); } @@ -491,38 +487,43 @@ static void connect_service(int fd, void* data) { asocket* host_service_to_socket(const char* name, const char* serial) { if (!strcmp(name,"track-devices")) { return create_device_tracker(); - } else if (!strncmp(name, "wait-for-", strlen("wait-for-"))) { - auto sinfo = reinterpret_cast<state_info*>(malloc(sizeof(state_info))); + } else if (android::base::StartsWith(name, "wait-for-")) { + name += strlen("wait-for-"); + + std::unique_ptr<state_info> sinfo(new state_info); if (sinfo == nullptr) { fprintf(stderr, "couldn't allocate state_info: %s", strerror(errno)); - return NULL; + return nullptr; } - if (serial) - sinfo->serial = strdup(serial); - else - sinfo->serial = NULL; - - name += strlen("wait-for-"); + if (serial) sinfo->serial = serial; - if (!strncmp(name, "local", strlen("local"))) { + if (android::base::StartsWith(name, "local")) { + name += strlen("local"); sinfo->transport_type = kTransportLocal; - sinfo->state = kCsDevice; - } else if (!strncmp(name, "usb", strlen("usb"))) { + } else if (android::base::StartsWith(name, "usb")) { + name += strlen("usb"); sinfo->transport_type = kTransportUsb; - sinfo->state = kCsDevice; - } else if (!strncmp(name, "any", strlen("any"))) { + } else if (android::base::StartsWith(name, "any")) { + name += strlen("any"); sinfo->transport_type = kTransportAny; + } else { + return nullptr; + } + + if (!strcmp(name, "-device")) { sinfo->state = kCsDevice; + } else if (!strcmp(name, "-recovery")) { + sinfo->state = kCsRecovery; + } else if (!strcmp(name, "-sideload")) { + sinfo->state = kCsSideload; + } else if (!strcmp(name, "-bootloader")) { + sinfo->state = kCsBootloader; } else { - if (sinfo->serial) { - free(sinfo->serial); - } - free(sinfo); - return NULL; + return nullptr; } - int fd = create_service_thread(wait_for_state, sinfo); + int fd = create_service_thread(wait_for_state, sinfo.release()); return create_local_socket(fd); } else if (!strncmp(name, "connect:", 8)) { char* host = strdup(name + 8); |