services.c revision f56d1b5a76c6cb282a7689fc93f85de63bd205f6
1/* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <stdlib.h> 18#include <stdio.h> 19#include <unistd.h> 20#include <string.h> 21#include <errno.h> 22 23#include "sysdeps.h" 24 25#define TRACE_TAG TRACE_ADB 26#include "adb.h" 27#include "file_sync_service.h" 28 29#if ADB_HOST 30# ifndef HAVE_WINSOCK 31# include <netinet/in.h> 32# include <netdb.h> 33# endif 34#else 35#include <sys/poll.h> 36#include <sys/reboot.h> 37#endif 38 39typedef struct stinfo stinfo; 40 41struct stinfo { 42 void (*func)(int fd, void *cookie); 43 int fd; 44 void *cookie; 45}; 46 47 48void *service_bootstrap_func(void *x) 49{ 50 stinfo *sti = x; 51 sti->func(sti->fd, sti->cookie); 52 free(sti); 53 return 0; 54} 55 56#if ADB_HOST 57ADB_MUTEX_DEFINE( dns_lock ); 58 59static void dns_service(int fd, void *cookie) 60{ 61 char *hostname = cookie; 62 struct hostent *hp; 63 unsigned zero = 0; 64 65 adb_mutex_lock(&dns_lock); 66 hp = gethostbyname(hostname); 67 if(hp == 0) { 68 writex(fd, &zero, 4); 69 } else { 70 writex(fd, hp->h_addr, 4); 71 } 72 adb_mutex_unlock(&dns_lock); 73 adb_close(fd); 74} 75#else 76extern int recovery_mode; 77 78static void recover_service(int s, void *cookie) 79{ 80 unsigned char buf[4096]; 81 unsigned count = (unsigned) cookie; 82 int fd; 83 84 fd = adb_creat("/tmp/update", 0644); 85 if(fd < 0) { 86 adb_close(s); 87 return; 88 } 89 90 while(count > 0) { 91 unsigned xfer = (count > 4096) ? 4096 : count; 92 if(readx(s, buf, xfer)) break; 93 if(writex(fd, buf, xfer)) break; 94 count -= xfer; 95 } 96 97 if(count == 0) { 98 writex(s, "OKAY", 4); 99 } else { 100 writex(s, "FAIL", 4); 101 } 102 adb_close(fd); 103 adb_close(s); 104 105 fd = adb_creat("/tmp/update.begin", 0644); 106 adb_close(fd); 107} 108 109void restart_root_service(int fd, void *cookie) 110{ 111 char buf[100]; 112 char value[PROPERTY_VALUE_MAX]; 113 114 if (getuid() == 0) { 115 snprintf(buf, sizeof(buf), "adbd is already running as root\n"); 116 writex(fd, buf, strlen(buf)); 117 adb_close(fd); 118 } else { 119 property_get("ro.debuggable", value, ""); 120 if (strcmp(value, "1") != 0) { 121 snprintf(buf, sizeof(buf), "adbd cannot run as root in production builds\n"); 122 writex(fd, buf, strlen(buf)); 123 adb_close(fd); 124 return; 125 } 126 127 property_set("service.adb.root", "1"); 128 snprintf(buf, sizeof(buf), "restarting adbd as root\n"); 129 writex(fd, buf, strlen(buf)); 130 adb_close(fd); 131 132 // quit, and init will restart us as root 133 sleep(1); 134 exit(1); 135 } 136} 137 138void restart_tcp_service(int fd, void *cookie) 139{ 140 char buf[100]; 141 char value[PROPERTY_VALUE_MAX]; 142 int port = (int)cookie; 143 144 if (port <= 0) { 145 snprintf(buf, sizeof(buf), "invalid port\n"); 146 writex(fd, buf, strlen(buf)); 147 adb_close(fd); 148 return; 149 } 150 151 snprintf(value, sizeof(value), "%d", port); 152 property_set("service.adb.tcp.port", value); 153 snprintf(buf, sizeof(buf), "restarting in TCP mode port: %d\n", port); 154 writex(fd, buf, strlen(buf)); 155 adb_close(fd); 156 157 // quit, and init will restart us in TCP mode 158 sleep(1); 159 exit(1); 160} 161 162void restart_usb_service(int fd, void *cookie) 163{ 164 char buf[100]; 165 166 property_set("service.adb.tcp.port", "0"); 167 snprintf(buf, sizeof(buf), "restarting in USB mode\n"); 168 writex(fd, buf, strlen(buf)); 169 adb_close(fd); 170 171 // quit, and init will restart us in USB mode 172 sleep(1); 173 exit(1); 174} 175 176void reboot_service(int fd, void *arg) 177{ 178 char buf[100]; 179 int ret; 180 181 sync(); 182 ret = __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, 183 LINUX_REBOOT_CMD_RESTART2, (char *)arg); 184 if (ret < 0) { 185 snprintf(buf, sizeof(buf), "reboot failed: %s\n", strerror(errno)); 186 writex(fd, buf, strlen(buf)); 187 } 188 adb_close(fd); 189} 190 191#endif 192 193#if 0 194static void echo_service(int fd, void *cookie) 195{ 196 char buf[4096]; 197 int r; 198 char *p; 199 int c; 200 201 for(;;) { 202 r = read(fd, buf, 4096); 203 if(r == 0) goto done; 204 if(r < 0) { 205 if(errno == EINTR) continue; 206 else goto done; 207 } 208 209 c = r; 210 p = buf; 211 while(c > 0) { 212 r = write(fd, p, c); 213 if(r > 0) { 214 c -= r; 215 p += r; 216 continue; 217 } 218 if((r < 0) && (errno == EINTR)) continue; 219 goto done; 220 } 221 } 222done: 223 close(fd); 224} 225#endif 226 227static int create_service_thread(void (*func)(int, void *), void *cookie) 228{ 229 stinfo *sti; 230 adb_thread_t t; 231 int s[2]; 232 233 if(adb_socketpair(s)) { 234 printf("cannot create service socket pair\n"); 235 return -1; 236 } 237 238 sti = malloc(sizeof(stinfo)); 239 if(sti == 0) fatal("cannot allocate stinfo"); 240 sti->func = func; 241 sti->cookie = cookie; 242 sti->fd = s[1]; 243 244 if(adb_thread_create( &t, service_bootstrap_func, sti)){ 245 free(sti); 246 adb_close(s[0]); 247 adb_close(s[1]); 248 printf("cannot create service thread\n"); 249 return -1; 250 } 251 252 D("service thread started, %d:%d\n",s[0], s[1]); 253 return s[0]; 254} 255 256#if !ADB_HOST 257static int create_subprocess(const char *cmd, const char *arg0, const char *arg1) 258{ 259 char *devname; 260 int ptm; 261 pid_t pid; 262 263 ptm = unix_open("/dev/ptmx", O_RDWR); // | O_NOCTTY); 264 if(ptm < 0){ 265 printf("[ cannot open /dev/ptmx - %s ]\n",strerror(errno)); 266 return -1; 267 } 268 fcntl(ptm, F_SETFD, FD_CLOEXEC); 269 270 if(grantpt(ptm) || unlockpt(ptm) || 271 ((devname = (char*) ptsname(ptm)) == 0)){ 272 printf("[ trouble with /dev/ptmx - %s ]\n", strerror(errno)); 273 return -1; 274 } 275 276 pid = fork(); 277 if(pid < 0) { 278 printf("- fork failed: %s -\n", strerror(errno)); 279 return -1; 280 } 281 282 if(pid == 0){ 283 int pts; 284 285 setsid(); 286 287 pts = unix_open(devname, O_RDWR); 288 if(pts < 0) exit(-1); 289 290 dup2(pts, 0); 291 dup2(pts, 1); 292 dup2(pts, 2); 293 294 adb_close(ptm); 295 296 execl(cmd, cmd, arg0, arg1, NULL); 297 fprintf(stderr, "- exec '%s' failed: %s (%d) -\n", 298 cmd, strerror(errno), errno); 299 exit(-1); 300 } else { 301 // set child's OOM adjustment to zero 302 char text[64]; 303 snprintf(text, sizeof text, "/proc/%d/oom_adj", pid); 304 int fd = adb_open(text, O_WRONLY); 305 if (fd >= 0) { 306 adb_write(fd, "0", 1); 307 adb_close(fd); 308 } else { 309 D("adb: unable to open %s\n", text); 310 } 311 312 return ptm; 313 } 314} 315#endif /* !ADB_HOST */ 316 317#if ADB_HOST 318#define SHELL_COMMAND "/bin/sh" 319#else 320#define SHELL_COMMAND "/system/bin/sh" 321#endif 322 323#if !ADB_HOST 324static void shell_service(int s, void *command) 325{ 326 char buffer[MAX_PAYLOAD]; 327 char buffer2[MAX_PAYLOAD]; 328 struct pollfd ufds[2]; 329 int fd, ret = 0; 330 unsigned count = 0; 331 char** args = (char **)command; 332 fd = create_subprocess(SHELL_COMMAND, args[0], args[1]); 333 334 while (1) { 335 while (count < sizeof(buffer)) { 336 ufds[0].fd = fd; 337 ufds[0].events = POLLIN | POLLHUP; 338 ufds[0].revents = 0; 339 ufds[1].fd = s; 340 ufds[1].events = POLLIN | POLLHUP; 341 ufds[1].revents = 0; 342 // use a 100ms timeout so we don't block indefinitely with our 343 // buffer partially filled. 344 ret = poll(ufds, 2, 100); 345 if (ret <= 0) { 346 D("poll returned %d\n", ret); 347 // file has closed or we timed out 348 // set ret to 1 so we don't exit the outer loop 349 ret = 1; 350 break; 351 } 352 353 if (ufds[0].revents & POLLIN) { 354 ret = adb_read(fd, buffer + count, sizeof(buffer) - count); 355 D("read fd ret: %d, count: %d\n", ret, count); 356 if (ret > 0) 357 count += ret; 358 else 359 break; 360 } 361 if (ufds[1].revents & POLLIN) { 362 ret = adb_read(s, buffer2, sizeof(buffer2)); 363 D("read s ret: %d\n", ret); 364 if (ret > 0) 365 adb_write(fd, buffer2, ret); 366 else 367 break; 368 } 369 370 if ((ufds[0].revents & POLLHUP) || (ufds[1].revents & POLLHUP)) { 371 // set flag to exit after flushing the buffer 372 ret = -1; 373 break; 374 } 375 } 376 377 D("writing: %d\n", count); 378 if (count > 0) { 379 adb_write(s, buffer, count); 380 count = 0; 381 } 382 if (ret <= 0) 383 break; 384 } 385 386 D("shell_service done\n"); 387 388 adb_close(fd); 389 adb_close(s); 390} 391#endif // !ADB_HOST 392 393int service_to_fd(const char *name) 394{ 395 int ret = -1; 396 397 if(!strncmp(name, "tcp:", 4)) { 398 int port = atoi(name + 4); 399 name = strchr(name + 4, ':'); 400 if(name == 0) { 401 ret = socket_loopback_client(port, SOCK_STREAM); 402 if (ret >= 0) 403 disable_tcp_nagle(ret); 404 } else { 405#if ADB_HOST 406 adb_mutex_lock(&dns_lock); 407 ret = socket_network_client(name + 1, port, SOCK_STREAM); 408 adb_mutex_unlock(&dns_lock); 409#else 410 return -1; 411#endif 412 } 413#ifndef HAVE_WINSOCK /* winsock doesn't implement unix domain sockets */ 414 } else if(!strncmp(name, "local:", 6)) { 415 ret = socket_local_client(name + 6, 416 ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM); 417 } else if(!strncmp(name, "localreserved:", 14)) { 418 ret = socket_local_client(name + 14, 419 ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM); 420 } else if(!strncmp(name, "localabstract:", 14)) { 421 ret = socket_local_client(name + 14, 422 ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM); 423 } else if(!strncmp(name, "localfilesystem:", 16)) { 424 ret = socket_local_client(name + 16, 425 ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM); 426#endif 427#if ADB_HOST 428 } else if(!strncmp("dns:", name, 4)){ 429 char *n = strdup(name + 4); 430 if(n == 0) return -1; 431 ret = create_service_thread(dns_service, n); 432#else /* !ADB_HOST */ 433 } else if(!strncmp("dev:", name, 4)) { 434 ret = unix_open(name + 4, O_RDWR); 435 } else if(!strncmp(name, "framebuffer:", 12)) { 436 ret = create_service_thread(framebuffer_service, 0); 437 } else if(recovery_mode && !strncmp(name, "recover:", 8)) { 438 ret = create_service_thread(recover_service, (void*) atoi(name + 8)); 439 } else if (!strncmp(name, "jdwp:", 5)) { 440 ret = create_jdwp_connection_fd(atoi(name+5)); 441 } else if (!strncmp(name, "log:", 4)) { 442 ret = create_service_thread(log_service, get_log_file_path(name + 4)); 443 } else if(!HOST && !strncmp(name, "shell:", 6)) { 444 const char* args[2]; 445 if(name[6]) { 446 args[0] = "-c"; 447 args[1] = name + 6; 448 } else { 449 args[0] = "-"; 450 args[1] = 0; 451 } 452 ret = create_service_thread(shell_service, (void *)args); 453 } else if(!strncmp(name, "sync:", 5)) { 454 ret = create_service_thread(file_sync_service, NULL); 455 } else if(!strncmp(name, "remount:", 8)) { 456 ret = create_service_thread(remount_service, NULL); 457 } else if(!strncmp(name, "reboot:", 7)) { 458 const char* arg = name + 7; 459 if (*name == 0) 460 arg = NULL; 461 ret = create_service_thread(reboot_service, (void *)arg); 462 } else if(!strncmp(name, "root:", 5)) { 463 ret = create_service_thread(restart_root_service, NULL); 464 } else if(!strncmp(name, "tcpip:", 6)) { 465 int port; 466 if (sscanf(name + 6, "%d", &port) == 0) { 467 port = 0; 468 } 469 ret = create_service_thread(restart_tcp_service, (void *)port); 470 } else if(!strncmp(name, "usb:", 4)) { 471 ret = create_service_thread(restart_usb_service, NULL); 472#endif 473#if 0 474 } else if(!strncmp(name, "echo:", 5)){ 475 ret = create_service_thread(echo_service, 0); 476#endif 477 } 478 if (ret >= 0) { 479 close_on_exec(ret); 480 } 481 return ret; 482} 483 484#if ADB_HOST 485struct state_info { 486 transport_type transport; 487 char* serial; 488 int state; 489}; 490 491static void wait_for_state(int fd, void* cookie) 492{ 493 struct state_info* sinfo = cookie; 494 char* err = "unknown error"; 495 496 D("wait_for_state %d\n", sinfo->state); 497 498 atransport *t = acquire_one_transport(sinfo->state, sinfo->transport, sinfo->serial, &err); 499 if(t != 0) { 500 writex(fd, "OKAY", 4); 501 } else { 502 sendfailmsg(fd, err); 503 } 504 505 if (sinfo->serial) 506 free(sinfo->serial); 507 free(sinfo); 508 adb_close(fd); 509 D("wait_for_state is done\n"); 510} 511#endif 512 513#if ADB_HOST 514asocket* host_service_to_socket(const char* name, const char *serial) 515{ 516 if (!strcmp(name,"track-devices")) { 517 return create_device_tracker(); 518 } else if (!strncmp(name, "wait-for-", strlen("wait-for-"))) { 519 struct state_info* sinfo = malloc(sizeof(struct state_info)); 520 521 if (serial) 522 sinfo->serial = strdup(serial); 523 else 524 sinfo->serial = NULL; 525 526 name += strlen("wait-for-"); 527 528 if (!strncmp(name, "local", strlen("local"))) { 529 sinfo->transport = kTransportLocal; 530 sinfo->state = CS_DEVICE; 531 } else if (!strncmp(name, "usb", strlen("usb"))) { 532 sinfo->transport = kTransportUsb; 533 sinfo->state = CS_DEVICE; 534 } else if (!strncmp(name, "any", strlen("any"))) { 535 sinfo->transport = kTransportAny; 536 sinfo->state = CS_DEVICE; 537 } else { 538 free(sinfo); 539 return NULL; 540 } 541 542 int fd = create_service_thread(wait_for_state, sinfo); 543 return create_local_socket(fd); 544 } 545 return NULL; 546} 547#endif /* ADB_HOST */ 548