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