Home | History | Annotate | Download | only in adb
      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_SERVICES
     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 #    include <sys/ioctl.h>
     34 #  endif
     35 #else
     36 #  include <cutils/android_reboot.h>
     37 #endif
     38 
     39 typedef struct stinfo stinfo;
     40 
     41 struct stinfo {
     42     void (*func)(int fd, void *cookie);
     43     int fd;
     44     void *cookie;
     45 };
     46 
     47 
     48 void *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
     57 ADB_MUTEX_DEFINE( dns_lock );
     58 
     59 static 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     free(cookie);
     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
     77 extern int recovery_mode;
     78 
     79 static 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 
    110 void 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             adb_close(fd);
    125             return;
    126         }
    127 
    128         property_set("service.adb.root", "1");
    129         snprintf(buf, sizeof(buf), "restarting adbd as root\n");
    130         writex(fd, buf, strlen(buf));
    131         adb_close(fd);
    132     }
    133 }
    134 
    135 void restart_tcp_service(int fd, void *cookie)
    136 {
    137     char buf[100];
    138     char value[PROPERTY_VALUE_MAX];
    139     int port = (int)cookie;
    140 
    141     if (port <= 0) {
    142         snprintf(buf, sizeof(buf), "invalid port\n");
    143         writex(fd, buf, strlen(buf));
    144         adb_close(fd);
    145         return;
    146     }
    147 
    148     snprintf(value, sizeof(value), "%d", port);
    149     property_set("service.adb.tcp.port", value);
    150     snprintf(buf, sizeof(buf), "restarting in TCP mode port: %d\n", port);
    151     writex(fd, buf, strlen(buf));
    152     adb_close(fd);
    153 }
    154 
    155 void restart_usb_service(int fd, void *cookie)
    156 {
    157     char buf[100];
    158 
    159     property_set("service.adb.tcp.port", "0");
    160     snprintf(buf, sizeof(buf), "restarting in USB mode\n");
    161     writex(fd, buf, strlen(buf));
    162     adb_close(fd);
    163 }
    164 
    165 void reboot_service(int fd, void *arg)
    166 {
    167     char buf[100];
    168     int pid, ret;
    169 
    170     sync();
    171 
    172     /* Attempt to unmount the SD card first.
    173      * No need to bother checking for errors.
    174      */
    175     pid = fork();
    176     if (pid == 0) {
    177         /* ask vdc to unmount it */
    178         execl("/system/bin/vdc", "/system/bin/vdc", "volume", "unmount",
    179                 getenv("EXTERNAL_STORAGE"), "force", NULL);
    180     } else if (pid > 0) {
    181         /* wait until vdc succeeds or fails */
    182         waitpid(pid, &ret, 0);
    183     }
    184 
    185     ret = android_reboot(ANDROID_RB_RESTART2, 0, (char *) arg);
    186     if (ret < 0) {
    187         snprintf(buf, sizeof(buf), "reboot failed: %s\n", strerror(errno));
    188         writex(fd, buf, strlen(buf));
    189     }
    190     free(arg);
    191     adb_close(fd);
    192 }
    193 
    194 #endif
    195 
    196 #if 0
    197 static void echo_service(int fd, void *cookie)
    198 {
    199     char buf[4096];
    200     int r;
    201     char *p;
    202     int c;
    203 
    204     for(;;) {
    205         r = read(fd, buf, 4096);
    206         if(r == 0) goto done;
    207         if(r < 0) {
    208             if(errno == EINTR) continue;
    209             else goto done;
    210         }
    211 
    212         c = r;
    213         p = buf;
    214         while(c > 0) {
    215             r = write(fd, p, c);
    216             if(r > 0) {
    217                 c -= r;
    218                 p += r;
    219                 continue;
    220             }
    221             if((r < 0) && (errno == EINTR)) continue;
    222             goto done;
    223         }
    224     }
    225 done:
    226     close(fd);
    227 }
    228 #endif
    229 
    230 static int create_service_thread(void (*func)(int, void *), void *cookie)
    231 {
    232     stinfo *sti;
    233     adb_thread_t t;
    234     int s[2];
    235 
    236     if(adb_socketpair(s)) {
    237         printf("cannot create service socket pair\n");
    238         return -1;
    239     }
    240 
    241     sti = malloc(sizeof(stinfo));
    242     if(sti == 0) fatal("cannot allocate stinfo");
    243     sti->func = func;
    244     sti->cookie = cookie;
    245     sti->fd = s[1];
    246 
    247     if(adb_thread_create( &t, service_bootstrap_func, sti)){
    248         free(sti);
    249         adb_close(s[0]);
    250         adb_close(s[1]);
    251         printf("cannot create service thread\n");
    252         return -1;
    253     }
    254 
    255     D("service thread started, %d:%d\n",s[0], s[1]);
    256     return s[0];
    257 }
    258 
    259 #if !ADB_HOST
    260 static int create_subprocess(const char *cmd, const char *arg0, const char *arg1, pid_t *pid)
    261 {
    262 #ifdef HAVE_WIN32_PROC
    263     D("create_subprocess(cmd=%s, arg0=%s, arg1=%s)\n", cmd, arg0, arg1);
    264     fprintf(stderr, "error: create_subprocess not implemented on Win32 (%s %s %s)\n", cmd, arg0, arg1);
    265     return -1;
    266 #else /* !HAVE_WIN32_PROC */
    267     char *devname;
    268     int ptm;
    269 
    270     ptm = unix_open("/dev/ptmx", O_RDWR); // | O_NOCTTY);
    271     if(ptm < 0){
    272         printf("[ cannot open /dev/ptmx - %s ]\n",strerror(errno));
    273         return -1;
    274     }
    275     fcntl(ptm, F_SETFD, FD_CLOEXEC);
    276 
    277     if(grantpt(ptm) || unlockpt(ptm) ||
    278        ((devname = (char*) ptsname(ptm)) == 0)){
    279         printf("[ trouble with /dev/ptmx - %s ]\n", strerror(errno));
    280         adb_close(ptm);
    281         return -1;
    282     }
    283 
    284     *pid = fork();
    285     if(*pid < 0) {
    286         printf("- fork failed: %s -\n", strerror(errno));
    287         adb_close(ptm);
    288         return -1;
    289     }
    290 
    291     if(*pid == 0){
    292         int pts;
    293 
    294         setsid();
    295 
    296         pts = unix_open(devname, O_RDWR);
    297         if(pts < 0) {
    298             fprintf(stderr, "child failed to open pseudo-term slave: %s\n", devname);
    299             exit(-1);
    300         }
    301 
    302         dup2(pts, 0);
    303         dup2(pts, 1);
    304         dup2(pts, 2);
    305 
    306         adb_close(pts);
    307         adb_close(ptm);
    308 
    309         // set OOM adjustment to zero
    310         char text[64];
    311         snprintf(text, sizeof text, "/proc/%d/oom_adj", getpid());
    312         int fd = adb_open(text, O_WRONLY);
    313         if (fd >= 0) {
    314             adb_write(fd, "0", 1);
    315             adb_close(fd);
    316         } else {
    317            D("adb: unable to open %s\n", text);
    318         }
    319         execl(cmd, cmd, arg0, arg1, NULL);
    320         fprintf(stderr, "- exec '%s' failed: %s (%d) -\n",
    321                 cmd, strerror(errno), errno);
    322         exit(-1);
    323     } else {
    324         // Don't set child's OOM adjustment to zero.
    325         // Let the child do it itself, as sometimes the parent starts
    326         // running before the child has a /proc/pid/oom_adj.
    327         // """adb: unable to open /proc/644/oom_adj""" seen in some logs.
    328         return ptm;
    329     }
    330 #endif /* !HAVE_WIN32_PROC */
    331 }
    332 #endif  /* !ABD_HOST */
    333 
    334 #if ADB_HOST
    335 #define SHELL_COMMAND "/bin/sh"
    336 #else
    337 #define SHELL_COMMAND "/system/bin/sh"
    338 #endif
    339 
    340 #if !ADB_HOST
    341 static void subproc_waiter_service(int fd, void *cookie)
    342 {
    343     pid_t pid = (pid_t)cookie;
    344 
    345     D("entered. fd=%d of pid=%d\n", fd, pid);
    346     for (;;) {
    347         int status;
    348         pid_t p = waitpid(pid, &status, 0);
    349         if (p == pid) {
    350             D("fd=%d, post waitpid(pid=%d) status=%04x\n", fd, p, status);
    351             if (WIFSIGNALED(status)) {
    352                 D("*** Killed by signal %d\n", WTERMSIG(status));
    353                 break;
    354             } else if (!WIFEXITED(status)) {
    355                 D("*** Didn't exit!!. status %d\n", status);
    356                 break;
    357             } else if (WEXITSTATUS(status) >= 0) {
    358                 D("*** Exit code %d\n", WEXITSTATUS(status));
    359                 break;
    360             }
    361          }
    362     }
    363     D("shell exited fd=%d of pid=%d err=%d\n", fd, pid, errno);
    364     if (SHELL_EXIT_NOTIFY_FD >=0) {
    365       int res;
    366       res = writex(SHELL_EXIT_NOTIFY_FD, &fd, sizeof(fd));
    367       D("notified shell exit via fd=%d for pid=%d res=%d errno=%d\n",
    368         SHELL_EXIT_NOTIFY_FD, pid, res, errno);
    369     }
    370 }
    371 
    372 static int create_subproc_thread(const char *name)
    373 {
    374     stinfo *sti;
    375     adb_thread_t t;
    376     int ret_fd;
    377     pid_t pid;
    378     if(name) {
    379         ret_fd = create_subprocess(SHELL_COMMAND, "-c", name, &pid);
    380     } else {
    381         ret_fd = create_subprocess(SHELL_COMMAND, "-", 0, &pid);
    382     }
    383     D("create_subprocess() ret_fd=%d pid=%d\n", ret_fd, pid);
    384 
    385     sti = malloc(sizeof(stinfo));
    386     if(sti == 0) fatal("cannot allocate stinfo");
    387     sti->func = subproc_waiter_service;
    388     sti->cookie = (void*)pid;
    389     sti->fd = ret_fd;
    390 
    391     if(adb_thread_create( &t, service_bootstrap_func, sti)){
    392         free(sti);
    393         adb_close(ret_fd);
    394         printf("cannot create service thread\n");
    395         return -1;
    396     }
    397 
    398     D("service thread started, fd=%d pid=%d\n",ret_fd, pid);
    399     return ret_fd;
    400 }
    401 #endif
    402 
    403 int service_to_fd(const char *name)
    404 {
    405     int ret = -1;
    406 
    407     if(!strncmp(name, "tcp:", 4)) {
    408         int port = atoi(name + 4);
    409         name = strchr(name + 4, ':');
    410         if(name == 0) {
    411             ret = socket_loopback_client(port, SOCK_STREAM);
    412             if (ret >= 0)
    413                 disable_tcp_nagle(ret);
    414         } else {
    415 #if ADB_HOST
    416             adb_mutex_lock(&dns_lock);
    417             ret = socket_network_client(name + 1, port, SOCK_STREAM);
    418             adb_mutex_unlock(&dns_lock);
    419 #else
    420             return -1;
    421 #endif
    422         }
    423 #ifndef HAVE_WINSOCK   /* winsock doesn't implement unix domain sockets */
    424     } else if(!strncmp(name, "local:", 6)) {
    425         ret = socket_local_client(name + 6,
    426                 ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
    427     } else if(!strncmp(name, "localreserved:", 14)) {
    428         ret = socket_local_client(name + 14,
    429                 ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
    430     } else if(!strncmp(name, "localabstract:", 14)) {
    431         ret = socket_local_client(name + 14,
    432                 ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
    433     } else if(!strncmp(name, "localfilesystem:", 16)) {
    434         ret = socket_local_client(name + 16,
    435                 ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM);
    436 #endif
    437 #if ADB_HOST
    438     } else if(!strncmp("dns:", name, 4)){
    439         char *n = strdup(name + 4);
    440         if(n == 0) return -1;
    441         ret = create_service_thread(dns_service, n);
    442 #else /* !ADB_HOST */
    443     } else if(!strncmp("dev:", name, 4)) {
    444         ret = unix_open(name + 4, O_RDWR);
    445     } else if(!strncmp(name, "framebuffer:", 12)) {
    446         ret = create_service_thread(framebuffer_service, 0);
    447     } else if(recovery_mode && !strncmp(name, "recover:", 8)) {
    448         ret = create_service_thread(recover_service, (void*) atoi(name + 8));
    449     } else if (!strncmp(name, "jdwp:", 5)) {
    450         ret = create_jdwp_connection_fd(atoi(name+5));
    451     } else if (!strncmp(name, "log:", 4)) {
    452         ret = create_service_thread(log_service, get_log_file_path(name + 4));
    453     } else if(!HOST && !strncmp(name, "shell:", 6)) {
    454         if(name[6]) {
    455             ret = create_subproc_thread(name + 6);
    456         } else {
    457             ret = create_subproc_thread(0);
    458         }
    459     } else if(!strncmp(name, "sync:", 5)) {
    460         ret = create_service_thread(file_sync_service, NULL);
    461     } else if(!strncmp(name, "remount:", 8)) {
    462         ret = create_service_thread(remount_service, NULL);
    463     } else if(!strncmp(name, "reboot:", 7)) {
    464         void* arg = strdup(name + 7);
    465         if(arg == 0) return -1;
    466         ret = create_service_thread(reboot_service, arg);
    467     } else if(!strncmp(name, "root:", 5)) {
    468         ret = create_service_thread(restart_root_service, NULL);
    469     } else if(!strncmp(name, "backup:", 7)) {
    470         char* arg = strdup(name+7);
    471         if (arg == NULL) return -1;
    472         ret = backup_service(BACKUP, arg);
    473     } else if(!strncmp(name, "restore:", 8)) {
    474         ret = backup_service(RESTORE, NULL);
    475     } else if(!strncmp(name, "tcpip:", 6)) {
    476         int port;
    477         if (sscanf(name + 6, "%d", &port) == 0) {
    478             port = 0;
    479         }
    480         ret = create_service_thread(restart_tcp_service, (void *)port);
    481     } else if(!strncmp(name, "usb:", 4)) {
    482         ret = create_service_thread(restart_usb_service, NULL);
    483 #endif
    484 #if 0
    485     } else if(!strncmp(name, "echo:", 5)){
    486         ret = create_service_thread(echo_service, 0);
    487 #endif
    488     }
    489     if (ret >= 0) {
    490         close_on_exec(ret);
    491     }
    492     return ret;
    493 }
    494 
    495 #if ADB_HOST
    496 struct state_info {
    497     transport_type transport;
    498     char* serial;
    499     int state;
    500 };
    501 
    502 static void wait_for_state(int fd, void* cookie)
    503 {
    504     struct state_info* sinfo = cookie;
    505     char* err = "unknown error";
    506 
    507     D("wait_for_state %d\n", sinfo->state);
    508 
    509     atransport *t = acquire_one_transport(sinfo->state, sinfo->transport, sinfo->serial, &err);
    510     if(t != 0) {
    511         writex(fd, "OKAY", 4);
    512     } else {
    513         sendfailmsg(fd, err);
    514     }
    515 
    516     if (sinfo->serial)
    517         free(sinfo->serial);
    518     free(sinfo);
    519     adb_close(fd);
    520     D("wait_for_state is done\n");
    521 }
    522 #endif
    523 
    524 #if ADB_HOST
    525 asocket*  host_service_to_socket(const char*  name, const char *serial)
    526 {
    527     if (!strcmp(name,"track-devices")) {
    528         return create_device_tracker();
    529     } else if (!strncmp(name, "wait-for-", strlen("wait-for-"))) {
    530         struct state_info* sinfo = malloc(sizeof(struct state_info));
    531 
    532         if (serial)
    533             sinfo->serial = strdup(serial);
    534         else
    535             sinfo->serial = NULL;
    536 
    537         name += strlen("wait-for-");
    538 
    539         if (!strncmp(name, "local", strlen("local"))) {
    540             sinfo->transport = kTransportLocal;
    541             sinfo->state = CS_DEVICE;
    542         } else if (!strncmp(name, "usb", strlen("usb"))) {
    543             sinfo->transport = kTransportUsb;
    544             sinfo->state = CS_DEVICE;
    545         } else if (!strncmp(name, "any", strlen("any"))) {
    546             sinfo->transport = kTransportAny;
    547             sinfo->state = CS_DEVICE;
    548         } else {
    549             free(sinfo);
    550             return NULL;
    551         }
    552 
    553         int fd = create_service_thread(wait_for_state, sinfo);
    554         return create_local_socket(fd);
    555     }
    556     return NULL;
    557 }
    558 #endif /* ADB_HOST */
    559