add ext4,vfat and tar.bz2
[u-tools.git] / u-tools / apps / adb / services.c
blob2ae5fc8a1fee815dad4d4bbe2eaa947b55838b2d
1 /*
2 * Copyright (C) 2007 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include <stdlib.h>
18 #include <stdio.h>
19 #include <unistd.h>
20 #include <string.h>
21 #include <errno.h>
23 #include "sysdeps.h"
25 #define TRACE_TAG TRACE_ADB
26 #include "adb.h"
27 #include "file_sync_service.h"
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> // liunote
36 #include <linux/reboot.h>
37 #endif
39 typedef struct stinfo stinfo;
41 struct stinfo {
42 void (*func)(int fd, void *cookie);
43 int fd;
44 void *cookie;
48 void *service_bootstrap_func(void *x)
50 stinfo *sti = x;
51 sti->func(sti->fd, sti->cookie);
52 free(sti);
53 return 0;
56 #if ADB_HOST
57 ADB_MUTEX_DEFINE( dns_lock );
59 static void dns_service(int fd, void *cookie)
61 char *hostname = cookie;
62 struct hostent *hp;
63 unsigned zero = 0;
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);
73 adb_mutex_unlock(&dns_lock);
74 adb_close(fd);
76 #else
77 extern int recovery_mode;
79 static void recover_service(int s, void *cookie)
81 unsigned char buf[4096];
82 unsigned count = (unsigned) cookie;
83 int fd;
85 fd = adb_creat("/tmp/update", 0644);
86 if(fd < 0) {
87 adb_close(s);
88 return;
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;
98 if(count == 0) {
99 writex(s, "OKAY", 4);
100 } else {
101 writex(s, "FAIL", 4);
103 adb_close(fd);
104 adb_close(s);
106 fd = adb_creat("/tmp/update.begin", 0644);
107 adb_close(fd);
110 void restart_root_service(int fd, void *cookie)
112 char buf[100];
113 //char value[PROPERTY_VALUE_MAX];
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 #if 0 // liunote remove for no property
121 property_get("ro.debuggable", value, "");
122 if (strcmp(value, "1") != 0) {
123 snprintf(buf, sizeof(buf), "adbd cannot run as root in production builds\n");
124 writex(fd, buf, strlen(buf));
125 adb_close(fd);
126 return;
129 property_set("service.adb.root", "1");
130 snprintf(buf, sizeof(buf), "restarting adbd as root\n");
131 writex(fd, buf, strlen(buf));
132 adb_close(fd);
133 #endif
135 // quit, and init will restart us as root
136 sleep(1);
137 exit(1);
141 void restart_tcp_service(int fd, void *cookie)
143 char buf[100];
144 // char value[PROPERTY_VALUE_MAX];
145 int port = (int)cookie;
147 if (port <= 0) {
148 snprintf(buf, sizeof(buf), "invalid port\n");
149 writex(fd, buf, strlen(buf));
150 adb_close(fd);
151 return;
154 // snprintf(value, sizeof(value), "%d", port); // liunote remove
155 // property_set("service.adb.tcp.port", value);
157 snprintf(buf, sizeof(buf), "restarting in TCP mode port: %d\n", port);
158 writex(fd, buf, strlen(buf));
159 adb_close(fd);
161 // quit, and init will restart us in TCP mode
162 sleep(1);
163 exit(1);
166 void restart_usb_service(int fd, void *cookie)
168 char buf[100];
170 //property_set("service.adb.tcp.port", "0"); // liunote remove
171 snprintf(buf, sizeof(buf), "restarting in USB mode\n");
172 writex(fd, buf, strlen(buf));
173 adb_close(fd);
175 // quit, and init will restart us in USB mode
176 sleep(1);
177 exit(1);
180 #if 1 /* liunote use reboot service do adbd exit */
181 void reboot_service(int fd, void *arg)
183 #if 0
184 char buf[100];
185 int ret;
187 sync();
188 ret = __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
189 LINUX_REBOOT_CMD_RESTART2, (char *)arg);
190 if (ret < 0) {
191 snprintf(buf, sizeof(buf), "reboot failed: %s\n", strerror(errno));
192 writex(fd, buf, strlen(buf));
194 free(arg);
195 adb_close(fd);
196 #else
197 free(arg);
198 adb_close(fd);
199 sleep(1);
200 exit(1);
201 #endif
203 #endif
205 #endif
207 #if 0
208 static void echo_service(int fd, void *cookie)
210 char buf[4096];
211 int r;
212 char *p;
213 int c;
215 for(;;) {
216 r = read(fd, buf, 4096);
217 if(r == 0) goto done;
218 if(r < 0) {
219 if(errno == EINTR) continue;
220 else goto done;
223 c = r;
224 p = buf;
225 while(c > 0) {
226 r = write(fd, p, c);
227 if(r > 0) {
228 c -= r;
229 p += r;
230 continue;
232 if((r < 0) && (errno == EINTR)) continue;
233 goto done;
236 done:
237 close(fd);
239 #endif
241 static int create_service_thread(void (*func)(int, void *), void *cookie)
243 stinfo *sti;
244 adb_thread_t t;
245 int s[2];
247 if(adb_socketpair(s)) {
248 printf("cannot create service socket pair\n");
249 return -1;
252 sti = malloc(sizeof(stinfo));
253 if(sti == 0) fatal("cannot allocate stinfo");
254 sti->func = func;
255 sti->cookie = cookie;
256 sti->fd = s[1];
258 if(adb_thread_create( &t, service_bootstrap_func, sti)){
259 free(sti);
260 adb_close(s[0]);
261 adb_close(s[1]);
262 printf("cannot create service thread\n");
263 return -1;
266 D("service thread started, %d:%d\n",s[0], s[1]);
267 return s[0];
270 static int create_subprocess(const char *cmd, const char *arg0, const char *arg1)
272 #ifdef HAVE_WIN32_PROC
273 fprintf(stderr, "error: create_subprocess not implemented on Win32 (%s %s %s)\n", cmd, arg0, arg1);
274 return -1;
275 #else /* !HAVE_WIN32_PROC */
276 char *devname;
277 int ptm;
278 pid_t pid;
280 ptm = unix_open("/dev/ptmx", O_RDWR); // | O_NOCTTY);
281 if(ptm < 0){
282 printf("[ cannot open /dev/ptmx - %s ]\n",strerror(errno));
283 return -1;
285 fcntl(ptm, F_SETFD, FD_CLOEXEC);
287 if(grantpt(ptm) || unlockpt(ptm) ||
288 ((devname = (char*) ptsname(ptm)) == 0)){
289 printf("[ trouble with /dev/ptmx - %s ]\n", strerror(errno));
290 return -1;
293 pid = fork();
294 if(pid < 0) {
295 printf("- fork failed: %s -\n", strerror(errno));
296 return -1;
299 if(pid == 0){
300 int pts;
302 setsid();
304 pts = unix_open(devname, O_RDWR);
305 if(pts < 0) exit(-1);
307 dup2(pts, 0);
308 dup2(pts, 1);
309 dup2(pts, 2);
311 adb_close(ptm);
313 execl(cmd, cmd, arg0, arg1, NULL);
314 fprintf(stderr, "- exec '%s' failed: %s (%d) -\n",
315 cmd, strerror(errno), errno);
316 exit(-1);
317 } else {
318 #if !ADB_HOST
319 // set child's OOM adjustment to zero
320 char text[64];
321 snprintf(text, sizeof text, "/proc/%d/oom_adj", pid);
322 int fd = adb_open(text, O_WRONLY);
323 if (fd >= 0) {
324 adb_write(fd, "0", 1);
325 adb_close(fd);
326 } else {
327 D("adb: unable to open %s\n", text);
329 #endif
330 return ptm;
332 #endif /* !HAVE_WIN32_PROC */
335 #if ADB_HOST
336 #define SHELL_COMMAND "/bin/sh"
337 #else
338 #define SHELL_COMMAND "/system/bin/sh"
339 #endif
341 int service_to_fd(const char *name)
343 int ret = -1;
345 if(!strncmp(name, "tcp:", 4)) {
346 int port = atoi(name + 4);
347 name = strchr(name + 4, ':');
348 if(name == 0) {
349 ret = socket_loopback_client(port, SOCK_STREAM);
350 if (ret >= 0)
351 disable_tcp_nagle(ret);
352 } else {
353 #if ADB_HOST
354 adb_mutex_lock(&dns_lock);
355 ret = socket_network_client(name + 1, port, SOCK_STREAM);
356 adb_mutex_unlock(&dns_lock);
357 #else
358 return -1;
359 #endif
361 #ifndef HAVE_WINSOCK /* winsock doesn't implement unix domain sockets */
362 } else if(!strncmp(name, "local:", 6)) {
363 ret = socket_local_client(name + 6,
364 ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
365 } else if(!strncmp(name, "localreserved:", 14)) {
366 ret = socket_local_client(name + 14,
367 ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
368 } else if(!strncmp(name, "localabstract:", 14)) {
369 ret = socket_local_client(name + 14,
370 ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
371 } else if(!strncmp(name, "localfilesystem:", 16)) {
372 ret = socket_local_client(name + 16,
373 ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM);
374 #endif
375 #if ADB_HOST
376 } else if(!strncmp("dns:", name, 4)){
377 char *n = strdup(name + 4);
378 if(n == 0) return -1;
379 ret = create_service_thread(dns_service, n);
380 #else /* !ADB_HOST */
381 } else if(!strncmp("dev:", name, 4)) {
382 ret = unix_open(name + 4, O_RDWR);
383 } else if(!strncmp(name, "framebuffer:", 12)) {
384 ret = create_service_thread(framebuffer_service, 0);
385 } else if(recovery_mode && !strncmp(name, "recover:", 8)) {
386 ret = create_service_thread(recover_service, (void*) atoi(name + 8));
387 } else if (!strncmp(name, "jdwp:", 5)) {
388 ret = create_jdwp_connection_fd(atoi(name+5));
389 } /* else if (!strncmp(name, "log:", 4)) {
390 ret = create_service_thread(log_service, get_log_file_path(name + 4)); */
391 #endif /* liunote remove log_service for log cat cmd */
392 /*}*/ else if(!HOST && !strncmp(name, "shell:", 6)) {
393 if(name[6]) {
394 ret = create_subprocess(SHELL_COMMAND, "-c", name + 6);
395 } else {
396 ret = create_subprocess(SHELL_COMMAND, "-", 0);
398 #if !ADB_HOST
399 } else if(!strncmp(name, "sync:", 5)) {
400 ret = create_service_thread(file_sync_service, NULL);
401 } else if(!strncmp(name, "remount:", 8)) {
402 ret = create_service_thread(remount_service, NULL);
403 } else if(!strncmp(name, "reboot:", 7)) {
404 void* arg = strdup(name + 7);
405 if(arg == 0) return -1;
406 ret = create_service_thread(reboot_service, arg); /* liunote use reboot service do adb close */
407 } else if(!strncmp(name, "root:", 5)) {
408 ret = create_service_thread(restart_root_service, NULL);
409 } else if(!strncmp(name, "tcpip:", 6)) {
410 int port;
411 if (sscanf(name + 6, "%d", &port) == 0) {
412 port = 0;
414 ret = create_service_thread(restart_tcp_service, (void *)port);
415 } else if(!strncmp(name, "usb:", 4)) {
416 ret = create_service_thread(restart_usb_service, NULL);
417 #endif
418 #if 0
419 } else if(!strncmp(name, "echo:", 5)){
420 ret = create_service_thread(echo_service, 0);
421 #endif
423 if (ret >= 0) {
424 close_on_exec(ret);
426 return ret;
429 #if ADB_HOST
430 struct state_info {
431 transport_type transport;
432 char* serial;
433 int state;
436 static void wait_for_state(int fd, void* cookie)
438 struct state_info* sinfo = cookie;
439 char* err = "unknown error";
441 D("wait_for_state %d\n", sinfo->state);
443 atransport *t = acquire_one_transport(sinfo->state, sinfo->transport, sinfo->serial, &err);
444 if(t != 0) {
445 writex(fd, "OKAY", 4);
446 } else {
447 sendfailmsg(fd, err);
450 if (sinfo->serial)
451 free(sinfo->serial);
452 free(sinfo);
453 adb_close(fd);
454 D("wait_for_state is done\n");
456 #endif
458 #if ADB_HOST
459 asocket* host_service_to_socket(const char* name, const char *serial)
461 if (!strcmp(name,"track-devices")) {
462 return create_device_tracker();
463 } else if (!strncmp(name, "wait-for-", strlen("wait-for-"))) {
464 struct state_info* sinfo = malloc(sizeof(struct state_info));
466 if (serial)
467 sinfo->serial = strdup(serial);
468 else
469 sinfo->serial = NULL;
471 name += strlen("wait-for-");
473 if (!strncmp(name, "local", strlen("local"))) {
474 sinfo->transport = kTransportLocal;
475 sinfo->state = CS_DEVICE;
476 } else if (!strncmp(name, "usb", strlen("usb"))) {
477 sinfo->transport = kTransportUsb;
478 sinfo->state = CS_DEVICE;
479 } else if (!strncmp(name, "any", strlen("any"))) {
480 sinfo->transport = kTransportAny;
481 sinfo->state = CS_DEVICE;
482 } else {
483 free(sinfo);
484 return NULL;
487 int fd = create_service_thread(wait_for_state, sinfo);
488 return create_local_socket(fd);
490 return NULL;
492 #endif /* ADB_HOST */