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; msg.req.id = ID_LIST; msg.req.namelen = htoll(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; len = ltohl(msg.dent.namelen); if (len > 256) 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); } fail: adb_close(fd); return -1; }
int adb_status(int fd) { unsigned char buf[5]; unsigned len; if(!ReadFdExactly(fd, buf, 4)) { strcpy(__adb_error, "protocol fault (no status)"); return -1; } if(!memcmp(buf, "OKAY", 4)) { return 0; } if(memcmp(buf, "FAIL", 4)) { sprintf(__adb_error, "protocol fault (status %02x %02x %02x %02x?!)", buf[0], buf[1], buf[2], buf[3]); return -1; } if(!ReadFdExactly(fd, buf, 4)) { strcpy(__adb_error, "protocol fault (status len)"); return -1; } buf[4] = 0; len = strtoul((char*)buf, 0, 16); if(len > 255) len = 255; if(!ReadFdExactly(fd, __adb_error, len)) { strcpy(__adb_error, "protocol fault (status read)"); return -1; } __adb_error[len] = 0; return -1; }
static int remote_read(apacket *p, atransport *t) { if(!ReadFdExactly(t->sfd, &p->msg, sizeof(amessage))){ D("remote local: read terminated (message)\n"); return -1; } fix_endians(p); #if 0 && defined __BIG_ENDIAN__ D("read remote packet: %04x arg0=%0x arg1=%0x data_length=%0x data_check=%0x magic=%0x\n", p->msg.command, p->msg.arg0, p->msg.arg1, p->msg.data_length, p->msg.data_check, p->msg.magic); #endif if(check_header(p, t)) { D("bad header: terminated (data)\n"); return -1; } if(!ReadFdExactly(t->sfd, p->data, p->msg.data_length)){ D("remote local: terminated (data)\n"); return -1; } if(check_data(p)) { D("bad data: terminated (data)\n"); return -1; } return 0; }
TEST(sysdeps_socketpair, smoke) { int fds[2]; ASSERT_EQ(0, adb_socketpair(fds)) << strerror(errno); ASSERT_TRUE(WriteFdExactly(fds[0], "foo", 4)); ASSERT_TRUE(WriteFdExactly(fds[1], "bar", 4)); char buf[4]; ASSERT_TRUE(ReadFdExactly(fds[1], buf, 4)); ASSERT_STREQ(buf, "foo"); ASSERT_TRUE(ReadFdExactly(fds[0], buf, 4)); ASSERT_STREQ(buf, "bar"); ASSERT_EQ(0, adb_close(fds[0])); ASSERT_EQ(0, adb_close(fds[1])); }
// This test checks if we can read packets from a closing local socket. // The socket's file handler may be non readable if the other side has // called shutdown(SHUT_WR). But we should always write packets // successfully to the other side. TEST_F(LocalSocketTest, half_close_with_packet) { int socket_fd[2]; ASSERT_EQ(0, adb_socketpair(socket_fd)); int cause_close_fd[2]; ASSERT_EQ(0, adb_socketpair(cause_close_fd)); CloseWithPacketArg arg; arg.socket_fd = socket_fd[1]; arg.cause_close_fd = cause_close_fd[1]; pthread_t thread; ASSERT_EQ(0, pthread_create(&thread, nullptr, reinterpret_cast<void* (*)(void*)>(CloseWithPacketThreadFunc), &arg)); // Wait until the fdevent_loop() starts. sleep(1); ASSERT_EQ(0, adb_close(cause_close_fd[0])); sleep(1); ASSERT_EQ(2u, fdevent_installed_count()); ASSERT_EQ(0, shutdown(socket_fd[0], SHUT_WR)); // Verify if we can read successfully. std::vector<char> buf(arg.bytes_written); ASSERT_EQ(true, ReadFdExactly(socket_fd[0], buf.data(), buf.size())); ASSERT_EQ(0, adb_close(socket_fd[0])); // Wait until the socket is closed. sleep(1); ASSERT_EQ(0, pthread_kill(thread, SIGUSR1)); ASSERT_EQ(0, pthread_join(thread, nullptr)); }
// This test checks if we can read packets from a closing local socket. TEST_F(LocalSocketTest, read_from_closing_socket) { int socket_fd[2]; ASSERT_EQ(0, adb_socketpair(socket_fd)); int cause_close_fd[2]; ASSERT_EQ(0, adb_socketpair(cause_close_fd)); CloseWithPacketArg arg; arg.socket_fd = socket_fd[1]; arg.cause_close_fd = cause_close_fd[1]; PrepareThread(); adb_thread_t thread; ASSERT_TRUE(adb_thread_create(reinterpret_cast<void (*)(void*)>(CloseWithPacketThreadFunc), &arg, &thread)); // Wait until the fdevent_loop() starts. adb_sleep_ms(SLEEP_FOR_FDEVENT_IN_MS); ASSERT_EQ(0, adb_close(cause_close_fd[0])); adb_sleep_ms(SLEEP_FOR_FDEVENT_IN_MS); EXPECT_EQ(1u + GetAdditionalLocalSocketCount(), fdevent_installed_count()); // Verify if we can read successfully. std::vector<char> buf(arg.bytes_written); ASSERT_NE(0u, arg.bytes_written); ASSERT_EQ(true, ReadFdExactly(socket_fd[0], buf.data(), buf.size())); ASSERT_EQ(0, adb_close(socket_fd[0])); adb_sleep_ms(SLEEP_FOR_FDEVENT_IN_MS); ASSERT_EQ(GetAdditionalLocalSocketCount(), fdevent_installed_count()); TerminateThread(thread); }
TEST_F(FdeventTest, smoke) { const size_t PIPE_COUNT = 10; const size_t MESSAGE_LOOP_COUNT = 100; const std::string MESSAGE = "fdevent_test"; int fd_pair1[2]; int fd_pair2[2]; ASSERT_EQ(0, pipe(fd_pair1)); ASSERT_EQ(0, pipe(fd_pair2)); pthread_t thread; ThreadArg thread_arg; thread_arg.first_read_fd = fd_pair1[0]; thread_arg.last_write_fd = fd_pair2[1]; thread_arg.middle_pipe_count = PIPE_COUNT; int writer = fd_pair1[1]; int reader = fd_pair2[0]; ASSERT_EQ(0, pthread_create(&thread, nullptr, reinterpret_cast<void* (*)(void*)>(FdEventThreadFunc), &thread_arg)); for (size_t i = 0; i < MESSAGE_LOOP_COUNT; ++i) { std::string read_buffer = MESSAGE; std::string write_buffer(MESSAGE.size(), 'a'); ASSERT_TRUE(WriteFdExactly(writer, read_buffer.c_str(), read_buffer.size())); ASSERT_TRUE(ReadFdExactly(reader, &write_buffer[0], write_buffer.size())); ASSERT_EQ(read_buffer, write_buffer); } ASSERT_EQ(0, pthread_kill(thread, SIGUSR1)); ASSERT_EQ(0, pthread_join(thread, nullptr)); ASSERT_EQ(0, close(writer)); ASSERT_EQ(0, close(reader)); }
static void fdevent_subproc_event_func(int fd, unsigned ev, void* /* userdata */) { ADB_LOGD(ADB_FDEV, "subproc handling on fd=%d ev=%04x", fd, ev); // Hook oneself back into the fde's suitable for select() on read. if ((fd < 0) || (fd >= fd_table_max)) { FATAL("fd %d out of range for fd_table", fd); } fdevent *fde = fd_table[fd]; fdevent_add(fde, FDE_READ); if (ev & FDE_READ) { int subproc_fd; if (!ReadFdExactly(fd, &subproc_fd, sizeof(subproc_fd))) { FATAL("Failed to read the subproc's fd from fd=%d", fd); } if ((subproc_fd < 0) || (subproc_fd >= fd_table_max)) { ADB_LOGD(ADB_FDEV, "subproc_fd %d out of range 0, fd_table_max=%d", subproc_fd, fd_table_max); return; } fdevent *subproc_fde = fd_table[subproc_fd]; if (!subproc_fde) { ADB_LOGD(ADB_FDEV, "subproc_fd %d cleared from fd_table", subproc_fd); return; } if (subproc_fde->fd != subproc_fd) { // Already reallocated? ADB_LOGD(ADB_FDEV, "subproc_fd %d != fd_table[].fd %d", subproc_fd, subproc_fde->fd); return; } subproc_fde->force_eof = 1; int rcount = 0; ioctl(subproc_fd, FIONREAD, &rcount); ADB_LOGD(ADB_FDEV, "subproc with fd=%d has rcount=%d err=%d", subproc_fd, rcount, errno); if (rcount) { // If there is data left, it will show up in the select(). // This works because there is no other thread reading that // data when in this fd_func(). return; } ADB_LOGD(ADB_FDEV, "subproc_fde.state=%04x", subproc_fde->state); subproc_fde->events |= FDE_READ; if (subproc_fde->state & FDE_PENDING) { return; } subproc_fde->state |= FDE_PENDING; fdevent_call_fdfunc(subproc_fde); } }
int sync_readtime(int fd, const char *path, unsigned int *timestamp, unsigned int *mode) { syncmsg msg; int len = strlen(path); msg.req.id = ID_STAT; msg.req.namelen = htoll(len); if(!WriteFdExactly(fd, &msg.req, sizeof(msg.req)) || !WriteFdExactly(fd, path, len)) { return -1; } if(!ReadFdExactly(fd, &msg.stat, sizeof(msg.stat))) { return -1; } if(msg.stat.id != ID_STAT) { return -1; } *timestamp = ltohl(msg.stat.time); *mode = ltohl(msg.stat.mode); return 0; }
TEST_F(LocalSocketTest, smoke) { // Join two socketpairs with a chain of intermediate socketpairs. int first[2]; std::vector<std::array<int, 2>> intermediates; int last[2]; constexpr size_t INTERMEDIATE_COUNT = 50; constexpr size_t MESSAGE_LOOP_COUNT = 100; const std::string MESSAGE = "socket_test"; intermediates.resize(INTERMEDIATE_COUNT); ASSERT_EQ(0, adb_socketpair(first)) << strerror(errno); ASSERT_EQ(0, adb_socketpair(last)) << strerror(errno); asocket* prev_tail = create_local_socket(first[1]); ASSERT_NE(nullptr, prev_tail); auto connect = [](asocket* tail, asocket* head) { tail->peer = head; head->peer = tail; tail->ready(tail); }; for (auto& intermediate : intermediates) { ASSERT_EQ(0, adb_socketpair(intermediate.data())) << strerror(errno); asocket* head = create_local_socket(intermediate[0]); ASSERT_NE(nullptr, head); asocket* tail = create_local_socket(intermediate[1]); ASSERT_NE(nullptr, tail); connect(prev_tail, head); prev_tail = tail; } asocket* end = create_local_socket(last[0]); ASSERT_NE(nullptr, end); connect(prev_tail, end); PrepareThread(); adb_thread_t thread; ASSERT_TRUE(adb_thread_create(FdEventThreadFunc, nullptr, &thread)); for (size_t i = 0; i < MESSAGE_LOOP_COUNT; ++i) { std::string read_buffer = MESSAGE; std::string write_buffer(MESSAGE.size(), 'a'); ASSERT_TRUE(WriteFdExactly(first[0], &read_buffer[0], read_buffer.size())); ASSERT_TRUE(ReadFdExactly(last[1], &write_buffer[0], write_buffer.size())); ASSERT_EQ(read_buffer, write_buffer); } ASSERT_EQ(0, adb_close(first[0])); ASSERT_EQ(0, adb_close(last[1])); // Wait until the local sockets are closed. adb_sleep_ms(SLEEP_FOR_FDEVENT_IN_MS); ASSERT_EQ(GetAdditionalLocalSocketCount(), fdevent_installed_count()); TerminateThread(thread); }
static bool handle_sync_command(int fd, std::vector<char>& buffer) { D("sync: waiting for request"); SyncRequest request; if (!ReadFdExactly(fd, &request, sizeof(request))) { SendSyncFail(fd, "command read failure"); return false; } size_t path_length = request.path_length; if (path_length > 1024) { SendSyncFail(fd, "path too long"); return false; } char name[1025]; if (!ReadFdExactly(fd, name, path_length)) { SendSyncFail(fd, "filename read failure"); return false; } name[path_length] = 0; const char* id = reinterpret_cast<const char*>(&request.id); D("sync: '%.4s' '%s'", id, name); switch (request.id) { case ID_STAT: if (!do_stat(fd, name)) return false; break; case ID_LIST: if (!do_list(fd, name)) return false; break; case ID_SEND: if (!do_send(fd, name, buffer)) return false; break; case ID_RECV: if (!do_recv(fd, name, buffer)) return false; break; case ID_QUIT: return false; default: SendSyncFail(fd, android::base::StringPrintf("unknown command '%.4s' (%08x)", id, request.id)); return false; } return true; }
bool ReadProtocolString(int fd, std::string* s, std::string* error) { char buf[5]; if (!ReadFdExactly(fd, buf, 4)) { *error = perror_str("protocol fault (couldn't read status length)"); return false; } buf[4] = 0; unsigned long len = strtoul(buf, 0, 16); s->resize(len, '\0'); if (!ReadFdExactly(fd, &(*s)[0], len)) { *error = perror_str("protocol fault (couldn't read status message)"); return false; } return true; }
static bool handle_send_link(int s, const std::string& path, std::vector<char>& buffer) { syncmsg msg; unsigned int len; int ret; if (!ReadFdExactly(s, &msg.data, sizeof(msg.data))) return false; if (msg.data.id != ID_DATA) { SendSyncFail(s, "invalid data message: expected ID_DATA"); return false; } len = msg.data.size; if (len > buffer.size()) { // TODO: resize buffer? SendSyncFail(s, "oversize data message"); return false; } if (!ReadFdExactly(s, &buffer[0], len)) return false; ret = symlink(&buffer[0], path.c_str()); if (ret && errno == ENOENT) { if (!secure_mkdirs(path)) { SendSyncFailErrno(s, "secure_mkdirs failed"); return false; } ret = symlink(&buffer[0], path.c_str()); } if (ret) { SendSyncFailErrno(s, "symlink failed"); return false; } if (!ReadFdExactly(s, &msg.data, sizeof(msg.data))) return false; if (msg.data.id == ID_DONE) { msg.status.id = ID_OKAY; msg.status.msglen = 0; if (!WriteFdExactly(s, &msg.status, sizeof(msg.status))) return false; } else { SendFail(s, "invalid data message: expected ID_DONE"); return false; } return true; }
TEST(io, ReadFdExactly_eof) { const char expected[] = "Foobar"; TemporaryFile tf; ASSERT_NE(-1, tf.fd); ASSERT_TRUE(android::base::WriteStringToFd(expected, tf.fd)) << strerror(errno); ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0)); // Test that not having enough data will fail. char buf[sizeof(expected) + 1] = {}; ASSERT_FALSE(ReadFdExactly(tf.fd, buf, sizeof(buf))); EXPECT_EQ(0, errno) << strerror(errno); }
TEST(io, ReadFdExactly_whole) { const char expected[] = "Foobar"; TemporaryFile tf; ASSERT_NE(-1, tf.fd); ASSERT_TRUE(android::base::WriteStringToFd(expected, tf.fd)) << strerror(errno); ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0)); // Test reading the whole file. char buf[sizeof(expected)] = {}; ASSERT_TRUE(ReadFdExactly(tf.fd, buf, sizeof(buf) - 1)) << strerror(errno); EXPECT_STREQ(expected, buf); }
int read_block_adb(void* data, uint32_t block, uint8_t* buffer, uint32_t fetch_size) { adb_data* ad = reinterpret_cast<adb_data*>(data); if (!WriteFdFmt(ad->sfd, "%08u", block)) { fprintf(stderr, "failed to write to adb host: %s\n", strerror(errno)); return -EIO; } if (!ReadFdExactly(ad->sfd, buffer, fetch_size)) { fprintf(stderr, "failed to read from adb host: %s\n", strerror(errno)); return -EIO; } return 0; }
static int remote_read(apacket *p, atransport *t) { if(!ReadFdExactly(t->sfd, &p->msg, sizeof(amessage))){ D("remote local: read terminated (message)\n"); return -1; } if(check_header(p, t)) { D("bad header: terminated (data)\n"); return -1; } if(!ReadFdExactly(t->sfd, p->data, p->msg.data_length)){ D("remote local: terminated (data)\n"); return -1; } if(check_data(p)) { D("bad data: terminated (data)\n"); return -1; } return 0; }
char *adb_query(const char *service) { char buf[5]; unsigned long n; char* tmp; D("adb_query: %s\n", service); int fd = adb_connect(service); if(fd < 0) { fprintf(stderr,"error: %s\n", __adb_error); return 0; } if(!ReadFdExactly(fd, buf, 4)) goto oops; buf[4] = 0; n = strtoul(buf, 0, 16); if(n >= 0xffff) { strcpy(__adb_error, "reply is too long (>= 64kB)"); goto oops; } tmp = reinterpret_cast<char*>(malloc(n + 1)); if(tmp == 0) goto oops; if(!ReadFdExactly(fd, tmp, n) == 0) { tmp[n] = 0; adb_close(fd); return tmp; } free(tmp); oops: adb_close(fd); return 0; }
TEST(io, ReadFdExactly_partial) { const char input[] = "Foobar"; TemporaryFile tf; ASSERT_NE(-1, tf.fd); ASSERT_TRUE(android::base::WriteStringToFd(input, tf.fd)) << strerror(errno); ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0)); // Test reading a partial file. char buf[sizeof(input) - 1] = {}; ASSERT_TRUE(ReadFdExactly(tf.fd, buf, sizeof(buf) - 1)); std::string expected(input); expected.pop_back(); EXPECT_STREQ(expected.c_str(), buf); }
static void fdevent_subproc_event_func(int fd, unsigned ev, void* /* userdata */) { D("subproc handling on fd = %d, ev = %x", fd, ev); CHECK_GE(fd, 0); if (ev & FDE_READ) { int subproc_fd; if(!ReadFdExactly(fd, &subproc_fd, sizeof(subproc_fd))) { LOG(FATAL) << "Failed to read the subproc's fd from " << fd; } auto it = g_poll_node_map.find(subproc_fd); if (it == g_poll_node_map.end()) { D("subproc_fd %d cleared from fd_table", subproc_fd); return; } fdevent* subproc_fde = it->second.fde; if(subproc_fde->fd != subproc_fd) { // Already reallocated? D("subproc_fd(%d) != subproc_fde->fd(%d)", subproc_fd, subproc_fde->fd); return; } subproc_fde->force_eof = 1; int rcount = 0; ioctl(subproc_fd, FIONREAD, &rcount); D("subproc with fd %d has rcount=%d, err=%d", subproc_fd, rcount, errno); if (rcount != 0) { // If there is data left, it will show up in the select(). // This works because there is no other thread reading that // data when in this fd_func(). return; } D("subproc_fde %s", dump_fde(subproc_fde).c_str()); subproc_fde->events |= FDE_READ; if(subproc_fde->state & FDE_PENDING) { return; } subproc_fde->state |= FDE_PENDING; fdevent_call_fdfunc(subproc_fde); } }
static int sync_finish_readtime(int fd, unsigned int *timestamp, unsigned int *mode, unsigned int *size) { syncmsg msg; if(!ReadFdExactly(fd, &msg.stat, sizeof(msg.stat))) return -1; if(msg.stat.id != ID_STAT) return -1; *timestamp = ltohl(msg.stat.time); *mode = ltohl(msg.stat.mode); *size = ltohl(msg.stat.size); return 0; }
void ShellServiceTest::CleanupTestSubprocess() { if (subprocess_fd_ >= 0) { // Subprocess should send its FD to SHELL_EXIT_NOTIFY_FD for cleanup. int notified_fd = -1; ASSERT_TRUE(ReadFdExactly(shell_exit_receiver_fd_, ¬ified_fd, sizeof(notified_fd))); ASSERT_EQ(notified_fd, subprocess_fd_); adb_close(subprocess_fd_); subprocess_fd_ = -1; // Restore SHELL_EXIT_NOTIFY_FD. adb_close(SHELL_EXIT_NOTIFY_FD); adb_close(shell_exit_receiver_fd_); shell_exit_receiver_fd_ = -1; SHELL_EXIT_NOTIFY_FD = saved_shell_exit_fd_; } }
bool adb_status(int fd, std::string* error) { char buf[5]; if (!ReadFdExactly(fd, buf, 4)) { *error = perror_str("protocol fault (couldn't read status)"); return false; } if (!memcmp(buf, "OKAY", 4)) { return true; } if (memcmp(buf, "FAIL", 4)) { *error = android::base::StringPrintf("protocol fault (status %02x %02x %02x %02x?!)", buf[0], buf[1], buf[2], buf[3]); return false; } ReadProtocolString(fd, error, error); return false; }
bool adb_kill_server() { D("adb_kill_server"); std::string reason; int fd = socket_spec_connect(__adb_server_socket_spec, &reason); if (fd < 0) { fprintf(stderr, "cannot connect to daemon at %s: %s\n", __adb_server_socket_spec, reason.c_str()); return true; } if (!SendProtocolString(fd, "host:kill")) { fprintf(stderr, "error: write failure during connection: %s\n", strerror(errno)); return false; } // The server might send OKAY, so consume that. char buf[4]; ReadFdExactly(fd, buf, 4); // Now that no more data is expected, wait for socket orderly shutdown or error, indicating // server death. ReadOrderlyShutdown(fd); return true; }
static bool handle_send_file(int s, const char* path, uid_t uid, gid_t gid, uint64_t capabilities, mode_t mode, std::vector<char>& buffer, bool do_unlink) { syncmsg msg; unsigned int timestamp = 0; __android_log_security_bswrite(SEC_TAG_ADB_SEND_FILE, path); int fd = adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, mode); if (fd < 0 && errno == ENOENT) { if (!secure_mkdirs(adb_dirname(path))) { SendSyncFailErrno(s, "secure_mkdirs failed"); goto fail; } fd = adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, mode); } if (fd < 0 && errno == EEXIST) { fd = adb_open_mode(path, O_WRONLY | O_CLOEXEC, mode); } if (fd < 0) { SendSyncFailErrno(s, "couldn't create file"); goto fail; } else { if (fchown(fd, uid, gid) == -1) { SendSyncFailErrno(s, "fchown failed"); goto fail; } // Not all filesystems support setting SELinux labels. http://b/23530370. selinux_android_restorecon(path, 0); // fchown clears the setuid bit - restore it if present. // Ignore the result of calling fchmod. It's not supported // by all filesystems, so we don't check for success. b/12441485 fchmod(fd, mode); if (!update_capabilities(path, capabilities)) { SendSyncFailErrno(s, "update_capabilities failed"); goto fail; } } while (true) { if (!ReadFdExactly(s, &msg.data, sizeof(msg.data))) goto fail; if (msg.data.id != ID_DATA) { if (msg.data.id == ID_DONE) { timestamp = msg.data.size; break; } SendSyncFail(s, "invalid data message"); goto abort; } if (msg.data.size > buffer.size()) { // TODO: resize buffer? SendSyncFail(s, "oversize data message"); goto abort; } if (!ReadFdExactly(s, &buffer[0], msg.data.size)) goto abort; if (!WriteFdExactly(fd, &buffer[0], msg.data.size)) { SendSyncFailErrno(s, "write failed"); goto fail; } } adb_close(fd); utimbuf u; u.actime = timestamp; u.modtime = timestamp; utime(path, &u); msg.status.id = ID_OKAY; msg.status.msglen = 0; return WriteFdExactly(s, &msg.status, sizeof(msg.status)); fail: // If there's a problem on the device, we'll send an ID_FAIL message and // close the socket. Unfortunately the kernel will sometimes throw that // data away if the other end keeps writing without reading (which is // the case with old versions of adb). To maintain compatibility, keep // reading and throwing away ID_DATA packets until the other side notices // that we've reported an error. while (true) { if (!ReadFdExactly(s, &msg.data, sizeof(msg.data))) goto fail; if (msg.data.id == ID_DONE) { goto abort; } else if (msg.data.id != ID_DATA) { char id[5]; memcpy(id, &msg.data.id, sizeof(msg.data.id)); id[4] = '\0'; D("handle_send_fail received unexpected id '%s' during failure", id); goto abort; } if (msg.data.size > buffer.size()) { D("handle_send_fail received oversized packet of length '%u' during failure", msg.data.size); goto abort; } if (!ReadFdExactly(s, &buffer[0], msg.data.size)) goto abort; } abort: if (fd >= 0) adb_close(fd); if (do_unlink) adb_unlink(path); return false; }
int adb_connect(const char *service) { // first query the adb server's version int fd = _adb_connect("host:version"); D("adb_connect: service %s\n", service); if(fd == -2 && __adb_server_name) { fprintf(stderr,"** Cannot start server on remote host\n"); return fd; } else if(fd == -2) { fprintf(stdout,"* daemon not running. starting it now on port %d *\n", __adb_server_port); start_server: if(launch_server(__adb_server_port)) { fprintf(stderr,"* failed to start daemon *\n"); return -1; } else { fprintf(stdout,"* daemon started successfully *\n"); } /* give the server some time to start properly and detect devices */ adb_sleep_ms(3000); // fall through to _adb_connect } else { // if server was running, check its version to make sure it is not out of date char buf[100]; size_t n; int version = ADB_SERVER_VERSION - 1; // if we have a file descriptor, then parse version result if(fd >= 0) { if(!ReadFdExactly(fd, buf, 4)) goto error; buf[4] = 0; n = strtoul(buf, 0, 16); if(n > sizeof(buf)) goto error; if(!ReadFdExactly(fd, buf, n)) goto error; adb_close(fd); if (sscanf(buf, "%04x", &version) != 1) goto error; } else { // if fd is -1, then check for "unknown host service", // which would indicate a version of adb that does not support the version command if (strcmp(__adb_error, "unknown host service") != 0) return fd; } if(version != ADB_SERVER_VERSION) { printf("adb server is out of date. killing...\n"); fd = _adb_connect("host:kill"); adb_close(fd); /* XXX can we better detect its death? */ adb_sleep_ms(2000); goto start_server; } } // if the command is start-server, we are done. if (!strcmp(service, "host:start-server")) return 0; fd = _adb_connect(service); if(fd == -1) { D("_adb_connect error: %s", __adb_error); } else if(fd == -2) { fprintf(stderr,"** daemon still not running\n"); } D("adb_connect: return fd %d\n", fd); return fd; error: adb_close(fd); return -1; }
static bool handle_send_file(int s, const char* path, uid_t uid, gid_t gid, mode_t mode, std::vector<char>& buffer, bool do_unlink) { syncmsg msg; unsigned int timestamp = 0; int fd = adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, mode); if (fd < 0 && errno == ENOENT) { if (!secure_mkdirs(path)) { SendSyncFailErrno(s, "secure_mkdirs failed"); goto fail; } fd = adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, mode); } if (fd < 0 && errno == EEXIST) { fd = adb_open_mode(path, O_WRONLY | O_CLOEXEC, mode); } if (fd < 0) { SendSyncFailErrno(s, "couldn't create file"); goto fail; } else { if (fchown(fd, uid, gid) == -1) { SendSyncFailErrno(s, "fchown failed"); goto fail; } // Not all filesystems support setting SELinux labels. http://b/23530370. selinux_android_restorecon(path, 0); // fchown clears the setuid bit - restore it if present. // Ignore the result of calling fchmod. It's not supported // by all filesystems. b/12441485 fchmod(fd, mode); } while (true) { unsigned int len; if (!ReadFdExactly(s, &msg.data, sizeof(msg.data))) goto fail; if (msg.data.id != ID_DATA) { if (msg.data.id == ID_DONE) { timestamp = msg.data.size; break; } SendSyncFail(s, "invalid data message"); goto fail; } len = msg.data.size; if (len > buffer.size()) { // TODO: resize buffer? SendSyncFail(s, "oversize data message"); goto fail; } if (!ReadFdExactly(s, &buffer[0], len)) goto fail; if (!WriteFdExactly(fd, &buffer[0], len)) { SendSyncFailErrno(s, "write failed"); goto fail; } } adb_close(fd); utimbuf u; u.actime = timestamp; u.modtime = timestamp; utime(path, &u); msg.status.id = ID_OKAY; msg.status.msglen = 0; return WriteFdExactly(s, &msg.status, sizeof(msg.status)); fail: if (fd >= 0) adb_close(fd); if (do_unlink) adb_unlink(path); return false; }
static int sync_send(int fd, const char *lpath, const char *rpath, unsigned mtime, mode_t mode, bool show_progress) { syncmsg msg; int len, r; syncsendbuf *sbuf = &send_buffer; char* file_buffer = NULL; int size = 0; char tmp[64]; len = strlen(rpath); if(len > 1024) goto fail; snprintf(tmp, sizeof(tmp), ",%d", mode); r = strlen(tmp); msg.req.id = ID_SEND; msg.req.namelen = htoll(len + r); if(!WriteFdExactly(fd, &msg.req, sizeof(msg.req)) || !WriteFdExactly(fd, rpath, len) || !WriteFdExactly(fd, tmp, r)) { free(file_buffer); goto fail; } if (file_buffer) { write_data_buffer(fd, file_buffer, size, sbuf, show_progress); free(file_buffer); } else if (S_ISREG(mode)) write_data_file(fd, lpath, sbuf, show_progress); else if (S_ISLNK(mode)) write_data_link(fd, lpath, sbuf); else goto fail; msg.data.id = ID_DONE; msg.data.size = htoll(mtime); if(!WriteFdExactly(fd, &msg.data, sizeof(msg.data))) goto fail; if(!ReadFdExactly(fd, &msg.status, sizeof(msg.status))) return -1; if(msg.status.id != ID_OKAY) { if(msg.status.id == ID_FAIL) { len = ltohl(msg.status.msglen); if(len > 256) len = 256; if(!ReadFdExactly(fd, sbuf->data, len)) { return -1; } sbuf->data[len] = 0; } else strcpy(sbuf->data, "unknown reason"); fprintf(stderr,"failed to copy '%s' to '%s': %s\n", lpath, rpath, sbuf->data); return -1; } return 0; fail: fprintf(stderr,"protocol failure\n"); adb_close(fd); return -1; }
static int sync_recv(int fd, const char* rpath, const char* lpath, bool show_progress) { syncmsg msg; int len; int lfd = -1; char *buffer = send_buffer.data; unsigned id; unsigned long long size = 0; len = strlen(rpath); if(len > 1024) return -1; if (show_progress) { // Determine remote file size. syncmsg stat_msg; stat_msg.req.id = ID_STAT; stat_msg.req.namelen = htoll(len); if (!WriteFdExactly(fd, &stat_msg.req, sizeof(stat_msg.req)) || !WriteFdExactly(fd, rpath, len)) { return -1; } if (!ReadFdExactly(fd, &stat_msg.stat, sizeof(stat_msg.stat))) { return -1; } if (stat_msg.stat.id != ID_STAT) return -1; size = ltohl(stat_msg.stat.size); } msg.req.id = ID_RECV; msg.req.namelen = htoll(len); if(!WriteFdExactly(fd, &msg.req, sizeof(msg.req)) || !WriteFdExactly(fd, rpath, len)) { return -1; } if(!ReadFdExactly(fd, &msg.data, sizeof(msg.data))) { return -1; } id = msg.data.id; if((id == ID_DATA) || (id == ID_DONE)) { adb_unlink(lpath); mkdirs(lpath); lfd = adb_creat(lpath, 0644); if(lfd < 0) { fprintf(stderr,"cannot create '%s': %s\n", lpath, strerror(errno)); return -1; } goto handle_data; } else { goto remote_error; } for(;;) { if(!ReadFdExactly(fd, &msg.data, sizeof(msg.data))) { return -1; } id = msg.data.id; handle_data: len = ltohl(msg.data.size); if(id == ID_DONE) break; if(id != ID_DATA) goto remote_error; if(len > SYNC_DATA_MAX) { fprintf(stderr,"data overrun\n"); adb_close(lfd); return -1; } if(!ReadFdExactly(fd, buffer, len)) { adb_close(lfd); return -1; } if(!WriteFdExactly(lfd, buffer, len)) { fprintf(stderr,"cannot write '%s': %s\n", rpath, strerror(errno)); adb_close(lfd); return -1; } total_bytes += len; if (show_progress) { print_transfer_progress(total_bytes, size); } } adb_close(lfd); return 0; remote_error: adb_close(lfd); adb_unlink(lpath); if(id == ID_FAIL) { len = ltohl(msg.data.size); if(len > 256) len = 256; if(!ReadFdExactly(fd, buffer, len)) { return -1; } buffer[len] = 0; } else { memcpy(buffer, &id, 4); buffer[4] = 0; } fprintf(stderr,"failed to copy '%s' to '%s': %s\n", rpath, lpath, buffer); return 0; }
/* A worker thread that monitors host connections, and registers a transport for * every new host connection. This thread replaces server_socket_thread on * condition that adbd daemon runs inside the emulator, and emulator uses QEMUD * pipe to communicate with adbd daemon inside the guest. This is done in order * to provide more robust communication channel between ADB host and guest. The * main issue with server_socket_thread approach is that it runs on top of TCP, * and thus is sensitive to network disruptions. For instance, the * ConnectionManager may decide to reset all network connections, in which case * the connection between ADB host and guest will be lost. To make ADB traffic * independent from the network, we use here 'adb' QEMUD service to transfer data * between the host, and the guest. See external/qemu/android/adb-*.* that * implements the emulator's side of the protocol. Another advantage of using * QEMUD approach is that ADB will be up much sooner, since it doesn't depend * anymore on network being set up. * The guest side of the protocol contains the following phases: * - Connect with adb QEMUD service. In this phase a handle to 'adb' QEMUD service * is opened, and it becomes clear whether or not emulator supports that * protocol. * - Wait for the ADB host to create connection with the guest. This is done by * sending an 'accept' request to the adb QEMUD service, and waiting on * response. * - When new ADB host connection is accepted, the connection with adb QEMUD * service is registered as the transport, and a 'start' request is sent to the * adb QEMUD service, indicating that the guest is ready to receive messages. * Note that the guest will ignore messages sent down from the emulator before * the transport registration is completed. That's why we need to send the * 'start' request after the transport is registered. */ static void qemu_socket_thread(void* arg) { /* 'accept' request to the adb QEMUD service. */ static const char _accept_req[] = "accept"; /* 'start' request to the adb QEMUD service. */ static const char _start_req[] = "start"; /* 'ok' reply from the adb QEMUD service. */ static const char _ok_resp[] = "ok"; const int port = (int) (uintptr_t) arg; int fd; char tmp[256]; char con_name[32]; adb_thread_setname("qemu socket"); D("transport: qemu_socket_thread() starting"); /* adb QEMUD service connection request. */ snprintf(con_name, sizeof(con_name), "qemud:adb:%d", port); /* Connect to the adb QEMUD service. */ fd = qemu_pipe_open(con_name); if (fd < 0) { /* This could be an older version of the emulator, that doesn't * implement adb QEMUD service. Fall back to the old TCP way. */ D("adb service is not available. Falling back to TCP socket."); adb_thread_create(server_socket_thread, arg); return; } for(;;) { /* * Wait till the host creates a new connection. */ /* Send the 'accept' request. */ if (WriteFdExactly(fd, _accept_req, strlen(_accept_req))) { /* Wait for the response. In the response we expect 'ok' on success, * or 'ko' on failure. */ if (!ReadFdExactly(fd, tmp, 2) || memcmp(tmp, _ok_resp, 2)) { D("Accepting ADB host connection has failed."); adb_close(fd); } else { /* Host is connected. Register the transport, and start the * exchange. */ std::string serial = android::base::StringPrintf("host-%d", fd); register_socket_transport(fd, serial.c_str(), port, 1); if (!WriteFdExactly(fd, _start_req, strlen(_start_req))) { adb_close(fd); } } /* Prepare for accepting of the next ADB host connection. */ fd = qemu_pipe_open(con_name); if (fd < 0) { D("adb service become unavailable."); return; } } else { D("Unable to send the '%s' request to ADB service.", _accept_req); return; } } D("transport: qemu_socket_thread() exiting"); return; }