services.c revision 91acb14877e7138879057f794a61ee2fd424a41d
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/reboot.h> 36#endif 37 38typedef struct stinfo stinfo; 39 40struct stinfo { 41 void (*func)(int fd, void *cookie); 42 int fd; 43 void *cookie; 44}; 45 46 47void *service_bootstrap_func(void *x) 48{ 49 stinfo *sti = x; 50 sti->func(sti->fd, sti->cookie); 51 free(sti); 52 return 0; 53} 54 55#if ADB_HOST 56ADB_MUTEX_DEFINE( dns_lock ); 57 58static void dns_service(int fd, void *cookie) 59{ 60 char *hostname = cookie; 61 struct hostent *hp; 62 unsigned zero = 0; 63 64 adb_mutex_lock(&dns_lock); 65 hp = gethostbyname(hostname); 66 if(hp == 0) { 67 writex(fd, &zero, 4); 68 } else { 69 writex(fd, hp->h_addr, 4); 70 } 71 adb_mutex_unlock(&dns_lock); 72 adb_close(fd); 73} 74#else 75extern int recovery_mode; 76 77static void recover_service(int s, void *cookie) 78{ 79 unsigned char buf[4096]; 80 unsigned count = (unsigned) cookie; 81 int fd; 82 83 fd = adb_creat("/tmp/update", 0644); 84 if(fd < 0) { 85 adb_close(s); 86 return; 87 } 88 89 while(count > 0) { 90 unsigned xfer = (count > 4096) ? 4096 : count; 91 if(readx(s, buf, xfer)) break; 92 if(writex(fd, buf, xfer)) break; 93 count -= xfer; 94 } 95 96 if(count == 0) { 97 writex(s, "OKAY", 4); 98 } else { 99 writex(s, "FAIL", 4); 100 } 101 adb_close(fd); 102 adb_close(s); 103 104 fd = adb_creat("/tmp/update.begin", 0644); 105 adb_close(fd); 106} 107 108void restart_root_service(int fd, void *cookie) 109{ 110 char buf[100]; 111 char value[PROPERTY_VALUE_MAX]; 112 113 if (getuid() == 0) { 114 snprintf(buf, sizeof(buf), "adbd is already running as root\n"); 115 writex(fd, buf, strlen(buf)); 116 adb_close(fd); 117 } else { 118 property_get("ro.debuggable", value, ""); 119 if (strcmp(value, "1") != 0) { 120 snprintf(buf, sizeof(buf), "adbd cannot run as root in production builds\n"); 121 writex(fd, buf, strlen(buf)); 122 adb_close(fd); 123 return; 124 } 125 126 property_set("service.adb.root", "1"); 127 snprintf(buf, sizeof(buf), "restarting adbd as root\n"); 128 writex(fd, buf, strlen(buf)); 129 adb_close(fd); 130 131 // quit, and init will restart us as root 132 sleep(1); 133 exit(1); 134 } 135} 136 137void restart_tcp_service(int fd, void *cookie) 138{ 139 char buf[100]; 140 char value[PROPERTY_VALUE_MAX]; 141 int port = (int)cookie; 142 143 if (port <= 0) { 144 snprintf(buf, sizeof(buf), "invalid port\n"); 145 writex(fd, buf, strlen(buf)); 146 adb_close(fd); 147 return; 148 } 149 150 snprintf(value, sizeof(value), "%d", port); 151 property_set("service.adb.tcp.port", value); 152 snprintf(buf, sizeof(buf), "restarting in TCP mode port: %d\n", port); 153 writex(fd, buf, strlen(buf)); 154 adb_close(fd); 155 156 // quit, and init will restart us in TCP mode 157 sleep(1); 158 exit(1); 159} 160 161void restart_usb_service(int fd, void *cookie) 162{ 163 char buf[100]; 164 165 property_set("service.adb.tcp.port", "0"); 166 snprintf(buf, sizeof(buf), "restarting in USB mode\n"); 167 writex(fd, buf, strlen(buf)); 168 adb_close(fd); 169 170 // quit, and init will restart us in USB mode 171 sleep(1); 172 exit(1); 173} 174 175void reboot_service(int fd, void *arg) 176{ 177 char buf[100]; 178 int ret; 179 180 sync(); 181 ret = __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, 182 LINUX_REBOOT_CMD_RESTART2, (char *)arg); 183 if (ret < 0) { 184 snprintf(buf, sizeof(buf), "reboot failed: %s\n", strerror(errno)); 185 writex(fd, buf, strlen(buf)); 186 } 187 adb_close(fd); 188} 189 190#endif 191 192#if 0 193static void echo_service(int fd, void *cookie) 194{ 195 char buf[4096]; 196 int r; 197 char *p; 198 int c; 199 200 for(;;) { 201 r = read(fd, buf, 4096); 202 if(r == 0) goto done; 203 if(r < 0) { 204 if(errno == EINTR) continue; 205 else goto done; 206 } 207 208 c = r; 209 p = buf; 210 while(c > 0) { 211 r = write(fd, p, c); 212 if(r > 0) { 213 c -= r; 214 p += r; 215 continue; 216 } 217 if((r < 0) && (errno == EINTR)) continue; 218 goto done; 219 } 220 } 221done: 222 close(fd); 223} 224#endif 225 226static int create_service_thread(void (*func)(int, void *), void *cookie) 227{ 228 stinfo *sti; 229 adb_thread_t t; 230 int s[2]; 231 232 if(adb_socketpair(s)) { 233 printf("cannot create service socket pair\n"); 234 return -1; 235 } 236 237 sti = malloc(sizeof(stinfo)); 238 if(sti == 0) fatal("cannot allocate stinfo"); 239 sti->func = func; 240 sti->cookie = cookie; 241 sti->fd = s[1]; 242 243 if(adb_thread_create( &t, service_bootstrap_func, sti)){ 244 free(sti); 245 adb_close(s[0]); 246 adb_close(s[1]); 247 printf("cannot create service thread\n"); 248 return -1; 249 } 250 251 D("service thread started, %d:%d\n",s[0], s[1]); 252 return s[0]; 253} 254 255static int create_subprocess(const char *cmd, const char *arg0, const char *arg1) 256{ 257#ifdef HAVE_WIN32_PROC 258 fprintf(stderr, "error: create_subprocess not implemented on Win32 (%s %s %s)\n", cmd, arg0, arg1); 259 return -1; 260#else /* !HAVE_WIN32_PROC */ 261 char *devname; 262 int ptm; 263 pid_t pid; 264 265 ptm = unix_open("/dev/ptmx", O_RDWR); // | O_NOCTTY); 266 if(ptm < 0){ 267 printf("[ cannot open /dev/ptmx - %s ]\n",strerror(errno)); 268 return -1; 269 } 270 fcntl(ptm, F_SETFD, FD_CLOEXEC); 271 272 if(grantpt(ptm) || unlockpt(ptm) || 273 ((devname = (char*) ptsname(ptm)) == 0)){ 274 printf("[ trouble with /dev/ptmx - %s ]\n", strerror(errno)); 275 return -1; 276 } 277 278 pid = fork(); 279 if(pid < 0) { 280 printf("- fork failed: %s -\n", strerror(errno)); 281 return -1; 282 } 283 284 if(pid == 0){ 285 int pts; 286 287 setsid(); 288 289 pts = unix_open(devname, O_RDWR); 290 if(pts < 0) exit(-1); 291 292 dup2(pts, 0); 293 dup2(pts, 1); 294 dup2(pts, 2); 295 296 adb_close(ptm); 297 298 execl(cmd, cmd, arg0, arg1, NULL); 299 fprintf(stderr, "- exec '%s' failed: %s (%d) -\n", 300 cmd, strerror(errno), errno); 301 exit(-1); 302 } else { 303#if !ADB_HOST 304 // set child's OOM adjustment to zero 305 char text[64]; 306 snprintf(text, sizeof text, "/proc/%d/oom_adj", pid); 307 int fd = adb_open(text, O_WRONLY); 308 if (fd >= 0) { 309 adb_write(fd, "0", 1); 310 adb_close(fd); 311 } else { 312 D("adb: unable to open %s\n", text); 313 } 314#endif 315 return ptm; 316 } 317#endif /* !HAVE_WIN32_PROC */ 318} 319 320#if ADB_HOST 321#define SHELL_COMMAND "/bin/sh" 322#else 323#define SHELL_COMMAND "/system/bin/sh" 324#endif 325 326int service_to_fd(const char *name) 327{ 328 int ret = -1; 329 330 if(!strncmp(name, "tcp:", 4)) { 331 int port = atoi(name + 4); 332 name = strchr(name + 4, ':'); 333 if(name == 0) { 334 ret = socket_loopback_client(port, SOCK_STREAM); 335 if (ret >= 0) 336 disable_tcp_nagle(ret); 337 } else { 338#if ADB_HOST 339 adb_mutex_lock(&dns_lock); 340 ret = socket_network_client(name + 1, port, SOCK_STREAM); 341 adb_mutex_unlock(&dns_lock); 342#else 343 return -1; 344#endif 345 } 346#ifndef HAVE_WINSOCK /* winsock doesn't implement unix domain sockets */ 347 } else if(!strncmp(name, "local:", 6)) { 348 ret = socket_local_client(name + 6, 349 ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM); 350 } else if(!strncmp(name, "localreserved:", 14)) { 351 ret = socket_local_client(name + 14, 352 ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM); 353 } else if(!strncmp(name, "localabstract:", 14)) { 354 ret = socket_local_client(name + 14, 355 ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM); 356 } else if(!strncmp(name, "localfilesystem:", 16)) { 357 ret = socket_local_client(name + 16, 358 ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM); 359#endif 360#if ADB_HOST 361 } else if(!strncmp("dns:", name, 4)){ 362 char *n = strdup(name + 4); 363 if(n == 0) return -1; 364 ret = create_service_thread(dns_service, n); 365#else /* !ADB_HOST */ 366 } else if(!strncmp("dev:", name, 4)) { 367 ret = unix_open(name + 4, O_RDWR); 368 } else if(!strncmp(name, "framebuffer:", 12)) { 369 ret = create_service_thread(framebuffer_service, 0); 370 } else if(recovery_mode && !strncmp(name, "recover:", 8)) { 371 ret = create_service_thread(recover_service, (void*) atoi(name + 8)); 372 } else if (!strncmp(name, "jdwp:", 5)) { 373 ret = create_jdwp_connection_fd(atoi(name+5)); 374 } else if (!strncmp(name, "log:", 4)) { 375 ret = create_service_thread(log_service, get_log_file_path(name + 4)); 376#endif 377 } else if(!HOST && !strncmp(name, "shell:", 6)) { 378 if(name[6]) { 379 ret = create_subprocess(SHELL_COMMAND, "-c", name + 6); 380 } else { 381 ret = create_subprocess(SHELL_COMMAND, "-", 0); 382 } 383#if !ADB_HOST 384 } else if(!strncmp(name, "sync:", 5)) { 385 ret = create_service_thread(file_sync_service, NULL); 386 } else if(!strncmp(name, "remount:", 8)) { 387 ret = create_service_thread(remount_service, NULL); 388 } else if(!strncmp(name, "reboot:", 7)) { 389 const char* arg = name + 7; 390 if (*name == 0) 391 arg = NULL; 392 ret = create_service_thread(reboot_service, (void *)arg); 393 } else if(!strncmp(name, "root:", 5)) { 394 ret = create_service_thread(restart_root_service, NULL); 395 } else if(!strncmp(name, "tcpip:", 6)) { 396 int port; 397 if (sscanf(name + 6, "%d", &port) == 0) { 398 port = 0; 399 } 400 ret = create_service_thread(restart_tcp_service, (void *)port); 401 } else if(!strncmp(name, "usb:", 4)) { 402 ret = create_service_thread(restart_usb_service, NULL); 403#endif 404#if 0 405 } else if(!strncmp(name, "echo:", 5)){ 406 ret = create_service_thread(echo_service, 0); 407#endif 408 } 409 if (ret >= 0) { 410 close_on_exec(ret); 411 } 412 return ret; 413} 414 415#if ADB_HOST 416struct state_info { 417 transport_type transport; 418 char* serial; 419 int state; 420}; 421 422static void wait_for_state(int fd, void* cookie) 423{ 424 struct state_info* sinfo = cookie; 425 char* err = "unknown error"; 426 427 D("wait_for_state %d\n", sinfo->state); 428 429 atransport *t = acquire_one_transport(sinfo->state, sinfo->transport, sinfo->serial, &err); 430 if(t != 0) { 431 writex(fd, "OKAY", 4); 432 } else { 433 sendfailmsg(fd, err); 434 } 435 436 if (sinfo->serial) 437 free(sinfo->serial); 438 free(sinfo); 439 adb_close(fd); 440 D("wait_for_state is done\n"); 441} 442#endif 443 444#if ADB_HOST 445asocket* host_service_to_socket(const char* name, const char *serial) 446{ 447 if (!strcmp(name,"track-devices")) { 448 return create_device_tracker(); 449 } else if (!strncmp(name, "wait-for-", strlen("wait-for-"))) { 450 struct state_info* sinfo = malloc(sizeof(struct state_info)); 451 452 if (serial) 453 sinfo->serial = strdup(serial); 454 else 455 sinfo->serial = NULL; 456 457 name += strlen("wait-for-"); 458 459 if (!strncmp(name, "local", strlen("local"))) { 460 sinfo->transport = kTransportLocal; 461 sinfo->state = CS_DEVICE; 462 } else if (!strncmp(name, "usb", strlen("usb"))) { 463 sinfo->transport = kTransportUsb; 464 sinfo->state = CS_DEVICE; 465 } else if (!strncmp(name, "any", strlen("any"))) { 466 sinfo->transport = kTransportAny; 467 sinfo->state = CS_DEVICE; 468 } else { 469 free(sinfo); 470 return NULL; 471 } 472 473 int fd = create_service_thread(wait_for_state, sinfo); 474 return create_local_socket(fd); 475 } 476 return NULL; 477} 478#endif /* ADB_HOST */ 479