services.c revision 5f4b051235c3e9e9e5b34b4af885e42a1c711fc4
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 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 reboot_service(int fd, char *arg) 138{ 139 char buf[100]; 140 int ret; 141 142 sync(); 143 ret = __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART2, arg); 144 if (ret < 0) { 145 snprintf(buf, sizeof(buf), "reboot failed: %s\n", strerror(errno)); 146 writex(fd, buf, strlen(buf)); 147 } 148 adb_close(fd); 149} 150 151#endif 152 153#if 0 154static void echo_service(int fd, void *cookie) 155{ 156 char buf[4096]; 157 int r; 158 char *p; 159 int c; 160 161 for(;;) { 162 r = read(fd, buf, 4096); 163 if(r == 0) goto done; 164 if(r < 0) { 165 if(errno == EINTR) continue; 166 else goto done; 167 } 168 169 c = r; 170 p = buf; 171 while(c > 0) { 172 r = write(fd, p, c); 173 if(r > 0) { 174 c -= r; 175 p += r; 176 continue; 177 } 178 if((r < 0) && (errno == EINTR)) continue; 179 goto done; 180 } 181 } 182done: 183 close(fd); 184} 185#endif 186 187static int create_service_thread(void (*func)(int, void *), void *cookie) 188{ 189 stinfo *sti; 190 adb_thread_t t; 191 int s[2]; 192 193 if(adb_socketpair(s)) { 194 printf("cannot create service socket pair\n"); 195 return -1; 196 } 197 198 sti = malloc(sizeof(stinfo)); 199 if(sti == 0) fatal("cannot allocate stinfo"); 200 sti->func = func; 201 sti->cookie = cookie; 202 sti->fd = s[1]; 203 204 if(adb_thread_create( &t, service_bootstrap_func, sti)){ 205 free(sti); 206 adb_close(s[0]); 207 adb_close(s[1]); 208 printf("cannot create service thread\n"); 209 return -1; 210 } 211 212 D("service thread started, %d:%d\n",s[0], s[1]); 213 return s[0]; 214} 215 216#if !ADB_HOST 217static int create_subprocess(const char *cmd, const char *arg0, const char *arg1) 218{ 219 char *devname; 220 int ptm; 221 pid_t pid; 222 223 ptm = unix_open("/dev/ptmx", O_RDWR); // | O_NOCTTY); 224 if(ptm < 0){ 225 printf("[ cannot open /dev/ptmx - %s ]\n",strerror(errno)); 226 return -1; 227 } 228 fcntl(ptm, F_SETFD, FD_CLOEXEC); 229 230 if(grantpt(ptm) || unlockpt(ptm) || 231 ((devname = (char*) ptsname(ptm)) == 0)){ 232 printf("[ trouble with /dev/ptmx - %s ]\n", strerror(errno)); 233 return -1; 234 } 235 236 pid = fork(); 237 if(pid < 0) { 238 printf("- fork failed: %s -\n", strerror(errno)); 239 return -1; 240 } 241 242 if(pid == 0){ 243 int pts; 244 245 setsid(); 246 247 pts = unix_open(devname, O_RDWR); 248 if(pts < 0) exit(-1); 249 250 dup2(pts, 0); 251 dup2(pts, 1); 252 dup2(pts, 2); 253 254 adb_close(ptm); 255 256 execl(cmd, cmd, arg0, arg1, NULL); 257 fprintf(stderr, "- exec '%s' failed: %s (%d) -\n", 258 cmd, strerror(errno), errno); 259 exit(-1); 260 } else { 261 // set child's OOM adjustment to zero 262 char text[64]; 263 snprintf(text, sizeof text, "/proc/%d/oom_adj", pid); 264 int fd = adb_open(text, O_WRONLY); 265 if (fd >= 0) { 266 adb_write(fd, "0", 1); 267 adb_close(fd); 268 } else { 269 D("adb: unable to open %s\n", text); 270 } 271 272 return ptm; 273 } 274} 275#endif /* !ADB_HOST */ 276 277#if ADB_HOST 278#define SHELL_COMMAND "/bin/sh" 279#else 280#define SHELL_COMMAND "/system/bin/sh" 281#endif 282 283#if !ADB_HOST 284static void shell_service(int s, void *command) 285{ 286 char buffer[MAX_PAYLOAD]; 287 char buffer2[MAX_PAYLOAD]; 288 struct pollfd ufds[2]; 289 int fd, ret = 0; 290 unsigned count = 0; 291 char** args = (char **)command; 292 fd = create_subprocess(SHELL_COMMAND, args[0], args[1]); 293 294 while (1) { 295 while (count < sizeof(buffer)) { 296 ufds[0].fd = fd; 297 ufds[0].events = POLLIN | POLLHUP; 298 ufds[0].revents = 0; 299 ufds[1].fd = s; 300 ufds[1].events = POLLIN | POLLHUP; 301 ufds[1].revents = 0; 302 // use a 100ms timeout so we don't block indefinitely with our 303 // buffer partially filled. 304 ret = poll(ufds, 2, 100); 305 if (ret <= 0) { 306 D("poll returned %d\n", ret); 307 // file has closed or we timed out 308 // set ret to 1 so we don't exit the outer loop 309 ret = 1; 310 break; 311 } 312 313 if (ufds[0].revents & POLLIN) { 314 ret = adb_read(fd, buffer + count, sizeof(buffer) - count); 315 D("read fd ret: %d, count: %d\n", ret, count); 316 if (ret > 0) 317 count += ret; 318 else 319 break; 320 } 321 if (ufds[1].revents & POLLIN) { 322 ret = adb_read(s, buffer2, sizeof(buffer2)); 323 D("read s ret: %d\n", ret); 324 if (ret > 0) 325 adb_write(fd, buffer2, ret); 326 else 327 break; 328 } 329 330 if ((ufds[0].revents & POLLHUP) || (ufds[1].revents & POLLHUP)) { 331 // set flag to exit after flushing the buffer 332 ret = -1; 333 break; 334 } 335 } 336 337 D("writing: %d\n", count); 338 if (count > 0) { 339 adb_write(s, buffer, count); 340 count = 0; 341 } 342 if (ret <= 0) 343 break; 344 } 345 346 D("shell_service done\n"); 347 348 adb_close(fd); 349 adb_close(s); 350} 351#endif // !ADB_HOST 352 353int service_to_fd(const char *name) 354{ 355 int ret = -1; 356 357 if(!strncmp(name, "tcp:", 4)) { 358 int port = atoi(name + 4); 359 name = strchr(name + 4, ':'); 360 if(name == 0) { 361 ret = socket_loopback_client(port, SOCK_STREAM); 362 if (ret >= 0) 363 disable_tcp_nagle(ret); 364 } else { 365#if ADB_HOST 366 adb_mutex_lock(&dns_lock); 367 ret = socket_network_client(name + 1, port, SOCK_STREAM); 368 adb_mutex_unlock(&dns_lock); 369#else 370 return -1; 371#endif 372 } 373#ifndef HAVE_WINSOCK /* winsock doesn't implement unix domain sockets */ 374 } else if(!strncmp(name, "local:", 6)) { 375 ret = socket_local_client(name + 6, 376 ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM); 377 } else if(!strncmp(name, "localreserved:", 14)) { 378 ret = socket_local_client(name + 14, 379 ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM); 380 } else if(!strncmp(name, "localabstract:", 14)) { 381 ret = socket_local_client(name + 14, 382 ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM); 383 } else if(!strncmp(name, "localfilesystem:", 16)) { 384 ret = socket_local_client(name + 16, 385 ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM); 386#endif 387#if ADB_HOST 388 } else if(!strncmp("dns:", name, 4)){ 389 char *n = strdup(name + 4); 390 if(n == 0) return -1; 391 ret = create_service_thread(dns_service, n); 392#else /* !ADB_HOST */ 393 } else if(!strncmp("dev:", name, 4)) { 394 ret = unix_open(name + 4, O_RDWR); 395 } else if(!strncmp(name, "framebuffer:", 12)) { 396 ret = create_service_thread(framebuffer_service, 0); 397 } else if(recovery_mode && !strncmp(name, "recover:", 8)) { 398 ret = create_service_thread(recover_service, (void*) atoi(name + 8)); 399 } else if (!strncmp(name, "jdwp:", 5)) { 400 ret = create_jdwp_connection_fd(atoi(name+5)); 401 } else if (!strncmp(name, "log:", 4)) { 402 ret = create_service_thread(log_service, get_log_file_path(name + 4)); 403 } else if(!HOST && !strncmp(name, "shell:", 6)) { 404 const char* args[2]; 405 if(name[6]) { 406 args[0] = "-c"; 407 args[1] = name + 6; 408 } else { 409 args[0] = "-"; 410 args[1] = 0; 411 } 412 ret = create_service_thread(shell_service, (void *)args); 413 } else if(!strncmp(name, "sync:", 5)) { 414 ret = create_service_thread(file_sync_service, NULL); 415 } else if(!strncmp(name, "remount:", 8)) { 416 ret = create_service_thread(remount_service, NULL); 417 } else if(!strncmp(name, "reboot:", 7)) { 418 char* arg = name + 7; 419 if (*name == 0) 420 arg = NULL; 421 ret = create_service_thread(reboot_service, arg); 422 } else if(!strncmp(name, "root:", 5)) { 423 ret = create_service_thread(restart_root_service, NULL); 424#endif 425#if 0 426 } else if(!strncmp(name, "echo:", 5)){ 427 ret = create_service_thread(echo_service, 0); 428#endif 429 } 430 if (ret >= 0) { 431 close_on_exec(ret); 432 } 433 return ret; 434} 435 436#if ADB_HOST 437struct state_info { 438 transport_type transport; 439 char* serial; 440 int state; 441}; 442 443static void wait_for_state(int fd, void* cookie) 444{ 445 struct state_info* sinfo = cookie; 446 char* err = "unknown error"; 447 448 D("wait_for_state %d\n", sinfo->state); 449 450 atransport *t = acquire_one_transport(sinfo->state, sinfo->transport, sinfo->serial, &err); 451 if(t != 0) { 452 writex(fd, "OKAY", 4); 453 } else { 454 sendfailmsg(fd, err); 455 } 456 457 if (sinfo->serial) 458 free(sinfo->serial); 459 free(sinfo); 460 adb_close(fd); 461 D("wait_for_state is done\n"); 462} 463#endif 464 465#if ADB_HOST 466asocket* host_service_to_socket(const char* name, const char *serial) 467{ 468 if (!strcmp(name,"track-devices")) { 469 return create_device_tracker(); 470 } else if (!strncmp(name, "wait-for-", strlen("wait-for-"))) { 471 struct state_info* sinfo = malloc(sizeof(struct state_info)); 472 473 if (serial) 474 sinfo->serial = strdup(serial); 475 else 476 sinfo->serial = NULL; 477 478 name += strlen("wait-for-"); 479 480 if (!strncmp(name, "local", strlen("local"))) { 481 sinfo->transport = kTransportLocal; 482 sinfo->state = CS_DEVICE; 483 } else if (!strncmp(name, "usb", strlen("usb"))) { 484 sinfo->transport = kTransportUsb; 485 sinfo->state = CS_DEVICE; 486 } else if (!strncmp(name, "any", strlen("any"))) { 487 sinfo->transport = kTransportAny; 488 sinfo->state = CS_DEVICE; 489 } else { 490 free(sinfo); 491 return NULL; 492 } 493 494 int fd = create_service_thread(wait_for_state, sinfo); 495 return create_local_socket(fd); 496 } 497 return NULL; 498} 499#endif /* ADB_HOST */ 500