aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDoug Zongker2012-01-09 17:16:13 -0600
committerDoug Zongker2012-01-10 12:18:17 -0600
commit9270a20a801403c9f60d6a701b39eae70d380403 (patch)
tree5bdb058af5b05a65112297a504018ee356e0ddbb
parent210f887382e0fd7e51ec6ce071972374a76f0722 (diff)
downloadplatform-bootable-recovery-9270a20a801403c9f60d6a701b39eae70d380403.tar.gz
platform-bootable-recovery-9270a20a801403c9f60d6a701b39eae70d380403.tar.xz
platform-bootable-recovery-9270a20a801403c9f60d6a701b39eae70d380403.zip
support "sideload over ADB" mode
Rather than depending on the existence of some place to store a file that is accessible to users on an an unbootable device (eg, a physical sdcard, external USB drive, etc.), add support for sideloading packages sent to the device with adb. This change adds a "minimal adbd" which supports nothing but receiving a package over adb (with the "adb sideload" command) and storing it to a fixed filename in the /tmp ramdisk, from where it can be verified and sideloaded in the usual way. This should be leave available even on locked user-build devices. The user can select "apply package from ADB" from the recovery menu, which starts minimal-adb mode (shutting down any real adbd that may be running). Once minimal-adb has received a package it exits (restarting real adbd if appropriate) and then verification and installation of the received package proceeds. Change-Id: I6fe13161ca064a98d06fa32104e1f432826582f5
-rw-r--r--Android.mk6
-rw-r--r--adb_install.cpp110
-rw-r--r--adb_install.h24
-rw-r--r--default_device.cpp10
-rw-r--r--device.h2
-rw-r--r--minadbd/Android.mk32
-rw-r--r--minadbd/README.txt27
-rw-r--r--minadbd/adb.c1151
-rw-r--r--minadbd/adb.h443
-rw-r--r--minadbd/fdevent.c695
-rw-r--r--minadbd/fdevent.h83
-rw-r--r--minadbd/mutex_list.h26
-rw-r--r--minadbd/services.c161
-rw-r--r--minadbd/sockets.c830
-rw-r--r--minadbd/sysdeps.h495
-rw-r--r--minadbd/transport.c1081
-rw-r--r--minadbd/transport.h26
-rw-r--r--minadbd/transport_usb.c148
-rw-r--r--minadbd/usb_linux_client.c157
-rw-r--r--minadbd/utils.c106
-rw-r--r--minadbd/utils.h68
-rw-r--r--recovery.cpp32
22 files changed, 5704 insertions, 9 deletions
diff --git a/Android.mk b/Android.mk
index a94ecc66..7e48e7f6 100644
--- a/Android.mk
+++ b/Android.mk
@@ -10,7 +10,8 @@ LOCAL_SRC_FILES := \
10 roots.cpp \ 10 roots.cpp \
11 ui.cpp \ 11 ui.cpp \
12 screen_ui.cpp \ 12 screen_ui.cpp \
13 verifier.cpp 13 verifier.cpp \
14 adb_install.cpp
14 15
15LOCAL_MODULE := recovery 16LOCAL_MODULE := recovery
16 17
@@ -40,7 +41,7 @@ else
40 LOCAL_STATIC_LIBRARIES += $(TARGET_RECOVERY_UI_LIB) 41 LOCAL_STATIC_LIBRARIES += $(TARGET_RECOVERY_UI_LIB)
41endif 42endif
42LOCAL_STATIC_LIBRARIES += libext4_utils libz 43LOCAL_STATIC_LIBRARIES += libext4_utils libz
43LOCAL_STATIC_LIBRARIES += libminzip libunz libmtdutils libmincrypt 44LOCAL_STATIC_LIBRARIES += libminzip libunz libmtdutils libmincrypt libminadbd
44LOCAL_STATIC_LIBRARIES += libminui libpixelflinger_static libpng libcutils 45LOCAL_STATIC_LIBRARIES += libminui libpixelflinger_static libpng libcutils
45LOCAL_STATIC_LIBRARIES += libstdc++ libc 46LOCAL_STATIC_LIBRARIES += libstdc++ libc
46 47
@@ -67,6 +68,7 @@ include $(BUILD_EXECUTABLE)
67include $(commands_recovery_local_path)/minui/Android.mk 68include $(commands_recovery_local_path)/minui/Android.mk
68include $(commands_recovery_local_path)/minelf/Android.mk 69include $(commands_recovery_local_path)/minelf/Android.mk
69include $(commands_recovery_local_path)/minzip/Android.mk 70include $(commands_recovery_local_path)/minzip/Android.mk
71include $(commands_recovery_local_path)/minadbd/Android.mk
70include $(commands_recovery_local_path)/mtdutils/Android.mk 72include $(commands_recovery_local_path)/mtdutils/Android.mk
71include $(commands_recovery_local_path)/tools/Android.mk 73include $(commands_recovery_local_path)/tools/Android.mk
72include $(commands_recovery_local_path)/edify/Android.mk 74include $(commands_recovery_local_path)/edify/Android.mk
diff --git a/adb_install.cpp b/adb_install.cpp
new file mode 100644
index 00000000..a226ea57
--- /dev/null
+++ b/adb_install.cpp
@@ -0,0 +1,110 @@
1/*
2 * Copyright (C) 2012 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 <unistd.h>
18#include <dirent.h>
19#include <errno.h>
20#include <stdlib.h>
21#include <string.h>
22#include <sys/types.h>
23#include <sys/wait.h>
24#include <sys/stat.h>
25#include <signal.h>
26#include <fcntl.h>
27
28#include "ui.h"
29#include "cutils/properties.h"
30#include "install.h"
31#include "common.h"
32#include "adb_install.h"
33extern "C" {
34#include "minadbd/adb.h"
35}
36
37static RecoveryUI* ui = NULL;
38
39static void
40set_usb_driver(bool enabled) {
41 int fd = open("/sys/class/android_usb/android0/enable", O_WRONLY);
42 if (fd < 0) {
43 ui->Print("failed to open driver control: %s\n", strerror(errno));
44 return;
45 }
46 if (write(fd, enabled ? "1" : "0", 1) < 0) {
47 ui->Print("failed to set driver control: %s\n", strerror(errno));
48 }
49 if (close(fd) < 0) {
50 ui->Print("failed to close driver control: %s\n", strerror(errno));
51 }
52}
53
54static void
55stop_adbd() {
56 property_set("ctl.stop", "adbd");
57 set_usb_driver(false);
58}
59
60
61static void
62maybe_restart_adbd() {
63 char value[PROPERTY_VALUE_MAX+1];
64 int len = property_get("ro.debuggable", value, NULL);
65 if (len == 1 && value[0] == '1') {
66 ui->Print("Restarting adbd...\n");
67 set_usb_driver(true);
68 property_set("ctl.start", "adbd");
69 }
70}
71
72int
73apply_from_adb(RecoveryUI* ui_, int* wipe_cache, const char* install_file) {
74 ui = ui_;
75
76 stop_adbd();
77 set_usb_driver(true);
78
79 ui->Print("\n\nNow send the package you want to apply\n"
80 "to the device with \"adb sideload <filename>\"...\n");
81
82 pid_t child;
83 if ((child = fork()) == 0) {
84 execl("/sbin/recovery", "recovery", "--adbd", NULL);
85 _exit(-1);
86 }
87 int status;
88 // TODO(dougz): there should be a way to cancel waiting for a
89 // package (by pushing some button combo on the device). For now
90 // you just have to 'adb sideload' a file that's not a valid
91 // package, like "/dev/null".
92 waitpid(child, &status, 0);
93 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
94 ui->Print("status %d\n", WEXITSTATUS(status));
95 }
96
97 set_usb_driver(false);
98 maybe_restart_adbd();
99
100 struct stat st;
101 if (stat(ADB_SIDELOAD_FILENAME, &st) != 0) {
102 if (errno == ENOENT) {
103 ui->Print("No package received.\n");
104 } else {
105 ui->Print("Error reading package:\n %s\n", strerror(errno));
106 }
107 return INSTALL_ERROR;
108 }
109 return install_package(ADB_SIDELOAD_FILENAME, wipe_cache, install_file);
110}
diff --git a/adb_install.h b/adb_install.h
new file mode 100644
index 00000000..a18b712a
--- /dev/null
+++ b/adb_install.h
@@ -0,0 +1,24 @@
1/*
2 * Copyright (C) 2012 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#ifndef _ADB_INSTALL_H
18#define _ADB_INSTALL_H
19
20class RecoveryUI;
21
22int apply_from_adb(RecoveryUI* h, int* wipe_cache, const char* install_file);
23
24#endif
diff --git a/default_device.cpp b/default_device.cpp
index 265ed071..648eaec4 100644
--- a/default_device.cpp
+++ b/default_device.cpp
@@ -26,8 +26,7 @@ static const char* HEADERS[] = { "Volume up/down to move highlight;",
26 NULL }; 26 NULL };
27 27
28static const char* ITEMS[] = {"reboot system now", 28static const char* ITEMS[] = {"reboot system now",
29 "apply update from external storage", 29 "apply update from ADB",
30 "apply update from cache",
31 "wipe data/factory reset", 30 "wipe data/factory reset",
32 "wipe cache partition", 31 "wipe cache partition",
33 NULL }; 32 NULL };
@@ -72,10 +71,9 @@ class DefaultDevice : public Device {
72 BuiltinAction InvokeMenuItem(int menu_position) { 71 BuiltinAction InvokeMenuItem(int menu_position) {
73 switch (menu_position) { 72 switch (menu_position) {
74 case 0: return REBOOT; 73 case 0: return REBOOT;
75 case 1: return APPLY_EXT; 74 case 1: return APPLY_ADB_SIDELOAD;
76 case 2: return APPLY_CACHE; 75 case 2: return WIPE_DATA;
77 case 3: return WIPE_DATA; 76 case 3: return WIPE_CACHE;
78 case 4: return WIPE_CACHE;
79 default: return NO_ACTION; 77 default: return NO_ACTION;
80 } 78 }
81 } 79 }
diff --git a/device.h b/device.h
index 8096a8d9..583de75e 100644
--- a/device.h
+++ b/device.h
@@ -66,7 +66,7 @@ class Device {
66 virtual int HandleMenuKey(int key, int visible) = 0; 66 virtual int HandleMenuKey(int key, int visible) = 0;
67 67
68 enum BuiltinAction { NO_ACTION, REBOOT, APPLY_EXT, APPLY_CACHE, 68 enum BuiltinAction { NO_ACTION, REBOOT, APPLY_EXT, APPLY_CACHE,
69 WIPE_DATA, WIPE_CACHE }; 69 APPLY_ADB_SIDELOAD, WIPE_DATA, WIPE_CACHE };
70 70
71 // Perform a recovery action selected from the menu. 71 // Perform a recovery action selected from the menu.
72 // 'menu_position' will be the item number of the selected menu 72 // 'menu_position' will be the item number of the selected menu
diff --git a/minadbd/Android.mk b/minadbd/Android.mk
new file mode 100644
index 00000000..5a4de682
--- /dev/null
+++ b/minadbd/Android.mk
@@ -0,0 +1,32 @@
1# Copyright 2005 The Android Open Source Project
2#
3# Android.mk for adb
4#
5
6LOCAL_PATH:= $(call my-dir)
7
8# minadbd library
9# =========================================================
10
11include $(CLEAR_VARS)
12
13LOCAL_SRC_FILES := \
14 adb.c \
15 fdevent.c \
16 transport.c \
17 transport_usb.c \
18 sockets.c \
19 services.c \
20 usb_linux_client.c \
21 utils.c
22
23LOCAL_CFLAGS := -O2 -g -DADB_HOST=0 -Wall -Wno-unused-parameter
24LOCAL_CFLAGS += -D_XOPEN_SOURCE -D_GNU_SOURCE
25
26LOCAL_MODULE := libminadbd
27
28LOCAL_STATIC_LIBRARIES := libcutils libc
29include $(BUILD_STATIC_LIBRARY)
30
31
32
diff --git a/minadbd/README.txt b/minadbd/README.txt
new file mode 100644
index 00000000..0c190d05
--- /dev/null
+++ b/minadbd/README.txt
@@ -0,0 +1,27 @@
1The contents of this directory are copied from system/core/adb, with
2the following changes:
3
4adb.c
5 - much support for host mode and non-linux OS's stripped out; this
6 version only runs as adbd on the device.
7 - does not setuid/setgid itself (always stays root)
8 - only uses USB transport
9 - references to JDWP removed
10 - main() removed
11
12adb.h
13 - minor changes to match adb.c changes
14
15sockets.c
16 - references to JDWP removed
17
18services.c
19 - all services except echo_service (which is commented out) removed
20 - all host mode support removed
21 - sideload_service() added; this is the only service supported. It
22 receives a single blob of data, writes it to a fixed filename, and
23 makes the process exit.
24
25Android.mk
26 - only builds in adbd mode; builds as static library instead of a
27 standalone executable.
diff --git a/minadbd/adb.c b/minadbd/adb.c
new file mode 100644
index 00000000..d1e97b31
--- /dev/null
+++ b/minadbd/adb.c
@@ -0,0 +1,1151 @@
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#define TRACE_TAG TRACE_ADB
18
19#include <stdio.h>
20#include <stdlib.h>
21#include <ctype.h>
22#include <stdarg.h>
23#include <errno.h>
24#include <string.h>
25#include <time.h>
26#include <sys/time.h>
27
28#include "sysdeps.h"
29#include "adb.h"
30
31#if !ADB_HOST
32#include <private/android_filesystem_config.h>
33#include <linux/capability.h>
34#include <linux/prctl.h>
35#else
36#include "usb_vendors.h"
37#endif
38
39#if ADB_TRACE
40ADB_MUTEX_DEFINE( D_lock );
41#endif
42
43int HOST = 0;
44
45static const char *adb_device_banner = "sideload";
46
47void fatal(const char *fmt, ...)
48{
49 va_list ap;
50 va_start(ap, fmt);
51 fprintf(stderr, "error: ");
52 vfprintf(stderr, fmt, ap);
53 fprintf(stderr, "\n");
54 va_end(ap);
55 exit(-1);
56}
57
58void fatal_errno(const char *fmt, ...)
59{
60 va_list ap;
61 va_start(ap, fmt);
62 fprintf(stderr, "error: %s: ", strerror(errno));
63 vfprintf(stderr, fmt, ap);
64 fprintf(stderr, "\n");
65 va_end(ap);
66 exit(-1);
67}
68
69int adb_trace_mask;
70
71/* read a comma/space/colum/semi-column separated list of tags
72 * from the ADB_TRACE environment variable and build the trace
73 * mask from it. note that '1' and 'all' are special cases to
74 * enable all tracing
75 */
76void adb_trace_init(void)
77{
78 const char* p = getenv("ADB_TRACE");
79 const char* q;
80
81 static const struct {
82 const char* tag;
83 int flag;
84 } tags[] = {
85 { "1", 0 },
86 { "all", 0 },
87 { "adb", TRACE_ADB },
88 { "sockets", TRACE_SOCKETS },
89 { "packets", TRACE_PACKETS },
90 { "rwx", TRACE_RWX },
91 { "usb", TRACE_USB },
92 { "sync", TRACE_SYNC },
93 { "sysdeps", TRACE_SYSDEPS },
94 { "transport", TRACE_TRANSPORT },
95 { "jdwp", TRACE_JDWP },
96 { "services", TRACE_SERVICES },
97 { NULL, 0 }
98 };
99
100 if (p == NULL)
101 return;
102
103 /* use a comma/column/semi-colum/space separated list */
104 while (*p) {
105 int len, tagn;
106
107 q = strpbrk(p, " ,:;");
108 if (q == NULL) {
109 q = p + strlen(p);
110 }
111 len = q - p;
112
113 for (tagn = 0; tags[tagn].tag != NULL; tagn++)
114 {
115 int taglen = strlen(tags[tagn].tag);
116
117 if (len == taglen && !memcmp(tags[tagn].tag, p, len) )
118 {
119 int flag = tags[tagn].flag;
120 if (flag == 0) {
121 adb_trace_mask = ~0;
122 return;
123 }
124 adb_trace_mask |= (1 << flag);
125 break;
126 }
127 }
128 p = q;
129 if (*p)
130 p++;
131 }
132}
133
134
135apacket *get_apacket(void)
136{
137 apacket *p = malloc(sizeof(apacket));
138 if(p == 0) fatal("failed to allocate an apacket");
139 memset(p, 0, sizeof(apacket) - MAX_PAYLOAD);
140 return p;
141}
142
143void put_apacket(apacket *p)
144{
145 free(p);
146}
147
148void handle_online(void)
149{
150 D("adb: online\n");
151}
152
153void handle_offline(atransport *t)
154{
155 D("adb: offline\n");
156 //Close the associated usb
157 run_transport_disconnects(t);
158}
159
160#if TRACE_PACKETS
161#define DUMPMAX 32
162void print_packet(const char *label, apacket *p)
163{
164 char *tag;
165 char *x;
166 unsigned count;
167
168 switch(p->msg.command){
169 case A_SYNC: tag = "SYNC"; break;
170 case A_CNXN: tag = "CNXN" ; break;
171 case A_OPEN: tag = "OPEN"; break;
172 case A_OKAY: tag = "OKAY"; break;
173 case A_CLSE: tag = "CLSE"; break;
174 case A_WRTE: tag = "WRTE"; break;
175 default: tag = "????"; break;
176 }
177
178 fprintf(stderr, "%s: %s %08x %08x %04x \"",
179 label, tag, p->msg.arg0, p->msg.arg1, p->msg.data_length);
180 count = p->msg.data_length;
181 x = (char*) p->data;
182 if(count > DUMPMAX) {
183 count = DUMPMAX;
184 tag = "\n";
185 } else {
186 tag = "\"\n";
187 }
188 while(count-- > 0){
189 if((*x >= ' ') && (*x < 127)) {
190 fputc(*x, stderr);
191 } else {
192 fputc('.', stderr);
193 }
194 x++;
195 }
196 fprintf(stderr, tag);
197}
198#endif
199
200static void send_ready(unsigned local, unsigned remote, atransport *t)
201{
202 D("Calling send_ready \n");
203 apacket *p = get_apacket();
204 p->msg.command = A_OKAY;
205 p->msg.arg0 = local;
206 p->msg.arg1 = remote;
207 send_packet(p, t);
208}
209
210static void send_close(unsigned local, unsigned remote, atransport *t)
211{
212 D("Calling send_close \n");
213 apacket *p = get_apacket();
214 p->msg.command = A_CLSE;
215 p->msg.arg0 = local;
216 p->msg.arg1 = remote;
217 send_packet(p, t);
218}
219
220static void send_connect(atransport *t)
221{
222 D("Calling send_connect \n");
223 apacket *cp = get_apacket();
224 cp->msg.command = A_CNXN;
225 cp->msg.arg0 = A_VERSION;
226 cp->msg.arg1 = MAX_PAYLOAD;
227 snprintf((char*) cp->data, sizeof cp->data, "%s::",
228 HOST ? "host" : adb_device_banner);
229 cp->msg.data_length = strlen((char*) cp->data) + 1;
230 send_packet(cp, t);
231#if ADB_HOST
232 /* XXX why sleep here? */
233 // allow the device some time to respond to the connect message
234 adb_sleep_ms(1000);
235#endif
236}
237
238static char *connection_state_name(atransport *t)
239{
240 if (t == NULL) {
241 return "unknown";
242 }
243
244 switch(t->connection_state) {
245 case CS_BOOTLOADER:
246 return "bootloader";
247 case CS_DEVICE:
248 return "device";
249 case CS_OFFLINE:
250 return "offline";
251 default:
252 return "unknown";
253 }
254}
255
256void parse_banner(char *banner, atransport *t)
257{
258 char *type, *product, *end;
259
260 D("parse_banner: %s\n", banner);
261 type = banner;
262 product = strchr(type, ':');
263 if(product) {
264 *product++ = 0;
265 } else {
266 product = "";
267 }
268
269 /* remove trailing ':' */
270 end = strchr(product, ':');
271 if(end) *end = 0;
272
273 /* save product name in device structure */
274 if (t->product == NULL) {
275 t->product = strdup(product);
276 } else if (strcmp(product, t->product) != 0) {
277 free(t->product);
278 t->product = strdup(product);
279 }
280
281 if(!strcmp(type, "bootloader")){
282 D("setting connection_state to CS_BOOTLOADER\n");
283 t->connection_state = CS_BOOTLOADER;
284 update_transports();
285 return;
286 }
287
288 if(!strcmp(type, "device")) {
289 D("setting connection_state to CS_DEVICE\n");
290 t->connection_state = CS_DEVICE;
291 update_transports();
292 return;
293 }
294
295 if(!strcmp(type, "recovery")) {
296 D("setting connection_state to CS_RECOVERY\n");
297 t->connection_state = CS_RECOVERY;
298 update_transports();
299 return;
300 }
301
302 if(!strcmp(type, "sideload")) {
303 D("setting connection_state to CS_SIDELOAD\n");
304 t->connection_state = CS_SIDELOAD;
305 update_transports();
306 return;
307 }
308
309 t->connection_state = CS_HOST;
310}
311
312void handle_packet(apacket *p, atransport *t)
313{
314 asocket *s;
315
316 D("handle_packet() %c%c%c%c\n", ((char*) (&(p->msg.command)))[0],
317 ((char*) (&(p->msg.command)))[1],
318 ((char*) (&(p->msg.command)))[2],
319 ((char*) (&(p->msg.command)))[3]);
320 print_packet("recv", p);
321
322 switch(p->msg.command){
323 case A_SYNC:
324 if(p->msg.arg0){
325 send_packet(p, t);
326 if(HOST) send_connect(t);
327 } else {
328 t->connection_state = CS_OFFLINE;
329 handle_offline(t);
330 send_packet(p, t);
331 }
332 return;
333
334 case A_CNXN: /* CONNECT(version, maxdata, "system-id-string") */
335 /* XXX verify version, etc */
336 if(t->connection_state != CS_OFFLINE) {
337 t->connection_state = CS_OFFLINE;
338 handle_offline(t);
339 }
340 parse_banner((char*) p->data, t);
341 handle_online();
342 if(!HOST) send_connect(t);
343 break;
344
345 case A_OPEN: /* OPEN(local-id, 0, "destination") */
346 if(t->connection_state != CS_OFFLINE) {
347 char *name = (char*) p->data;
348 name[p->msg.data_length > 0 ? p->msg.data_length - 1 : 0] = 0;
349 s = create_local_service_socket(name);
350 if(s == 0) {
351 send_close(0, p->msg.arg0, t);
352 } else {
353 s->peer = create_remote_socket(p->msg.arg0, t);
354 s->peer->peer = s;
355 send_ready(s->id, s->peer->id, t);
356 s->ready(s);
357 }
358 }
359 break;
360
361 case A_OKAY: /* READY(local-id, remote-id, "") */
362 if(t->connection_state != CS_OFFLINE) {
363 if((s = find_local_socket(p->msg.arg1))) {
364 if(s->peer == 0) {
365 s->peer = create_remote_socket(p->msg.arg0, t);
366 s->peer->peer = s;
367 }
368 s->ready(s);
369 }
370 }
371 break;
372
373 case A_CLSE: /* CLOSE(local-id, remote-id, "") */
374 if(t->connection_state != CS_OFFLINE) {
375 if((s = find_local_socket(p->msg.arg1))) {
376 s->close(s);
377 }
378 }
379 break;
380
381 case A_WRTE:
382 if(t->connection_state != CS_OFFLINE) {
383 if((s = find_local_socket(p->msg.arg1))) {
384 unsigned rid = p->msg.arg0;
385 p->len = p->msg.data_length;
386
387 if(s->enqueue(s, p) == 0) {
388 D("Enqueue the socket\n");
389 send_ready(s->id, rid, t);
390 }
391 return;
392 }
393 }
394 break;
395
396 default:
397 printf("handle_packet: what is %08x?!\n", p->msg.command);
398 }
399
400 put_apacket(p);
401}
402
403alistener listener_list = {
404 .next = &listener_list,
405 .prev = &listener_list,
406};
407
408static void ss_listener_event_func(int _fd, unsigned ev, void *_l)
409{
410 asocket *s;
411
412 if(ev & FDE_READ) {
413 struct sockaddr addr;
414 socklen_t alen;
415 int fd;
416
417 alen = sizeof(addr);
418 fd = adb_socket_accept(_fd, &addr, &alen);
419 if(fd < 0) return;
420
421 adb_socket_setbufsize(fd, CHUNK_SIZE);
422
423 s = create_local_socket(fd);
424 if(s) {
425 connect_to_smartsocket(s);
426 return;
427 }
428
429 adb_close(fd);
430 }
431}
432
433static void listener_event_func(int _fd, unsigned ev, void *_l)
434{
435 alistener *l = _l;
436 asocket *s;
437
438 if(ev & FDE_READ) {
439 struct sockaddr addr;
440 socklen_t alen;
441 int fd;
442
443 alen = sizeof(addr);
444 fd = adb_socket_accept(_fd, &addr, &alen);
445 if(fd < 0) return;
446
447 s = create_local_socket(fd);
448 if(s) {
449 s->transport = l->transport;
450 connect_to_remote(s, l->connect_to);
451 return;
452 }
453
454 adb_close(fd);
455 }
456}
457
458static void free_listener(alistener* l)
459{
460 if (l->next) {
461 l->next->prev = l->prev;
462 l->prev->next = l->next;
463 l->next = l->prev = l;
464 }
465
466 // closes the corresponding fd
467 fdevent_remove(&l->fde);
468
469 if (l->local_name)
470 free((char*)l->local_name);
471
472 if (l->connect_to)
473 free((char*)l->connect_to);
474
475 if (l->transport) {
476 remove_transport_disconnect(l->transport, &l->disconnect);
477 }
478 free(l);
479}
480
481static void listener_disconnect(void* _l, atransport* t)
482{
483 alistener* l = _l;
484
485 free_listener(l);
486}
487
488int local_name_to_fd(const char *name)
489{
490 int port;
491
492 if(!strncmp("tcp:", name, 4)){
493 int ret;
494 port = atoi(name + 4);
495 ret = socket_loopback_server(port, SOCK_STREAM);
496 return ret;
497 }
498#ifndef HAVE_WIN32_IPC /* no Unix-domain sockets on Win32 */
499 // It's non-sensical to support the "reserved" space on the adb host side
500 if(!strncmp(name, "local:", 6)) {
501 return socket_local_server(name + 6,
502 ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
503 } else if(!strncmp(name, "localabstract:", 14)) {
504 return socket_local_server(name + 14,
505 ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
506 } else if(!strncmp(name, "localfilesystem:", 16)) {
507 return socket_local_server(name + 16,
508 ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM);
509 }
510
511#endif
512 printf("unknown local portname '%s'\n", name);
513 return -1;
514}
515
516static int remove_listener(const char *local_name, const char *connect_to, atransport* transport)
517{
518 alistener *l;
519
520 for (l = listener_list.next; l != &listener_list; l = l->next) {
521 if (!strcmp(local_name, l->local_name) &&
522 !strcmp(connect_to, l->connect_to) &&
523 l->transport && l->transport == transport) {
524
525 listener_disconnect(l, transport);
526 return 0;
527 }
528 }
529
530 return -1;
531}
532
533static int install_listener(const char *local_name, const char *connect_to, atransport* transport)
534{
535 alistener *l;
536
537 //printf("install_listener('%s','%s')\n", local_name, connect_to);
538
539 for(l = listener_list.next; l != &listener_list; l = l->next){
540 if(strcmp(local_name, l->local_name) == 0) {
541 char *cto;
542
543 /* can't repurpose a smartsocket */
544 if(l->connect_to[0] == '*') {
545 return -1;
546 }
547
548 cto = strdup(connect_to);
549 if(cto == 0) {
550 return -1;
551 }
552
553 //printf("rebinding '%s' to '%s'\n", local_name, connect_to);
554 free((void*) l->connect_to);
555 l->connect_to = cto;
556 if (l->transport != transport) {
557 remove_transport_disconnect(l->transport, &l->disconnect);
558 l->transport = transport;
559 add_transport_disconnect(l->transport, &l->disconnect);
560 }
561 return 0;
562 }
563 }
564
565 if((l = calloc(1, sizeof(alistener))) == 0) goto nomem;
566 if((l->local_name = strdup(local_name)) == 0) goto nomem;
567 if((l->connect_to = strdup(connect_to)) == 0) goto nomem;
568
569
570 l->fd = local_name_to_fd(local_name);
571 if(l->fd < 0) {
572 free((void*) l->local_name);
573 free((void*) l->connect_to);
574 free(l);
575 printf("cannot bind '%s'\n", local_name);
576 return -2;
577 }
578
579 close_on_exec(l->fd);
580 if(!strcmp(l->connect_to, "*smartsocket*")) {
581 fdevent_install(&l->fde, l->fd, ss_listener_event_func, l);
582 } else {
583 fdevent_install(&l->fde, l->fd, listener_event_func, l);
584 }
585 fdevent_set(&l->fde, FDE_READ);
586
587 l->next = &listener_list;
588 l->prev = listener_list.prev;
589 l->next->prev = l;
590 l->prev->next = l;
591 l->transport = transport;
592
593 if (transport) {
594 l->disconnect.opaque = l;
595 l->disconnect.func = listener_disconnect;
596 add_transport_disconnect(transport, &l->disconnect);
597 }
598 return 0;
599
600nomem:
601 fatal("cannot allocate listener");
602 return 0;
603}
604
605#ifdef HAVE_WIN32_PROC
606static BOOL WINAPI ctrlc_handler(DWORD type)
607{
608 exit(STATUS_CONTROL_C_EXIT);
609 return TRUE;
610}
611#endif
612
613static void adb_cleanup(void)
614{
615 usb_cleanup();
616}
617
618void start_logging(void)
619{
620#ifdef HAVE_WIN32_PROC
621 char temp[ MAX_PATH ];
622 FILE* fnul;
623 FILE* flog;
624
625 GetTempPath( sizeof(temp) - 8, temp );
626 strcat( temp, "adb.log" );
627
628 /* Win32 specific redirections */
629 fnul = fopen( "NUL", "rt" );
630 if (fnul != NULL)
631 stdin[0] = fnul[0];
632
633 flog = fopen( temp, "at" );
634 if (flog == NULL)
635 flog = fnul;
636
637 setvbuf( flog, NULL, _IONBF, 0 );
638
639 stdout[0] = flog[0];
640 stderr[0] = flog[0];
641 fprintf(stderr,"--- adb starting (pid %d) ---\n", getpid());
642#else
643 int fd;
644
645 fd = unix_open("/dev/null", O_RDONLY);
646 dup2(fd, 0);
647 adb_close(fd);
648
649 fd = unix_open("/tmp/adb.log", O_WRONLY | O_CREAT | O_APPEND, 0640);
650 if(fd < 0) {
651 fd = unix_open("/dev/null", O_WRONLY);
652 }
653 dup2(fd, 1);
654 dup2(fd, 2);
655 adb_close(fd);
656 fprintf(stderr,"--- adb starting (pid %d) ---\n", getpid());
657#endif
658}
659
660#if !ADB_HOST
661void start_device_log(void)
662{
663 int fd;
664 char path[PATH_MAX];
665 struct tm now;
666 time_t t;
667 char value[PROPERTY_VALUE_MAX];
668
669 // read the trace mask from persistent property persist.adb.trace_mask
670 // give up if the property is not set or cannot be parsed
671 property_get("persist.adb.trace_mask", value, "");
672 if (sscanf(value, "%x", &adb_trace_mask) != 1)
673 return;
674
675 adb_mkdir("/data/adb", 0775);
676 tzset();
677 time(&t);
678 localtime_r(&t, &now);
679 strftime(path, sizeof(path),
680 "/data/adb/adb-%Y-%m-%d-%H-%M-%S.txt",
681 &now);
682 fd = unix_open(path, O_WRONLY | O_CREAT | O_TRUNC, 0640);
683 if (fd < 0)
684 return;
685
686 // redirect stdout and stderr to the log file
687 dup2(fd, 1);
688 dup2(fd, 2);
689 fprintf(stderr,"--- adb starting (pid %d) ---\n", getpid());
690 adb_close(fd);
691
692 fd = unix_open("/dev/null", O_RDONLY);
693 dup2(fd, 0);
694 adb_close(fd);
695}
696#endif
697
698#if ADB_HOST
699int launch_server(int server_port)
700{
701#ifdef HAVE_WIN32_PROC
702 /* we need to start the server in the background */
703 /* we create a PIPE that will be used to wait for the server's "OK" */
704 /* message since the pipe handles must be inheritable, we use a */
705 /* security attribute */
706 HANDLE pipe_read, pipe_write;
707 SECURITY_ATTRIBUTES sa;
708 STARTUPINFO startup;
709 PROCESS_INFORMATION pinfo;
710 char program_path[ MAX_PATH ];
711 int ret;
712
713 sa.nLength = sizeof(sa);
714 sa.lpSecurityDescriptor = NULL;
715 sa.bInheritHandle = TRUE;
716
717 /* create pipe, and ensure its read handle isn't inheritable */
718 ret = CreatePipe( &pipe_read, &pipe_write, &sa, 0 );
719 if (!ret) {
720 fprintf(stderr, "CreatePipe() failure, error %ld\n", GetLastError() );
721 return -1;
722 }
723
724 SetHandleInformation( pipe_read, HANDLE_FLAG_INHERIT, 0 );
725
726 ZeroMemory( &startup, sizeof(startup) );
727 startup.cb = sizeof(startup);
728 startup.hStdInput = GetStdHandle( STD_INPUT_HANDLE );
729 startup.hStdOutput = pipe_write;
730 startup.hStdError = GetStdHandle( STD_ERROR_HANDLE );
731 startup.dwFlags = STARTF_USESTDHANDLES;
732
733 ZeroMemory( &pinfo, sizeof(pinfo) );
734
735 /* get path of current program */
736 GetModuleFileName( NULL, program_path, sizeof(program_path) );
737
738 ret = CreateProcess(
739 program_path, /* program path */
740 "adb fork-server server",
741 /* the fork-server argument will set the
742 debug = 2 in the child */
743 NULL, /* process handle is not inheritable */
744 NULL, /* thread handle is not inheritable */
745 TRUE, /* yes, inherit some handles */
746 DETACHED_PROCESS, /* the new process doesn't have a console */
747 NULL, /* use parent's environment block */
748 NULL, /* use parent's starting directory */
749 &startup, /* startup info, i.e. std handles */
750 &pinfo );
751
752 CloseHandle( pipe_write );
753
754 if (!ret) {
755 fprintf(stderr, "CreateProcess failure, error %ld\n", GetLastError() );
756 CloseHandle( pipe_read );
757 return -1;
758 }
759
760 CloseHandle( pinfo.hProcess );
761 CloseHandle( pinfo.hThread );
762
763 /* wait for the "OK\n" message */
764 {
765 char temp[3];
766 DWORD count;
767
768 ret = ReadFile( pipe_read, temp, 3, &count, NULL );
769 CloseHandle( pipe_read );
770 if ( !ret ) {
771 fprintf(stderr, "could not read ok from ADB Server, error = %ld\n", GetLastError() );
772 return -1;
773 }
774 if (count != 3 || temp[0] != 'O' || temp[1] != 'K' || temp[2] != '\n') {
775 fprintf(stderr, "ADB server didn't ACK\n" );
776 return -1;
777 }
778 }
779#elif defined(HAVE_FORKEXEC)
780 char path[PATH_MAX];
781 int fd[2];
782
783 // set up a pipe so the child can tell us when it is ready.
784 // fd[0] will be parent's end, and fd[1] will get mapped to stderr in the child.
785 if (pipe(fd)) {
786 fprintf(stderr, "pipe failed in launch_server, errno: %d\n", errno);
787 return -1;
788 }
789 get_my_path(path, PATH_MAX);
790 pid_t pid = fork();
791 if(pid < 0) return -1;
792
793 if (pid == 0) {
794 // child side of the fork
795
796 // redirect stderr to the pipe
797 // we use stderr instead of stdout due to stdout's buffering behavior.
798 adb_close(fd[0]);
799 dup2(fd[1], STDERR_FILENO);
800 adb_close(fd[1]);
801
802 // child process
803 int result = execl(path, "adb", "fork-server", "server", NULL);
804 // this should not return
805 fprintf(stderr, "OOPS! execl returned %d, errno: %d\n", result, errno);
806 } else {
807 // parent side of the fork
808
809 char temp[3];
810
811 temp[0] = 'A'; temp[1] = 'B'; temp[2] = 'C';
812 // wait for the "OK\n" message
813 adb_close(fd[1]);
814 int ret = adb_read(fd[0], temp, 3);
815 int saved_errno = errno;
816 adb_close(fd[0]);
817 if (ret < 0) {
818 fprintf(stderr, "could not read ok from ADB Server, errno = %d\n", saved_errno);
819 return -1;
820 }
821 if (ret != 3 || temp[0] != 'O' || temp[1] != 'K' || temp[2] != '\n') {
822 fprintf(stderr, "ADB server didn't ACK\n" );
823 return -1;
824 }
825
826 setsid();
827 }
828#else
829#error "cannot implement background server start on this platform"
830#endif
831 return 0;
832}
833#endif
834
835/* Constructs a local name of form tcp:port.
836 * target_str points to the target string, it's content will be overwritten.
837 * target_size is the capacity of the target string.
838 * server_port is the port number to use for the local name.
839 */
840void build_local_name(char* target_str, size_t target_size, int server_port)
841{
842 snprintf(target_str, target_size, "tcp:%d", server_port);
843}
844
845int adb_main()
846{
847 atexit(adb_cleanup);
848#if defined(HAVE_FORKEXEC)
849 // No SIGCHLD. Let the service subproc handle its children.
850 signal(SIGPIPE, SIG_IGN);
851#endif
852
853 init_transport_registration();
854
855 // The minimal version of adbd only uses USB.
856 if (access("/dev/android_adb", F_OK) == 0) {
857 // listen on USB
858 usb_init();
859 }
860
861 D("Event loop starting\n");
862
863 fdevent_loop();
864
865 usb_cleanup();
866
867 return 0;
868}
869
870#if ADB_HOST
871void connect_device(char* host, char* buffer, int buffer_size)
872{
873 int port, fd;
874 char* portstr = strchr(host, ':');
875 char hostbuf[100];
876 char serial[100];
877
878 strncpy(hostbuf, host, sizeof(hostbuf) - 1);
879 if (portstr) {
880 if (portstr - host >= sizeof(hostbuf)) {
881 snprintf(buffer, buffer_size, "bad host name %s", host);
882 return;
883 }
884 // zero terminate the host at the point we found the colon
885 hostbuf[portstr - host] = 0;
886 if (sscanf(portstr + 1, "%d", &port) == 0) {
887 snprintf(buffer, buffer_size, "bad port number %s", portstr);
888 return;
889 }
890 } else {
891 port = DEFAULT_ADB_LOCAL_TRANSPORT_PORT;
892 }
893
894 snprintf(serial, sizeof(serial), "%s:%d", hostbuf, port);
895 if (find_transport(serial)) {
896 snprintf(buffer, buffer_size, "already connected to %s", serial);
897 return;
898 }
899
900 fd = socket_network_client(hostbuf, port, SOCK_STREAM);
901 if (fd < 0) {
902 snprintf(buffer, buffer_size, "unable to connect to %s:%d", host, port);
903 return;
904 }
905
906 D("client: connected on remote on fd %d\n", fd);
907 close_on_exec(fd);
908 disable_tcp_nagle(fd);
909 register_socket_transport(fd, serial, port, 0);
910 snprintf(buffer, buffer_size, "connected to %s", serial);
911}
912
913void connect_emulator(char* port_spec, char* buffer, int buffer_size)
914{
915 char* port_separator = strchr(port_spec, ',');
916 if (!port_separator) {
917 snprintf(buffer, buffer_size,
918 "unable to parse '%s' as <console port>,<adb port>",
919 port_spec);
920 return;
921 }
922
923 // Zero-terminate console port and make port_separator point to 2nd port.
924 *port_separator++ = 0;
925 int console_port = strtol(port_spec, NULL, 0);
926 int adb_port = strtol(port_separator, NULL, 0);
927 if (!(console_port > 0 && adb_port > 0)) {
928 *(port_separator - 1) = ',';
929 snprintf(buffer, buffer_size,
930 "Invalid port numbers: Expected positive numbers, got '%s'",
931 port_spec);
932 return;
933 }
934
935 /* Check if the emulator is already known.
936 * Note: There's a small but harmless race condition here: An emulator not
937 * present just yet could be registered by another invocation right
938 * after doing this check here. However, local_connect protects
939 * against double-registration too. From here, a better error message
940 * can be produced. In the case of the race condition, the very specific
941 * error message won't be shown, but the data doesn't get corrupted. */
942 atransport* known_emulator = find_emulator_transport_by_adb_port(adb_port);
943 if (known_emulator != NULL) {
944 snprintf(buffer, buffer_size,
945 "Emulator on port %d already registered.", adb_port);
946 return;
947 }
948
949 /* Check if more emulators can be registered. Similar unproblematic
950 * race condition as above. */
951 int candidate_slot = get_available_local_transport_index();
952 if (candidate_slot < 0) {
953 snprintf(buffer, buffer_size, "Cannot accept more emulators.");
954 return;
955 }
956
957 /* Preconditions met, try to connect to the emulator. */
958 if (!local_connect_arbitrary_ports(console_port, adb_port)) {
959 snprintf(buffer, buffer_size,
960 "Connected to emulator on ports %d,%d", console_port, adb_port);
961 } else {
962 snprintf(buffer, buffer_size,
963 "Could not connect to emulator on ports %d,%d",
964 console_port, adb_port);
965 }
966}
967#endif
968
969int handle_host_request(char *service, transport_type ttype, char* serial, int reply_fd, asocket *s)
970{
971 atransport *transport = NULL;
972 char buf[4096];
973
974 if(!strcmp(service, "kill")) {
975 fprintf(stderr,"adb server killed by remote request\n");
976 fflush(stdout);
977 adb_write(reply_fd, "OKAY", 4);
978 usb_cleanup();
979 exit(0);
980 }
981
982#if ADB_HOST
983 // "transport:" is used for switching transport with a specified serial number
984 // "transport-usb:" is used for switching transport to the only USB transport
985 // "transport-local:" is used for switching transport to the only local transport
986 // "transport-any:" is used for switching transport to the only transport
987 if (!strncmp(service, "transport", strlen("transport"))) {
988 char* error_string = "unknown failure";
989 transport_type type = kTransportAny;
990
991 if (!strncmp(service, "transport-usb", strlen("transport-usb"))) {
992 type = kTransportUsb;
993 } else if (!strncmp(service, "transport-local", strlen("transport-local"))) {
994 type = kTransportLocal;
995 } else if (!strncmp(service, "transport-any", strlen("transport-any"))) {
996 type = kTransportAny;
997 } else if (!strncmp(service, "transport:", strlen("transport:"))) {
998 service += strlen("transport:");
999 serial = service;
1000 }
1001
1002 transport = acquire_one_transport(CS_ANY, type, serial, &error_string);
1003
1004 if (transport) {
1005 s->transport = transport;
1006 adb_write(reply_fd, "OKAY", 4);
1007 } else {
1008 sendfailmsg(reply_fd, error_string);
1009 }
1010 return 1;
1011 }
1012
1013 // return a list of all connected devices
1014 if (!strcmp(service, "devices")) {
1015 char buffer[4096];
1016 memset(buf, 0, sizeof(buf));
1017 memset(buffer, 0, sizeof(buffer));
1018 D("Getting device list \n");
1019 list_transports(buffer, sizeof(buffer));
1020 snprintf(buf, sizeof(buf), "OKAY%04x%s",(unsigned)strlen(buffer),buffer);
1021 D("Wrote device list \n");
1022 writex(reply_fd, buf, strlen(buf));
1023 return 0;
1024 }
1025
1026 // add a new TCP transport, device or emulator
1027 if (!strncmp(service, "connect:", 8)) {
1028 char buffer[4096];
1029 char* host = service + 8;
1030 if (!strncmp(host, "emu:", 4)) {
1031 connect_emulator(host + 4, buffer, sizeof(buffer));
1032 } else {
1033 connect_device(host, buffer, sizeof(buffer));
1034 }
1035 // Send response for emulator and device
1036 snprintf(buf, sizeof(buf), "OKAY%04x%s",(unsigned)strlen(buffer), buffer);
1037 writex(reply_fd, buf, strlen(buf));
1038 return 0;
1039 }
1040
1041 // remove TCP transport
1042 if (!strncmp(service, "disconnect:", 11)) {
1043 char buffer[4096];
1044 memset(buffer, 0, sizeof(buffer));
1045 char* serial = service + 11;
1046 if (serial[0] == 0) {
1047 // disconnect from all TCP devices
1048 unregister_all_tcp_transports();
1049 } else {
1050 char hostbuf[100];
1051 // assume port 5555 if no port is specified
1052 if (!strchr(serial, ':')) {
1053 snprintf(hostbuf, sizeof(hostbuf) - 1, "%s:5555", serial);
1054 serial = hostbuf;
1055 }
1056 atransport *t = find_transport(serial);
1057
1058 if (t) {
1059 unregister_transport(t);
1060 } else {
1061 snprintf(buffer, sizeof(buffer), "No such device %s", serial);
1062 }
1063 }
1064
1065 snprintf(buf, sizeof(buf), "OKAY%04x%s",(unsigned)strlen(buffer), buffer);
1066 writex(reply_fd, buf, strlen(buf));
1067 return 0;
1068 }
1069
1070 // returns our value for ADB_SERVER_VERSION
1071 if (!strcmp(service, "version")) {
1072 char version[12];
1073 snprintf(version, sizeof version, "%04x", ADB_SERVER_VERSION);
1074 snprintf(buf, sizeof buf, "OKAY%04x%s", (unsigned)strlen(version), version);
1075 writex(reply_fd, buf, strlen(buf));
1076 return 0;
1077 }
1078
1079 if(!strncmp(service,"get-serialno",strlen("get-serialno"))) {
1080 char *out = "unknown";
1081 transport = acquire_one_transport(CS_ANY, ttype, serial, NULL);
1082 if (transport && transport->serial) {
1083 out = transport->serial;
1084 }
1085 snprintf(buf, sizeof buf, "OKAY%04x%s",(unsigned)strlen(out),out);
1086 writex(reply_fd, buf, strlen(buf));
1087 return 0;
1088 }
1089 // indicates a new emulator instance has started
1090 if (!strncmp(service,"emulator:",9)) {
1091 int port = atoi(service+9);
1092 local_connect(port);
1093 /* we don't even need to send a reply */
1094 return 0;
1095 }
1096#endif // ADB_HOST
1097
1098 if(!strncmp(service,"forward:",8) || !strncmp(service,"killforward:",12)) {
1099 char *local, *remote, *err;
1100 int r;
1101 atransport *transport;
1102
1103 int createForward = strncmp(service,"kill",4);
1104
1105 local = service + (createForward ? 8 : 12);
1106 remote = strchr(local,';');
1107 if(remote == 0) {
1108 sendfailmsg(reply_fd, "malformed forward spec");
1109 return 0;
1110 }
1111
1112 *remote++ = 0;
1113 if((local[0] == 0) || (remote[0] == 0) || (remote[0] == '*')){
1114 sendfailmsg(reply_fd, "malformed forward spec");
1115 return 0;
1116 }
1117
1118 transport = acquire_one_transport(CS_ANY, ttype, serial, &err);
1119 if (!transport) {
1120 sendfailmsg(reply_fd, err);
1121 return 0;
1122 }
1123
1124 if (createForward) {
1125 r = install_listener(local, remote, transport);
1126 } else {
1127 r = remove_listener(local, remote, transport);
1128 }
1129 if(r == 0) {
1130 /* 1st OKAY is connect, 2nd OKAY is status */
1131 writex(reply_fd, "OKAYOKAY", 8);
1132 return 0;
1133 }
1134
1135 if (createForward) {
1136 sendfailmsg(reply_fd, (r == -1) ? "cannot rebind smartsocket" : "cannot bind socket");
1137 } else {
1138 sendfailmsg(reply_fd, "cannot remove listener");
1139 }
1140 return 0;
1141 }
1142
1143 if(!strncmp(service,"get-state",strlen("get-state"))) {
1144 transport = acquire_one_transport(CS_ANY, ttype, serial, NULL);
1145 char *state = connection_state_name(transport);
1146 snprintf(buf, sizeof buf, "OKAY%04x%s",(unsigned)strlen(state),state);
1147 writex(reply_fd, buf, strlen(buf));
1148 return 0;
1149 }
1150 return -1;
1151}
diff --git a/minadbd/adb.h b/minadbd/adb.h
new file mode 100644
index 00000000..a989edda
--- /dev/null
+++ b/minadbd/adb.h
@@ -0,0 +1,443 @@
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#ifndef __ADB_H
18#define __ADB_H
19
20#include <limits.h>
21
22#include "transport.h" /* readx(), writex() */
23#include "fdevent.h"
24
25#define MAX_PAYLOAD 4096
26
27#define A_SYNC 0x434e5953
28#define A_CNXN 0x4e584e43
29#define A_OPEN 0x4e45504f
30#define A_OKAY 0x59414b4f
31#define A_CLSE 0x45534c43
32#define A_WRTE 0x45545257
33
34#define A_VERSION 0x01000000 // ADB protocol version
35
36#define ADB_VERSION_MAJOR 1 // Used for help/version information
37#define ADB_VERSION_MINOR 0 // Used for help/version information
38
39#define ADB_SERVER_VERSION 29 // Increment this when we want to force users to start a new adb server
40
41typedef struct amessage amessage;
42typedef struct apacket apacket;
43typedef struct asocket asocket;
44typedef struct alistener alistener;
45typedef struct aservice aservice;
46typedef struct atransport atransport;
47typedef struct adisconnect adisconnect;
48typedef struct usb_handle usb_handle;
49
50struct amessage {
51 unsigned command; /* command identifier constant */
52 unsigned arg0; /* first argument */
53 unsigned arg1; /* second argument */
54 unsigned data_length; /* length of payload (0 is allowed) */
55 unsigned data_check; /* checksum of data payload */
56 unsigned magic; /* command ^ 0xffffffff */
57};
58
59struct apacket
60{
61 apacket *next;
62
63 unsigned len;
64 unsigned char *ptr;
65
66 amessage msg;
67 unsigned char data[MAX_PAYLOAD];
68};
69
70/* An asocket represents one half of a connection between a local and
71** remote entity. A local asocket is bound to a file descriptor. A
72** remote asocket is bound to the protocol engine.
73*/
74struct asocket {
75 /* chain pointers for the local/remote list of
76 ** asockets that this asocket lives in
77 */
78 asocket *next;
79 asocket *prev;
80
81 /* the unique identifier for this asocket
82 */
83 unsigned id;
84
85 /* flag: set when the socket's peer has closed
86 ** but packets are still queued for delivery
87 */
88 int closing;
89
90 /* the asocket we are connected to
91 */
92
93 asocket *peer;
94
95 /* For local asockets, the fde is used to bind
96 ** us to our fd event system. For remote asockets
97 ** these fields are not used.
98 */
99 fdevent fde;
100 int fd;
101
102 /* queue of apackets waiting to be written
103 */
104 apacket *pkt_first;
105 apacket *pkt_last;
106
107 /* enqueue is called by our peer when it has data
108 ** for us. It should return 0 if we can accept more
109 ** data or 1 if not. If we return 1, we must call
110 ** peer->ready() when we once again are ready to
111 ** receive data.
112 */
113 int (*enqueue)(asocket *s, apacket *pkt);
114
115 /* ready is called by the peer when it is ready for
116 ** us to send data via enqueue again
117 */
118 void (*ready)(asocket *s);
119
120 /* close is called by the peer when it has gone away.
121 ** we are not allowed to make any further calls on the
122 ** peer once our close method is called.
123 */
124 void (*close)(asocket *s);
125
126 /* socket-type-specific extradata */
127 void *extra;
128
129 /* A socket is bound to atransport */
130 atransport *transport;
131};
132
133
134/* the adisconnect structure is used to record a callback that
135** will be called whenever a transport is disconnected (e.g. by the user)
136** this should be used to cleanup objects that depend on the
137** transport (e.g. remote sockets, listeners, etc...)
138*/
139struct adisconnect
140{
141 void (*func)(void* opaque, atransport* t);
142 void* opaque;
143 adisconnect* next;
144 adisconnect* prev;
145};
146
147
148/* a transport object models the connection to a remote device or emulator
149** there is one transport per connected device/emulator. a "local transport"
150** connects through TCP (for the emulator), while a "usb transport" through
151** USB (for real devices)
152**
153** note that kTransportHost doesn't really correspond to a real transport
154** object, it's a special value used to indicate that a client wants to
155** connect to a service implemented within the ADB server itself.
156*/
157typedef enum transport_type {
158 kTransportUsb,
159 kTransportLocal,
160 kTransportAny,
161 kTransportHost,
162} transport_type;
163
164struct atransport
165{
166 atransport *next;
167 atransport *prev;
168
169 int (*read_from_remote)(apacket *p, atransport *t);
170 int (*write_to_remote)(apacket *p, atransport *t);
171 void (*close)(atransport *t);
172 void (*kick)(atransport *t);
173
174 int fd;
175 int transport_socket;
176 fdevent transport_fde;
177 int ref_count;
178 unsigned sync_token;
179 int connection_state;
180 transport_type type;
181
182 /* usb handle or socket fd as needed */
183 usb_handle *usb;
184 int sfd;
185
186 /* used to identify transports for clients */
187 char *serial;
188 char *product;
189 int adb_port; // Use for emulators (local transport)
190
191 /* a list of adisconnect callbacks called when the transport is kicked */
192 int kicked;
193 adisconnect disconnects;
194};
195
196
197/* A listener is an entity which binds to a local port
198** and, upon receiving a connection on that port, creates
199** an asocket to connect the new local connection to a
200** specific remote service.
201**
202** TODO: some listeners read from the new connection to
203** determine what exact service to connect to on the far
204** side.
205*/
206struct alistener
207{
208 alistener *next;
209 alistener *prev;
210
211 fdevent fde;
212 int fd;
213
214 const char *local_name;
215 const char *connect_to;
216 atransport *transport;
217 adisconnect disconnect;
218};
219
220
221void print_packet(const char *label, apacket *p);
222
223asocket *find_local_socket(unsigned id);
224void install_local_socket(asocket *s);
225void remove_socket(asocket *s);
226void close_all_sockets(atransport *t);
227
228#define LOCAL_CLIENT_PREFIX "emulator-"
229
230asocket *create_local_socket(int fd);
231asocket *create_local_service_socket(const char *destination);
232
233asocket *create_remote_socket(unsigned id, atransport *t);
234void connect_to_remote(asocket *s, const char *destination);
235void connect_to_smartsocket(asocket *s);
236
237void fatal(const char *fmt, ...);
238void fatal_errno(const char *fmt, ...);
239
240void handle_packet(apacket *p, atransport *t);
241void send_packet(apacket *p, atransport *t);
242
243void get_my_path(char *s, size_t maxLen);
244int launch_server(int server_port);
245int adb_main();
246
247
248/* transports are ref-counted
249** get_device_transport does an acquire on your behalf before returning
250*/
251void init_transport_registration(void);
252int list_transports(char *buf, size_t bufsize);
253void update_transports(void);
254
255asocket* create_device_tracker(void);
256
257/* Obtain a transport from the available transports.
258** If state is != CS_ANY, only transports in that state are considered.
259** If serial is non-NULL then only the device with that serial will be chosen.
260** If no suitable transport is found, error is set.
261*/
262atransport *acquire_one_transport(int state, transport_type ttype, const char* serial, char **error_out);
263void add_transport_disconnect( atransport* t, adisconnect* dis );
264void remove_transport_disconnect( atransport* t, adisconnect* dis );
265void run_transport_disconnects( atransport* t );
266void kick_transport( atransport* t );
267
268/* initialize a transport object's func pointers and state */
269#if ADB_HOST
270int get_available_local_transport_index();
271#endif
272int init_socket_transport(atransport *t, int s, int port, int local);
273void init_usb_transport(atransport *t, usb_handle *usb, int state);
274
275/* for MacOS X cleanup */
276void close_usb_devices();
277
278/* cause new transports to be init'd and added to the list */
279void register_socket_transport(int s, const char *serial, int port, int local);
280
281/* these should only be used for the "adb disconnect" command */
282void unregister_transport(atransport *t);
283void unregister_all_tcp_transports();
284
285void register_usb_transport(usb_handle *h, const char *serial, unsigned writeable);
286
287/* this should only be used for transports with connection_state == CS_NOPERM */
288void unregister_usb_transport(usb_handle *usb);
289
290atransport *find_transport(const char *serial);
291#if ADB_HOST
292atransport* find_emulator_transport_by_adb_port(int adb_port);
293#endif
294
295int service_to_fd(const char *name);
296#if ADB_HOST
297asocket *host_service_to_socket(const char* name, const char *serial);
298#endif
299
300#if !ADB_HOST
301typedef enum {
302 BACKUP,
303 RESTORE
304} BackupOperation;
305int backup_service(BackupOperation operation, char* args);
306void framebuffer_service(int fd, void *cookie);
307void log_service(int fd, void *cookie);
308void remount_service(int fd, void *cookie);
309char * get_log_file_path(const char * log_name);
310#endif
311
312/* packet allocator */
313apacket *get_apacket(void);
314void put_apacket(apacket *p);
315
316int check_header(apacket *p);
317int check_data(apacket *p);
318
319/* define ADB_TRACE to 1 to enable tracing support, or 0 to disable it */
320
321#define ADB_TRACE 1
322
323/* IMPORTANT: if you change the following list, don't
324 * forget to update the corresponding 'tags' table in
325 * the adb_trace_init() function implemented in adb.c
326 */
327typedef enum {
328 TRACE_ADB = 0, /* 0x001 */
329 TRACE_SOCKETS,
330 TRACE_PACKETS,
331 TRACE_TRANSPORT,
332 TRACE_RWX, /* 0x010 */
333 TRACE_USB,
334 TRACE_SYNC,
335 TRACE_SYSDEPS,
336 TRACE_JDWP, /* 0x100 */
337 TRACE_SERVICES,
338} AdbTrace;
339
340#if ADB_TRACE
341
342 extern int adb_trace_mask;
343 extern unsigned char adb_trace_output_count;
344 void adb_trace_init(void);
345
346# define ADB_TRACING ((adb_trace_mask & (1 << TRACE_TAG)) != 0)
347
348 /* you must define TRACE_TAG before using this macro */
349# define D(...) \
350 do { \
351 if (ADB_TRACING) { \
352 int save_errno = errno; \
353 adb_mutex_lock(&D_lock); \
354 fprintf(stderr, "%s::%s():", \
355 __FILE__, __FUNCTION__); \
356 errno = save_errno; \
357 fprintf(stderr, __VA_ARGS__ ); \
358 fflush(stderr); \
359 adb_mutex_unlock(&D_lock); \
360 errno = save_errno; \
361 } \
362 } while (0)
363# define DR(...) \
364 do { \
365 if (ADB_TRACING) { \
366 int save_errno = errno; \
367 adb_mutex_lock(&D_lock); \
368 errno = save_errno; \
369 fprintf(stderr, __VA_ARGS__ ); \
370 fflush(stderr); \
371 adb_mutex_unlock(&D_lock); \
372 errno = save_errno; \
373 } \
374 } while (0)
375#else
376# define D(...) ((void)0)
377# define DR(...) ((void)0)
378# define ADB_TRACING 0
379#endif
380
381
382#if !TRACE_PACKETS
383#define print_packet(tag,p) do {} while (0)
384#endif
385
386#if ADB_HOST_ON_TARGET
387/* adb and adbd are coexisting on the target, so use 5038 for adb
388 * to avoid conflicting with adbd's usage of 5037
389 */
390# define DEFAULT_ADB_PORT 5038
391#else
392# define DEFAULT_ADB_PORT 5037
393#endif
394
395#define DEFAULT_ADB_LOCAL_TRANSPORT_PORT 5555
396
397#define ADB_CLASS 0xff
398#define ADB_SUBCLASS 0x42
399#define ADB_PROTOCOL 0x1
400
401
402void local_init(int port);
403int local_connect(int port);
404int local_connect_arbitrary_ports(int console_port, int adb_port);
405
406/* usb host/client interface */
407void usb_init();
408void usb_cleanup();
409int usb_write(usb_handle *h, const void *data, int len);
410int usb_read(usb_handle *h, void *data, int len);
411int usb_close(usb_handle *h);
412void usb_kick(usb_handle *h);
413
414/* used for USB device detection */
415#if ADB_HOST
416int is_adb_interface(int vid, int pid, int usb_class, int usb_subclass, int usb_protocol);
417#endif
418
419unsigned host_to_le32(unsigned n);
420int adb_commandline(int argc, char **argv);
421
422int connection_state(atransport *t);
423
424#define CS_ANY -1
425#define CS_OFFLINE 0
426#define CS_BOOTLOADER 1
427#define CS_DEVICE 2
428#define CS_HOST 3
429#define CS_RECOVERY 4
430#define CS_NOPERM 5 /* Insufficient permissions to communicate with the device */
431#define CS_SIDELOAD 6
432
433extern int HOST;
434extern int SHELL_EXIT_NOTIFY_FD;
435
436#define CHUNK_SIZE (64*1024)
437
438int sendfailmsg(int fd, const char *reason);
439int handle_host_request(char *service, transport_type ttype, char* serial, int reply_fd, asocket *s);
440
441#define ADB_SIDELOAD_FILENAME "/tmp/update.zip"
442
443#endif
diff --git a/minadbd/fdevent.c b/minadbd/fdevent.c
new file mode 100644
index 00000000..5c374a71
--- /dev/null
+++ b/minadbd/fdevent.c
@@ -0,0 +1,695 @@
1/* http://frotznet.googlecode.com/svn/trunk/utils/fdevent.c
2**
3** Copyright 2006, Brian Swetland <swetland@frotz.net>
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18#include <sys/ioctl.h>
19
20#include <stdlib.h>
21#include <stdio.h>
22#include <string.h>
23#include <unistd.h>
24#include <errno.h>
25
26#include <fcntl.h>
27
28#include <stdarg.h>
29#include <stddef.h>
30
31#include "fdevent.h"
32#include "transport.h"
33#include "sysdeps.h"
34
35
36/* !!! Do not enable DEBUG for the adb that will run as the server:
37** both stdout and stderr are used to communicate between the client
38** and server. Any extra output will cause failures.
39*/
40#define DEBUG 0 /* non-0 will break adb server */
41
42// This socket is used when a subproc shell service exists.
43// It wakes up the fdevent_loop() and cause the correct handling
44// of the shell's pseudo-tty master. I.e. force close it.
45int SHELL_EXIT_NOTIFY_FD = -1;
46
47static void fatal(const char *fn, const char *fmt, ...)
48{
49 va_list ap;
50 va_start(ap, fmt);
51 fprintf(stderr, "%s:", fn);
52 vfprintf(stderr, fmt, ap);
53 va_end(ap);
54 abort();
55}
56
57#define FATAL(x...) fatal(__FUNCTION__, x)
58
59#if DEBUG
60#define D(...) \
61 do { \
62 adb_mutex_lock(&D_lock); \
63 int save_errno = errno; \
64 fprintf(stderr, "%s::%s():", __FILE__, __FUNCTION__); \
65 errno = save_errno; \
66 fprintf(stderr, __VA_ARGS__); \
67 adb_mutex_unlock(&D_lock); \
68 errno = save_errno; \
69 } while(0)
70static void dump_fde(fdevent *fde, const char *info)
71{
72 adb_mutex_lock(&D_lock);
73 fprintf(stderr,"FDE #%03d %c%c%c %s\n", fde->fd,
74 fde->state & FDE_READ ? 'R' : ' ',
75 fde->state & FDE_WRITE ? 'W' : ' ',
76 fde->state & FDE_ERROR ? 'E' : ' ',
77 info);
78 adb_mutex_unlock(&D_lock);
79}
80#else
81#define D(...) ((void)0)
82#define dump_fde(fde, info) do { } while(0)
83#endif
84
85#define FDE_EVENTMASK 0x00ff
86#define FDE_STATEMASK 0xff00
87
88#define FDE_ACTIVE 0x0100
89#define FDE_PENDING 0x0200
90#define FDE_CREATED 0x0400
91
92static void fdevent_plist_enqueue(fdevent *node);
93static void fdevent_plist_remove(fdevent *node);
94static fdevent *fdevent_plist_dequeue(void);
95static void fdevent_subproc_event_func(int fd, unsigned events, void *userdata);
96
97static fdevent list_pending = {
98 .next = &list_pending,
99 .prev = &list_pending,
100};
101
102static fdevent **fd_table = 0;
103static int fd_table_max = 0;
104
105#ifdef CRAPTASTIC
106//HAVE_EPOLL
107
108#include <sys/epoll.h>
109
110static int epoll_fd = -1;
111
112static void fdevent_init()
113{
114 /* XXX: what's a good size for the passed in hint? */
115 epoll_fd = epoll_create(256);
116
117 if(epoll_fd < 0) {
118 perror("epoll_create() failed");
119 exit(1);
120 }
121
122 /* mark for close-on-exec */
123 fcntl(epoll_fd, F_SETFD, FD_CLOEXEC);
124}
125
126static void fdevent_connect(fdevent *fde)
127{
128 struct epoll_event ev;
129
130 memset(&ev, 0, sizeof(ev));
131 ev.events = 0;
132 ev.data.ptr = fde;
133
134#if 0
135 if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fde->fd, &ev)) {
136 perror("epoll_ctl() failed\n");
137 exit(1);
138 }
139#endif
140}
141
142static void fdevent_disconnect(fdevent *fde)
143{
144 struct epoll_event ev;
145
146 memset(&ev, 0, sizeof(ev));
147 ev.events = 0;
148 ev.data.ptr = fde;
149
150 /* technically we only need to delete if we
151 ** were actively monitoring events, but let's
152 ** be aggressive and do it anyway, just in case
153 ** something's out of sync
154 */
155 epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fde->fd, &ev);
156}
157
158static void fdevent_update(fdevent *fde, unsigned events)
159{
160 struct epoll_event ev;
161 int active;
162
163 active = (fde->state & FDE_EVENTMASK) != 0;
164
165 memset(&ev, 0, sizeof(ev));
166 ev.events = 0;
167 ev.data.ptr = fde;
168
169 if(events & FDE_READ) ev.events |= EPOLLIN;
170 if(events & FDE_WRITE) ev.events |= EPOLLOUT;
171 if(events & FDE_ERROR) ev.events |= (EPOLLERR | EPOLLHUP);
172
173 fde->state = (fde->state & FDE_STATEMASK) | events;
174
175 if(active) {
176 /* we're already active. if we're changing to *no*
177 ** events being monitored, we need to delete, otherwise
178 ** we need to just modify
179 */
180 if(ev.events) {
181 if(epoll_ctl(epoll_fd, EPOLL_CTL_MOD, fde->fd, &ev)) {
182 perror("epoll_ctl() failed\n");
183 exit(1);
184 }
185 } else {
186 if(epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fde->fd, &ev)) {
187 perror("epoll_ctl() failed\n");
188 exit(1);
189 }
190 }
191 } else {
192 /* we're not active. if we're watching events, we need
193 ** to add, otherwise we can just do nothing
194 */
195 if(ev.events) {
196 if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fde->fd, &ev)) {
197 perror("epoll_ctl() failed\n");
198 exit(1);
199 }
200 }
201 }
202}
203
204static void fdevent_process()
205{
206 struct epoll_event events[256];
207 fdevent *fde;
208 int i, n;
209
210 n = epoll_wait(epoll_fd, events, 256, -1);
211
212 if(n < 0) {
213 if(errno == EINTR) return;
214 perror("epoll_wait");
215 exit(1);
216 }
217
218 for(i = 0; i < n; i++) {
219 struct epoll_event *ev = events + i;
220 fde = ev->data.ptr;
221
222 if(ev->events & EPOLLIN) {
223 fde->events |= FDE_READ;
224 }
225 if(ev->events & EPOLLOUT) {
226 fde->events |= FDE_WRITE;
227 }
228 if(ev->events & (EPOLLERR | EPOLLHUP)) {
229 fde->events |= FDE_ERROR;
230 }
231 if(fde->events) {
232 if(fde->state & FDE_PENDING) continue;
233 fde->state |= FDE_PENDING;
234 fdevent_plist_enqueue(fde);
235 }
236 }
237}
238
239#else /* USE_SELECT */
240
241#ifdef HAVE_WINSOCK
242#include <winsock2.h>
243#else
244#include <sys/select.h>
245#endif
246
247static fd_set read_fds;
248static fd_set write_fds;
249static fd_set error_fds;
250
251static int select_n = 0;
252
253static void fdevent_init(void)
254{
255 FD_ZERO(&read_fds);
256 FD_ZERO(&write_fds);
257 FD_ZERO(&error_fds);
258}
259
260static void fdevent_connect(fdevent *fde)
261{
262 if(fde->fd >= select_n) {
263 select_n = fde->fd + 1;
264 }
265}
266
267static void fdevent_disconnect(fdevent *fde)
268{
269 int i, n;
270
271 FD_CLR(fde->fd, &read_fds);
272 FD_CLR(fde->fd, &write_fds);
273 FD_CLR(fde->fd, &error_fds);
274
275 for(n = 0, i = 0; i < select_n; i++) {
276 if(fd_table[i] != 0) n = i;
277 }
278 select_n = n + 1;
279}
280
281static void fdevent_update(fdevent *fde, unsigned events)
282{
283 if(events & FDE_READ) {
284 FD_SET(fde->fd, &read_fds);
285 } else {
286 FD_CLR(fde->fd, &read_fds);
287 }
288 if(events & FDE_WRITE) {
289 FD_SET(fde->fd, &write_fds);
290 } else {
291 FD_CLR(fde->fd, &write_fds);
292 }
293 if(events & FDE_ERROR) {
294 FD_SET(fde->fd, &error_fds);
295 } else {
296 FD_CLR(fde->fd, &error_fds);
297 }
298
299 fde->state = (fde->state & FDE_STATEMASK) | events;
300}
301
302/* Looks at fd_table[] for bad FDs and sets bit in fds.
303** Returns the number of bad FDs.
304*/
305static int fdevent_fd_check(fd_set *fds)
306{
307 int i, n = 0;
308 fdevent *fde;
309
310 for(i = 0; i < select_n; i++) {
311 fde = fd_table[i];
312 if(fde == 0) continue;
313 if(fcntl(i, F_GETFL, NULL) < 0) {
314 FD_SET(i, fds);
315 n++;
316 // fde->state |= FDE_DONT_CLOSE;
317
318 }
319 }
320 return n;
321}
322
323#if !DEBUG
324static inline void dump_all_fds(const char *extra_msg) {}
325#else
326static void dump_all_fds(const char *extra_msg)
327{
328int i;
329 fdevent *fde;
330 // per fd: 4 digits (but really: log10(FD_SETSIZE)), 1 staus, 1 blank
331 char msg_buff[FD_SETSIZE*6 + 1], *pb=msg_buff;
332 size_t max_chars = FD_SETSIZE * 6 + 1;
333 int printed_out;
334#define SAFE_SPRINTF(...) \
335 do { \
336 printed_out = snprintf(pb, max_chars, __VA_ARGS__); \
337 if (printed_out <= 0) { \
338 D("... snprintf failed.\n"); \
339 return; \
340 } \
341 if (max_chars < (unsigned int)printed_out) { \
342 D("... snprintf out of space.\n"); \
343 return; \
344 } \
345 pb += printed_out; \
346 max_chars -= printed_out; \
347 } while(0)
348
349 for(i = 0; i < select_n; i++) {
350 fde = fd_table[i];
351 SAFE_SPRINTF("%d", i);
352 if(fde == 0) {
353 SAFE_SPRINTF("? ");
354 continue;
355 }
356 if(fcntl(i, F_GETFL, NULL) < 0) {
357 SAFE_SPRINTF("b");
358 }
359 SAFE_SPRINTF(" ");
360 }
361 D("%s fd_table[]->fd = {%s}\n", extra_msg, msg_buff);
362}
363#endif
364
365static void fdevent_process()
366{
367 int i, n;
368 fdevent *fde;
369 unsigned events;
370 fd_set rfd, wfd, efd;
371
372 memcpy(&rfd, &read_fds, sizeof(fd_set));
373 memcpy(&wfd, &write_fds, sizeof(fd_set));
374 memcpy(&efd, &error_fds, sizeof(fd_set));
375
376 dump_all_fds("pre select()");
377
378 n = select(select_n, &rfd, &wfd, &efd, NULL);
379 int saved_errno = errno;
380 D("select() returned n=%d, errno=%d\n", n, n<0?saved_errno:0);
381
382 dump_all_fds("post select()");
383
384 if(n < 0) {
385 switch(saved_errno) {
386 case EINTR: return;
387 case EBADF:
388 // Can't trust the FD sets after an error.
389 FD_ZERO(&wfd);
390 FD_ZERO(&efd);
391 FD_ZERO(&rfd);
392 break;
393 default:
394 D("Unexpected select() error=%d\n", saved_errno);
395 return;
396 }
397 }
398 if(n <= 0) {
399 // We fake a read, as the rest of the code assumes
400 // that errors will be detected at that point.
401 n = fdevent_fd_check(&rfd);
402 }
403
404 for(i = 0; (i < select_n) && (n > 0); i++) {
405 events = 0;
406 if(FD_ISSET(i, &rfd)) { events |= FDE_READ; n--; }
407 if(FD_ISSET(i, &wfd)) { events |= FDE_WRITE; n--; }
408 if(FD_ISSET(i, &efd)) { events |= FDE_ERROR; n--; }
409
410 if(events) {
411 fde = fd_table[i];
412 if(fde == 0)
413 FATAL("missing fde for fd %d\n", i);
414
415 fde->events |= events;
416
417 D("got events fde->fd=%d events=%04x, state=%04x\n",
418 fde->fd, fde->events, fde->state);
419 if(fde->state & FDE_PENDING) continue;
420 fde->state |= FDE_PENDING;
421 fdevent_plist_enqueue(fde);
422 }
423 }
424}
425
426#endif
427
428static void fdevent_register(fdevent *fde)
429{
430 if(fde->fd < 0) {
431 FATAL("bogus negative fd (%d)\n", fde->fd);
432 }
433
434 if(fde->fd >= fd_table_max) {
435 int oldmax = fd_table_max;
436 if(fde->fd > 32000) {
437 FATAL("bogus huuuuge fd (%d)\n", fde->fd);
438 }
439 if(fd_table_max == 0) {
440 fdevent_init();
441 fd_table_max = 256;
442 }
443 while(fd_table_max <= fde->fd) {
444 fd_table_max *= 2;
445 }
446 fd_table = realloc(fd_table, sizeof(fdevent*) * fd_table_max);
447 if(fd_table == 0) {
448 FATAL("could not expand fd_table to %d entries\n", fd_table_max);
449 }
450 memset(fd_table + oldmax, 0, sizeof(int) * (fd_table_max - oldmax));
451 }
452
453 fd_table[fde->fd] = fde;
454}
455
456static void fdevent_unregister(fdevent *fde)
457{
458 if((fde->fd < 0) || (fde->fd >= fd_table_max)) {
459 FATAL("fd out of range (%d)\n", fde->fd);
460 }
461
462 if(fd_table[fde->fd] != fde) {
463 FATAL("fd_table out of sync [%d]\n", fde->fd);
464 }
465
466 fd_table[fde->fd] = 0;
467
468 if(!(fde->state & FDE_DONT_CLOSE)) {
469 dump_fde(fde, "close");
470 adb_close(fde->fd);
471 }
472}
473
474static void fdevent_plist_enqueue(fdevent *node)
475{
476 fdevent *list = &list_pending;
477
478 node->next = list;
479 node->prev = list->prev;
480 node->prev->next = node;
481 list->prev = node;
482}
483
484static void fdevent_plist_remove(fdevent *node)
485{
486 node->prev->next = node->next;
487 node->next->prev = node->prev;
488 node->next = 0;
489 node->prev = 0;
490}
491
492static fdevent *fdevent_plist_dequeue(void)
493{
494 fdevent *list = &list_pending;
495 fdevent *node = list->next;
496
497 if(node == list) return 0;
498
499 list->next = node->next;
500 list->next->prev = list;
501 node->next = 0;
502 node->prev = 0;
503
504 return node;
505}
506
507static void fdevent_call_fdfunc(fdevent* fde)
508{
509 unsigned events = fde->events;
510 fde->events = 0;
511 if(!(fde->state & FDE_PENDING)) return;
512 fde->state &= (~FDE_PENDING);
513 dump_fde(fde, "callback");
514 fde->func(fde->fd, events, fde->arg);
515}
516
517static void fdevent_subproc_event_func(int fd, unsigned ev, void *userdata)
518{
519
520 D("subproc handling on fd=%d ev=%04x\n", fd, ev);
521
522 // Hook oneself back into the fde's suitable for select() on read.
523 if((fd < 0) || (fd >= fd_table_max)) {
524 FATAL("fd %d out of range for fd_table \n", fd);
525 }
526 fdevent *fde = fd_table[fd];
527 fdevent_add(fde, FDE_READ);
528
529 if(ev & FDE_READ){
530 int subproc_fd;
531
532 if(readx(fd, &subproc_fd, sizeof(subproc_fd))) {
533 FATAL("Failed to read the subproc's fd from fd=%d\n", fd);
534 }
535 if((subproc_fd < 0) || (subproc_fd >= fd_table_max)) {
536 D("subproc_fd %d out of range 0, fd_table_max=%d\n",
537 subproc_fd, fd_table_max);
538 return;
539 }
540 fdevent *subproc_fde = fd_table[subproc_fd];
541 if(!subproc_fde) {
542 D("subproc_fd %d cleared from fd_table\n", subproc_fd);
543 return;
544 }
545 if(subproc_fde->fd != subproc_fd) {
546 // Already reallocated?
547 D("subproc_fd %d != fd_table[].fd %d\n", subproc_fd, subproc_fde->fd);
548 return;
549 }
550
551 subproc_fde->force_eof = 1;
552
553 int rcount = 0;
554 ioctl(subproc_fd, FIONREAD, &rcount);
555 D("subproc with fd=%d has rcount=%d err=%d\n",
556 subproc_fd, rcount, errno);
557
558 if(rcount) {
559 // If there is data left, it will show up in the select().
560 // This works because there is no other thread reading that
561 // data when in this fd_func().
562 return;
563 }
564
565 D("subproc_fde.state=%04x\n", subproc_fde->state);
566 subproc_fde->events |= FDE_READ;
567 if(subproc_fde->state & FDE_PENDING) {
568 return;
569 }
570 subproc_fde->state |= FDE_PENDING;
571 fdevent_call_fdfunc(subproc_fde);
572 }
573}
574
575fdevent *fdevent_create(int fd, fd_func func, void *arg)
576{
577 fdevent *fde = (fdevent*) malloc(sizeof(fdevent));
578 if(fde == 0) return 0;
579 fdevent_install(fde, fd, func, arg);
580 fde->state |= FDE_CREATED;
581 return fde;
582}
583
584void fdevent_destroy(fdevent *fde)
585{
586 if(fde == 0) return;
587 if(!(fde->state & FDE_CREATED)) {
588 FATAL("fde %p not created by fdevent_create()\n", fde);
589 }
590 fdevent_remove(fde);
591}
592
593void fdevent_install(fdevent *fde, int fd, fd_func func, void *arg)
594{
595 memset(fde, 0, sizeof(fdevent));
596 fde->state = FDE_ACTIVE;
597 fde->fd = fd;
598 fde->force_eof = 0;
599 fde->func = func;
600 fde->arg = arg;
601
602#ifndef HAVE_WINSOCK
603 fcntl(fd, F_SETFL, O_NONBLOCK);
604#endif
605 fdevent_register(fde);
606 dump_fde(fde, "connect");
607 fdevent_connect(fde);
608 fde->state |= FDE_ACTIVE;
609}
610
611void fdevent_remove(fdevent *fde)
612{
613 if(fde->state & FDE_PENDING) {
614 fdevent_plist_remove(fde);
615 }
616
617 if(fde->state & FDE_ACTIVE) {
618 fdevent_disconnect(fde);
619 dump_fde(fde, "disconnect");
620 fdevent_unregister(fde);
621 }
622
623 fde->state = 0;
624 fde->events = 0;
625}
626
627
628void fdevent_set(fdevent *fde, unsigned events)
629{
630 events &= FDE_EVENTMASK;
631
632 if((fde->state & FDE_EVENTMASK) == events) return;
633
634 if(fde->state & FDE_ACTIVE) {
635 fdevent_update(fde, events);
636 dump_fde(fde, "update");
637 }
638
639 fde->state = (fde->state & FDE_STATEMASK) | events;
640
641 if(fde->state & FDE_PENDING) {
642 /* if we're pending, make sure
643 ** we don't signal an event that
644 ** is no longer wanted.
645 */
646 fde->events &= (~events);
647 if(fde->events == 0) {
648 fdevent_plist_remove(fde);
649 fde->state &= (~FDE_PENDING);
650 }
651 }
652}
653
654void fdevent_add(fdevent *fde, unsigned events)
655{
656 fdevent_set(
657 fde, (fde->state & FDE_EVENTMASK) | (events & FDE_EVENTMASK));
658}
659
660void fdevent_del(fdevent *fde, unsigned events)
661{
662 fdevent_set(
663 fde, (fde->state & FDE_EVENTMASK) & (~(events & FDE_EVENTMASK)));
664}
665
666void fdevent_subproc_setup()
667{
668 int s[2];
669
670 if(adb_socketpair(s)) {
671 FATAL("cannot create shell-exit socket-pair\n");
672 }
673 SHELL_EXIT_NOTIFY_FD = s[0];
674 fdevent *fde;
675 fde = fdevent_create(s[1], fdevent_subproc_event_func, NULL);
676 if(!fde)
677 FATAL("cannot create fdevent for shell-exit handler\n");
678 fdevent_add(fde, FDE_READ);
679}
680
681void fdevent_loop()
682{
683 fdevent *fde;
684 fdevent_subproc_setup();
685
686 for(;;) {
687 D("--- ---- waiting for events\n");
688
689 fdevent_process();
690
691 while((fde = fdevent_plist_dequeue())) {
692 fdevent_call_fdfunc(fde);
693 }
694 }
695}
diff --git a/minadbd/fdevent.h b/minadbd/fdevent.h
new file mode 100644
index 00000000..a0ebe2a7
--- /dev/null
+++ b/minadbd/fdevent.h
@@ -0,0 +1,83 @@
1/*
2 * Copyright (C) 2006 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#ifndef __FDEVENT_H
18#define __FDEVENT_H
19
20#include <stdint.h> /* for int64_t */
21
22/* events that may be observed */
23#define FDE_READ 0x0001
24#define FDE_WRITE 0x0002
25#define FDE_ERROR 0x0004
26#define FDE_TIMEOUT 0x0008
27
28/* features that may be set (via the events set/add/del interface) */
29#define FDE_DONT_CLOSE 0x0080
30
31typedef struct fdevent fdevent;
32
33typedef void (*fd_func)(int fd, unsigned events, void *userdata);
34
35/* Allocate and initialize a new fdevent object
36 * Note: use FD_TIMER as 'fd' to create a fd-less object
37 * (used to implement timers).
38*/
39fdevent *fdevent_create(int fd, fd_func func, void *arg);
40
41/* Uninitialize and deallocate an fdevent object that was
42** created by fdevent_create()
43*/
44void fdevent_destroy(fdevent *fde);
45
46/* Initialize an fdevent object that was externally allocated
47*/
48void fdevent_install(fdevent *fde, int fd, fd_func func, void *arg);
49
50/* Uninitialize an fdevent object that was initialized by
51** fdevent_install()
52*/
53void fdevent_remove(fdevent *item);
54
55/* Change which events should cause notifications
56*/
57void fdevent_set(fdevent *fde, unsigned events);
58void fdevent_add(fdevent *fde, unsigned events);
59void fdevent_del(fdevent *fde, unsigned events);
60
61void fdevent_set_timeout(fdevent *fde, int64_t timeout_ms);
62
63/* loop forever, handling events.
64*/
65void fdevent_loop();
66
67struct fdevent
68{
69 fdevent *next;
70 fdevent *prev;
71
72 int fd;
73 int force_eof;
74
75 unsigned short state;
76 unsigned short events;
77
78 fd_func func;
79 void *arg;
80};
81
82
83#endif
diff --git a/minadbd/mutex_list.h b/minadbd/mutex_list.h
new file mode 100644
index 00000000..652dd734
--- /dev/null
+++ b/minadbd/mutex_list.h
@@ -0,0 +1,26 @@
1/* the list of mutexes used by adb */
2/* #ifndef __MUTEX_LIST_H
3 * Do not use an include-guard. This file is included once to declare the locks
4 * and once in win32 to actually do the runtime initialization.
5 */
6#ifndef ADB_MUTEX
7#error ADB_MUTEX not defined when including this file
8#endif
9ADB_MUTEX(dns_lock)
10ADB_MUTEX(socket_list_lock)
11ADB_MUTEX(transport_lock)
12#if ADB_HOST
13ADB_MUTEX(local_transports_lock)
14#endif
15ADB_MUTEX(usb_lock)
16
17// Sadly logging to /data/adb/adb-... is not thread safe.
18// After modifying adb.h::D() to count invocations:
19// DEBUG(jpa):0:Handling main()
20// DEBUG(jpa):1:[ usb_init - starting thread ]
21// (Oopsies, no :2:, and matching message is also gone.)
22// DEBUG(jpa):3:[ usb_thread - opening device ]
23// DEBUG(jpa):4:jdwp control socket started (10)
24ADB_MUTEX(D_lock)
25
26#undef ADB_MUTEX
diff --git a/minadbd/services.c b/minadbd/services.c
new file mode 100644
index 00000000..8fc8b3cc
--- /dev/null
+++ b/minadbd/services.c
@@ -0,0 +1,161 @@
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#include "fdevent.h"
25
26#define TRACE_TAG TRACE_SERVICES
27#include "adb.h"
28
29typedef struct stinfo stinfo;
30
31struct stinfo {
32 void (*func)(int fd, void *cookie);
33 int fd;
34 void *cookie;
35};
36
37
38void *service_bootstrap_func(void *x)
39{
40 stinfo *sti = x;
41 sti->func(sti->fd, sti->cookie);
42 free(sti);
43 return 0;
44}
45
46static void sideload_service(int s, void *cookie)
47{
48 unsigned char buf[4096];
49 unsigned count = (unsigned) cookie;
50 int fd;
51
52 fprintf(stderr, "sideload_service invoked\n");
53
54 fd = adb_creat(ADB_SIDELOAD_FILENAME, 0644);
55 if(fd < 0) {
56 adb_close(s);
57 return;
58 }
59
60 while(count > 0) {
61 unsigned xfer = (count > 4096) ? 4096 : count;
62 if(readx(s, buf, xfer)) break;
63 if(writex(fd, buf, xfer)) break;
64 count -= xfer;
65 }
66
67 if(count == 0) {
68 writex(s, "OKAY", 4);
69 } else {
70 writex(s, "FAIL", 4);
71 }
72 adb_close(fd);
73 adb_close(s);
74
75 if (count == 0) {
76 fprintf(stderr, "adbd exiting after successful sideload\n");
77 sleep(1);
78 exit(0);
79 }
80}
81
82
83#if 0
84static void echo_service(int fd, void *cookie)
85{
86 char buf[4096];
87 int r;
88 char *p;
89 int c;
90
91 for(;;) {
92 r = read(fd, buf, 4096);
93 if(r == 0) goto done;
94 if(r < 0) {
95 if(errno == EINTR) continue;
96 else goto done;
97 }
98
99 c = r;
100 p = buf;
101 while(c > 0) {
102 r = write(fd, p, c);
103 if(r > 0) {
104 c -= r;
105 p += r;
106 continue;
107 }
108 if((r < 0) && (errno == EINTR)) continue;
109 goto done;
110 }
111 }
112done:
113 close(fd);
114}
115#endif
116
117static int create_service_thread(void (*func)(int, void *), void *cookie)
118{
119 stinfo *sti;
120 adb_thread_t t;
121 int s[2];
122
123 if(adb_socketpair(s)) {
124 printf("cannot create service socket pair\n");
125 return -1;
126 }
127
128 sti = malloc(sizeof(stinfo));
129 if(sti == 0) fatal("cannot allocate stinfo");
130 sti->func = func;
131 sti->cookie = cookie;
132 sti->fd = s[1];
133
134 if(adb_thread_create( &t, service_bootstrap_func, sti)){
135 free(sti);
136 adb_close(s[0]);
137 adb_close(s[1]);
138 printf("cannot create service thread\n");
139 return -1;
140 }
141
142 D("service thread started, %d:%d\n",s[0], s[1]);
143 return s[0];
144}
145
146int service_to_fd(const char *name)
147{
148 int ret = -1;
149
150 if (!strncmp(name, "sideload:", 9)) {
151 ret = create_service_thread(sideload_service, (void*) atoi(name + 9));
152#if 0
153 } else if(!strncmp(name, "echo:", 5)){
154 ret = create_service_thread(echo_service, 0);
155#endif
156 }
157 if (ret >= 0) {
158 close_on_exec(ret);
159 }
160 return ret;
161}
diff --git a/minadbd/sockets.c b/minadbd/sockets.c
new file mode 100644
index 00000000..9f4cecb3
--- /dev/null
+++ b/minadbd/sockets.c
@@ -0,0 +1,830 @@
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 <stdio.h>
18#include <stdlib.h>
19#include <unistd.h>
20#include <errno.h>
21#include <string.h>
22#include <ctype.h>
23
24#include "sysdeps.h"
25
26#define TRACE_TAG TRACE_SOCKETS
27#include "adb.h"
28
29ADB_MUTEX_DEFINE( socket_list_lock );
30
31static void local_socket_close_locked(asocket *s);
32
33int sendfailmsg(int fd, const char *reason)
34{
35 char buf[9];
36 int len;
37 len = strlen(reason);
38 if(len > 0xffff) len = 0xffff;
39 snprintf(buf, sizeof buf, "FAIL%04x", len);
40 if(writex(fd, buf, 8)) return -1;
41 return writex(fd, reason, len);
42}
43
44//extern int online;
45
46static unsigned local_socket_next_id = 1;
47
48static asocket local_socket_list = {
49 .next = &local_socket_list,
50 .prev = &local_socket_list,
51};
52
53/* the the list of currently closing local sockets.
54** these have no peer anymore, but still packets to
55** write to their fd.
56*/
57static asocket local_socket_closing_list = {
58 .next = &local_socket_closing_list,
59 .prev = &local_socket_closing_list,
60};
61
62asocket *find_local_socket(unsigned id)
63{
64 asocket *s;
65 asocket *result = NULL;
66
67 adb_mutex_lock(&socket_list_lock);
68 for (s = local_socket_list.next; s != &local_socket_list; s = s->next) {
69 if (s->id == id) {
70 result = s;
71 break;
72 }
73 }
74 adb_mutex_unlock(&socket_list_lock);
75
76 return result;
77}
78
79static void
80insert_local_socket(asocket* s, asocket* list)
81{
82 s->next = list;
83 s->prev = s->next->prev;
84 s->prev->next = s;
85 s->next->prev = s;
86}
87
88
89void install_local_socket(asocket *s)
90{
91 adb_mutex_lock(&socket_list_lock);
92
93 s->id = local_socket_next_id++;
94 insert_local_socket(s, &local_socket_list);
95
96 adb_mutex_unlock(&socket_list_lock);
97}
98
99void remove_socket(asocket *s)
100{
101 // socket_list_lock should already be held
102 if (s->prev && s->next)
103 {
104 s->prev->next = s->next;
105 s->next->prev = s->prev;
106 s->next = 0;
107 s->prev = 0;
108 s->id = 0;
109 }
110}
111
112void close_all_sockets(atransport *t)
113{
114 asocket *s;
115
116 /* this is a little gross, but since s->close() *will* modify
117 ** the list out from under you, your options are limited.
118 */
119 adb_mutex_lock(&socket_list_lock);
120restart:
121 for(s = local_socket_list.next; s != &local_socket_list; s = s->next){
122 if(s->transport == t || (s->peer && s->peer->transport == t)) {
123 local_socket_close_locked(s);
124 goto restart;
125 }
126 }
127 adb_mutex_unlock(&socket_list_lock);
128}
129
130static int local_socket_enqueue(asocket *s, apacket *p)
131{
132 D("LS(%d): enqueue %d\n", s->id, p->len);
133
134 p->ptr = p->data;
135
136 /* if there is already data queue'd, we will receive
137 ** events when it's time to write. just add this to
138 ** the tail
139 */
140 if(s->pkt_first) {
141 goto enqueue;
142 }
143
144 /* write as much as we can, until we
145 ** would block or there is an error/eof
146 */
147 while(p->len > 0) {
148 int r = adb_write(s->fd, p->ptr, p->len);
149 if(r > 0) {
150 p->len -= r;
151 p->ptr += r;
152 continue;
153 }
154 if((r == 0) || (errno != EAGAIN)) {
155 D( "LS(%d): not ready, errno=%d: %s\n", s->id, errno, strerror(errno) );
156 s->close(s);
157 return 1; /* not ready (error) */
158 } else {
159 break;
160 }
161 }
162
163 if(p->len == 0) {
164 put_apacket(p);
165 return 0; /* ready for more data */
166 }
167
168enqueue:
169 p->next = 0;
170 if(s->pkt_first) {
171 s->pkt_last->next = p;
172 } else {
173 s->pkt_first = p;
174 }
175 s->pkt_last = p;
176
177 /* make sure we are notified when we can drain the queue */
178 fdevent_add(&s->fde, FDE_WRITE);
179
180 return 1; /* not ready (backlog) */
181}
182
183static void local_socket_ready(asocket *s)
184{
185 /* far side is ready for data, pay attention to
186 readable events */
187 fdevent_add(&s->fde, FDE_READ);
188// D("LS(%d): ready()\n", s->id);
189}
190
191static void local_socket_close(asocket *s)
192{
193 adb_mutex_lock(&socket_list_lock);
194 local_socket_close_locked(s);
195 adb_mutex_unlock(&socket_list_lock);
196}
197
198// be sure to hold the socket list lock when calling this
199static void local_socket_destroy(asocket *s)
200{
201 apacket *p, *n;
202 D("LS(%d): destroying fde.fd=%d\n", s->id, s->fde.fd);
203
204 /* IMPORTANT: the remove closes the fd
205 ** that belongs to this socket
206 */
207 fdevent_remove(&s->fde);
208
209 /* dispose of any unwritten data */
210 for(p = s->pkt_first; p; p = n) {
211 D("LS(%d): discarding %d bytes\n", s->id, p->len);
212 n = p->next;
213 put_apacket(p);
214 }
215 remove_socket(s);
216 free(s);
217}
218
219
220static void local_socket_close_locked(asocket *s)
221{
222 D("entered. LS(%d) fd=%d\n", s->id, s->fd);
223 if(s->peer) {
224 D("LS(%d): closing peer. peer->id=%d peer->fd=%d\n",
225 s->id, s->peer->id, s->peer->fd);
226 s->peer->peer = 0;
227 // tweak to avoid deadlock
228 if (s->peer->close == local_socket_close) {
229 local_socket_close_locked(s->peer);
230 } else {
231 s->peer->close(s->peer);
232 }
233 s->peer = 0;
234 }
235
236 /* If we are already closing, or if there are no
237 ** pending packets, destroy immediately
238 */
239 if (s->closing || s->pkt_first == NULL) {
240 int id = s->id;
241 local_socket_destroy(s);
242 D("LS(%d): closed\n", id);
243 return;
244 }
245
246 /* otherwise, put on the closing list
247 */
248 D("LS(%d): closing\n", s->id);
249 s->closing = 1;
250 fdevent_del(&s->fde, FDE_READ);
251 remove_socket(s);
252 D("LS(%d): put on socket_closing_list fd=%d\n", s->id, s->fd);
253 insert_local_socket(s, &local_socket_closing_list);
254}
255
256static void local_socket_event_func(int fd, unsigned ev, void *_s)
257{
258 asocket *s = _s;
259
260 D("LS(%d): event_func(fd=%d(==%d), ev=%04x)\n", s->id, s->fd, fd, ev);
261
262 /* put the FDE_WRITE processing before the FDE_READ
263 ** in order to simplify the code.
264 */
265 if(ev & FDE_WRITE){
266 apacket *p;
267
268 while((p = s->pkt_first) != 0) {
269 while(p->len > 0) {
270 int r = adb_write(fd, p->ptr, p->len);
271 if(r > 0) {
272 p->ptr += r;
273 p->len -= r;
274 continue;
275 }
276 if(r < 0) {
277 /* returning here is ok because FDE_READ will
278 ** be processed in the next iteration loop
279 */
280 if(errno == EAGAIN) return;
281 if(errno == EINTR) continue;
282 }
283 D(" closing after write because r=%d and errno is %d\n", r, errno);
284 s->close(s);
285 return;
286 }
287
288 if(p->len == 0) {
289 s->pkt_first = p->next;
290 if(s->pkt_first == 0) s->pkt_last = 0;
291 put_apacket(p);
292 }
293 }
294
295 /* if we sent the last packet of a closing socket,
296 ** we can now destroy it.
297 */
298 if (s->closing) {
299 D(" closing because 'closing' is set after write\n");
300 s->close(s);
301 return;
302 }
303
304 /* no more packets queued, so we can ignore
305 ** writable events again and tell our peer
306 ** to resume writing
307 */
308 fdevent_del(&s->fde, FDE_WRITE);
309 s->peer->ready(s->peer);
310 }
311
312
313 if(ev & FDE_READ){
314 apacket *p = get_apacket();
315 unsigned char *x = p->data;
316 size_t avail = MAX_PAYLOAD;
317 int r;
318 int is_eof = 0;
319
320 while(avail > 0) {
321 r = adb_read(fd, x, avail);
322 D("LS(%d): post adb_read(fd=%d,...) r=%d (errno=%d) avail=%d\n", s->id, s->fd, r, r<0?errno:0, avail);
323 if(r > 0) {
324 avail -= r;
325 x += r;
326 continue;
327 }
328 if(r < 0) {
329 if(errno == EAGAIN) break;
330 if(errno == EINTR) continue;
331 }
332
333 /* r = 0 or unhandled error */
334 is_eof = 1;
335 break;
336 }
337 D("LS(%d): fd=%d post avail loop. r=%d is_eof=%d forced_eof=%d\n",
338 s->id, s->fd, r, is_eof, s->fde.force_eof);
339 if((avail == MAX_PAYLOAD) || (s->peer == 0)) {
340 put_apacket(p);
341 } else {
342 p->len = MAX_PAYLOAD - avail;
343
344 r = s->peer->enqueue(s->peer, p);
345 D("LS(%d): fd=%d post peer->enqueue(). r=%d\n", s->id, s->fd, r);
346
347 if(r < 0) {
348 /* error return means they closed us as a side-effect
349 ** and we must return immediately.
350 **
351 ** note that if we still have buffered packets, the
352 ** socket will be placed on the closing socket list.
353 ** this handler function will be called again
354 ** to process FDE_WRITE events.
355 */
356 return;
357 }
358
359 if(r > 0) {
360 /* if the remote cannot accept further events,
361 ** we disable notification of READs. They'll
362 ** be enabled again when we get a call to ready()
363 */
364 fdevent_del(&s->fde, FDE_READ);
365 }
366 }
367 /* Don't allow a forced eof if data is still there */
368 if((s->fde.force_eof && !r) || is_eof) {
369 D(" closing because is_eof=%d r=%d s->fde.force_eof=%d\n", is_eof, r, s->fde.force_eof);
370 s->close(s);
371 }
372 }
373
374 if(ev & FDE_ERROR){
375 /* this should be caught be the next read or write
376 ** catching it here means we may skip the last few
377 ** bytes of readable data.
378 */
379// s->close(s);
380 D("LS(%d): FDE_ERROR (fd=%d)\n", s->id, s->fd);
381
382 return;
383 }
384}
385
386asocket *create_local_socket(int fd)
387{
388 asocket *s = calloc(1, sizeof(asocket));
389 if (s == NULL) fatal("cannot allocate socket");
390 s->fd = fd;
391 s->enqueue = local_socket_enqueue;
392 s->ready = local_socket_ready;
393 s->close = local_socket_close;
394 install_local_socket(s);
395
396 fdevent_install(&s->fde, fd, local_socket_event_func, s);
397/* fdevent_add(&s->fde, FDE_ERROR); */
398 //fprintf(stderr, "Created local socket in create_local_socket \n");
399 D("LS(%d): created (fd=%d)\n", s->id, s->fd);
400 return s;
401}
402
403asocket *create_local_service_socket(const char *name)
404{
405 asocket *s;
406 int fd;
407
408 fd = service_to_fd(name);
409 if(fd < 0) return 0;
410
411 s = create_local_socket(fd);
412 D("LS(%d): bound to '%s' via %d\n", s->id, name, fd);
413 return s;
414}
415
416#if ADB_HOST
417static asocket *create_host_service_socket(const char *name, const char* serial)
418{
419 asocket *s;
420
421 s = host_service_to_socket(name, serial);
422
423 if (s != NULL) {
424 D("LS(%d) bound to '%s'\n", s->id, name);
425 return s;
426 }
427
428 return s;
429}
430#endif /* ADB_HOST */
431
432/* a Remote socket is used to send/receive data to/from a given transport object
433** it needs to be closed when the transport is forcibly destroyed by the user
434*/
435typedef struct aremotesocket {
436 asocket socket;
437 adisconnect disconnect;
438} aremotesocket;
439
440static int remote_socket_enqueue(asocket *s, apacket *p)
441{
442 D("entered remote_socket_enqueue RS(%d) WRITE fd=%d peer.fd=%d\n",
443 s->id, s->fd, s->peer->fd);
444 p->msg.command = A_WRTE;
445 p->msg.arg0 = s->peer->id;
446 p->msg.arg1 = s->id;
447 p->msg.data_length = p->len;
448 send_packet(p, s->transport);
449 return 1;
450}
451
452static void remote_socket_ready(asocket *s)
453{
454 D("entered remote_socket_ready RS(%d) OKAY fd=%d peer.fd=%d\n",
455 s->id, s->fd, s->peer->fd);
456 apacket *p = get_apacket();
457 p->msg.command = A_OKAY;
458 p->msg.arg0 = s->peer->id;
459 p->msg.arg1 = s->id;
460 send_packet(p, s->transport);
461}
462
463static void remote_socket_close(asocket *s)
464{
465 D("entered remote_socket_close RS(%d) CLOSE fd=%d peer->fd=%d\n",
466 s->id, s->fd, s->peer?s->peer->fd:-1);
467 apacket *p = get_apacket();
468 p->msg.command = A_CLSE;
469 if(s->peer) {
470 p->msg.arg0 = s->peer->id;
471 s->peer->peer = 0;
472 D("RS(%d) peer->close()ing peer->id=%d peer->fd=%d\n",
473 s->id, s->peer->id, s->peer->fd);
474 s->peer->close(s->peer);
475 }
476 p->msg.arg1 = s->id;
477 send_packet(p, s->transport);
478 D("RS(%d): closed\n", s->id);
479 remove_transport_disconnect( s->transport, &((aremotesocket*)s)->disconnect );
480 free(s);
481}
482
483static void remote_socket_disconnect(void* _s, atransport* t)
484{
485 asocket* s = _s;
486 asocket* peer = s->peer;
487
488 D("remote_socket_disconnect RS(%d)\n", s->id);
489 if (peer) {
490 peer->peer = NULL;
491 peer->close(peer);
492 }
493 remove_transport_disconnect( s->transport, &((aremotesocket*)s)->disconnect );
494 free(s);
495}
496
497asocket *create_remote_socket(unsigned id, atransport *t)
498{
499 asocket *s = calloc(1, sizeof(aremotesocket));
500 adisconnect* dis = &((aremotesocket*)s)->disconnect;
501
502 if (s == NULL) fatal("cannot allocate socket");
503 s->id = id;
504 s->enqueue = remote_socket_enqueue;
505 s->ready = remote_socket_ready;
506 s->close = remote_socket_close;
507 s->transport = t;
508
509 dis->func = remote_socket_disconnect;
510 dis->opaque = s;
511 add_transport_disconnect( t, dis );
512 D("RS(%d): created\n", s->id);
513 return s;
514}
515
516void connect_to_remote(asocket *s, const char *destination)
517{
518 D("Connect_to_remote call RS(%d) fd=%d\n", s->id, s->fd);
519 apacket *p = get_apacket();
520 int len = strlen(destination) + 1;
521
522 if(len > (MAX_PAYLOAD-1)) {
523 fatal("destination oversized");
524 }
525
526 D("LS(%d): connect('%s')\n", s->id, destination);
527 p->msg.command = A_OPEN;
528 p->msg.arg0 = s->id;
529 p->msg.data_length = len;
530 strcpy((char*) p->data, destination);
531 send_packet(p, s->transport);
532}
533
534
535/* this is used by magic sockets to rig local sockets to
536 send the go-ahead message when they connect */
537static void local_socket_ready_notify(asocket *s)
538{
539 s->ready = local_socket_ready;
540 s->close = local_socket_close;
541 adb_write(s->fd, "OKAY", 4);
542 s->ready(s);
543}
544
545/* this is used by magic sockets to rig local sockets to
546 send the failure message if they are closed before
547 connected (to avoid closing them without a status message) */
548static void local_socket_close_notify(asocket *s)
549{
550 s->ready = local_socket_ready;
551 s->close = local_socket_close;
552 sendfailmsg(s->fd, "closed");
553 s->close(s);
554}
555
556unsigned unhex(unsigned char *s, int len)
557{
558 unsigned n = 0, c;
559
560 while(len-- > 0) {
561 switch((c = *s++)) {
562 case '0': case '1': case '2':
563 case '3': case '4': case '5':
564 case '6': case '7': case '8':
565 case '9':
566 c -= '0';
567 break;
568 case 'a': case 'b': case 'c':
569 case 'd': case 'e': case 'f':
570 c = c - 'a' + 10;
571 break;
572 case 'A': case 'B': case 'C':
573 case 'D': case 'E': case 'F':
574 c = c - 'A' + 10;
575 break;
576 default:
577 return 0xffffffff;
578 }
579
580 n = (n << 4) | c;
581 }
582
583 return n;
584}
585
586/* skip_host_serial return the position in a string
587 skipping over the 'serial' parameter in the ADB protocol,
588 where parameter string may be a host:port string containing
589 the protocol delimiter (colon). */
590char *skip_host_serial(char *service) {
591 char *first_colon, *serial_end;
592
593 first_colon = strchr(service, ':');
594 if (!first_colon) {
595 /* No colon in service string. */
596 return NULL;
597 }
598 serial_end = first_colon;
599 if (isdigit(serial_end[1])) {
600 serial_end++;
601 while ((*serial_end) && isdigit(*serial_end)) {
602 serial_end++;
603 }
604 if ((*serial_end) != ':') {
605 // Something other than numbers was found, reset the end.
606 serial_end = first_colon;
607 }
608 }
609 return serial_end;
610}
611
612static int smart_socket_enqueue(asocket *s, apacket *p)
613{
614 unsigned len;
615#if ADB_HOST
616 char *service = NULL;
617 char* serial = NULL;
618 transport_type ttype = kTransportAny;
619#endif
620
621 D("SS(%d): enqueue %d\n", s->id, p->len);
622
623 if(s->pkt_first == 0) {
624 s->pkt_first = p;
625 s->pkt_last = p;
626 } else {
627 if((s->pkt_first->len + p->len) > MAX_PAYLOAD) {
628 D("SS(%d): overflow\n", s->id);
629 put_apacket(p);
630 goto fail;
631 }
632
633 memcpy(s->pkt_first->data + s->pkt_first->len,
634 p->data, p->len);
635 s->pkt_first->len += p->len;
636 put_apacket(p);
637
638 p = s->pkt_first;
639 }
640
641 /* don't bother if we can't decode the length */
642 if(p->len < 4) return 0;
643
644 len = unhex(p->data, 4);
645 if((len < 1) || (len > 1024)) {
646 D("SS(%d): bad size (%d)\n", s->id, len);
647 goto fail;
648 }
649
650 D("SS(%d): len is %d\n", s->id, len );
651 /* can't do anything until we have the full header */
652 if((len + 4) > p->len) {
653 D("SS(%d): waiting for %d more bytes\n", s->id, len+4 - p->len);
654 return 0;
655 }
656
657 p->data[len + 4] = 0;
658
659 D("SS(%d): '%s'\n", s->id, (char*) (p->data + 4));
660
661#if ADB_HOST
662 service = (char *)p->data + 4;
663 if(!strncmp(service, "host-serial:", strlen("host-serial:"))) {
664 char* serial_end;
665 service += strlen("host-serial:");
666
667 // serial number should follow "host:" and could be a host:port string.
668 serial_end = skip_host_serial(service);
669 if (serial_end) {
670 *serial_end = 0; // terminate string
671 serial = service;
672 service = serial_end + 1;
673 }
674 } else if (!strncmp(service, "host-usb:", strlen("host-usb:"))) {
675 ttype = kTransportUsb;
676 service += strlen("host-usb:");
677 } else if (!strncmp(service, "host-local:", strlen("host-local:"))) {
678 ttype = kTransportLocal;
679 service += strlen("host-local:");
680 } else if (!strncmp(service, "host:", strlen("host:"))) {
681 ttype = kTransportAny;
682 service += strlen("host:");
683 } else {
684 service = NULL;
685 }
686
687 if (service) {
688 asocket *s2;
689
690 /* some requests are handled immediately -- in that
691 ** case the handle_host_request() routine has sent
692 ** the OKAY or FAIL message and all we have to do
693 ** is clean up.
694 */
695 if(handle_host_request(service, ttype, serial, s->peer->fd, s) == 0) {
696 /* XXX fail message? */
697 D( "SS(%d): handled host service '%s'\n", s->id, service );
698 goto fail;
699 }
700 if (!strncmp(service, "transport", strlen("transport"))) {
701 D( "SS(%d): okay transport\n", s->id );
702 p->len = 0;
703 return 0;
704 }
705
706 /* try to find a local service with this name.
707 ** if no such service exists, we'll fail out
708 ** and tear down here.
709 */
710 s2 = create_host_service_socket(service, serial);
711 if(s2 == 0) {
712 D( "SS(%d): couldn't create host service '%s'\n", s->id, service );
713 sendfailmsg(s->peer->fd, "unknown host service");
714 goto fail;
715 }
716
717 /* we've connected to a local host service,
718 ** so we make our peer back into a regular
719 ** local socket and bind it to the new local
720 ** service socket, acknowledge the successful
721 ** connection, and close this smart socket now
722 ** that its work is done.
723 */
724 adb_write(s->peer->fd, "OKAY", 4);
725
726 s->peer->ready = local_socket_ready;
727 s->peer->close = local_socket_close;
728 s->peer->peer = s2;
729 s2->peer = s->peer;
730 s->peer = 0;
731 D( "SS(%d): okay\n", s->id );
732 s->close(s);
733
734 /* initial state is "ready" */
735 s2->ready(s2);
736 return 0;
737 }
738#else /* !ADB_HOST */
739 if (s->transport == NULL) {
740 char* error_string = "unknown failure";
741 s->transport = acquire_one_transport (CS_ANY,
742 kTransportAny, NULL, &error_string);
743
744 if (s->transport == NULL) {
745 sendfailmsg(s->peer->fd, error_string);
746 goto fail;
747 }
748 }
749#endif
750
751 if(!(s->transport) || (s->transport->connection_state == CS_OFFLINE)) {
752 /* if there's no remote we fail the connection
753 ** right here and terminate it
754 */
755 sendfailmsg(s->peer->fd, "device offline (x)");
756 goto fail;
757 }
758
759
760 /* instrument our peer to pass the success or fail
761 ** message back once it connects or closes, then
762 ** detach from it, request the connection, and
763 ** tear down
764 */
765 s->peer->ready = local_socket_ready_notify;
766 s->peer->close = local_socket_close_notify;
767 s->peer->peer = 0;
768 /* give him our transport and upref it */
769 s->peer->transport = s->transport;
770
771 connect_to_remote(s->peer, (char*) (p->data + 4));
772 s->peer = 0;
773 s->close(s);
774 return 1;
775
776fail:
777 /* we're going to close our peer as a side-effect, so
778 ** return -1 to signal that state to the local socket
779 ** who is enqueueing against us
780 */
781 s->close(s);
782 return -1;
783}
784
785static void smart_socket_ready(asocket *s)
786{
787 D("SS(%d): ready\n", s->id);
788}
789
790static void smart_socket_close(asocket *s)
791{
792 D("SS(%d): closed\n", s->id);
793 if(s->pkt_first){
794 put_apacket(s->pkt_first);
795 }
796 if(s->peer) {
797 s->peer->peer = 0;
798 s->peer->close(s->peer);
799 s->peer = 0;
800 }
801 free(s);
802}
803
804asocket *create_smart_socket(void (*action_cb)(asocket *s, const char *act))
805{
806 D("Creating smart socket \n");
807 asocket *s = calloc(1, sizeof(asocket));
808 if (s == NULL) fatal("cannot allocate socket");
809 s->enqueue = smart_socket_enqueue;
810 s->ready = smart_socket_ready;
811 s->close = smart_socket_close;
812 s->extra = action_cb;
813
814 D("SS(%d): created %p\n", s->id, action_cb);
815 return s;
816}
817
818void smart_socket_action(asocket *s, const char *act)
819{
820
821}
822
823void connect_to_smartsocket(asocket *s)
824{
825 D("Connecting to smart socket \n");
826 asocket *ss = create_smart_socket(smart_socket_action);
827 s->peer = ss;
828 ss->peer = s;
829 s->ready(s);
830}
diff --git a/minadbd/sysdeps.h b/minadbd/sysdeps.h
new file mode 100644
index 00000000..b5180761
--- /dev/null
+++ b/minadbd/sysdeps.h
@@ -0,0 +1,495 @@
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/* this file contains system-dependent definitions used by ADB
18 * they're related to threads, sockets and file descriptors
19 */
20#ifndef _ADB_SYSDEPS_H
21#define _ADB_SYSDEPS_H
22
23#ifdef __CYGWIN__
24# undef _WIN32
25#endif
26
27#ifdef _WIN32
28
29#include <windows.h>
30#include <winsock2.h>
31#include <ws2tcpip.h>
32#include <process.h>
33#include <fcntl.h>
34#include <io.h>
35#include <sys/stat.h>
36#include <errno.h>
37#include <ctype.h>
38
39#define OS_PATH_SEPARATOR '\\'
40#define OS_PATH_SEPARATOR_STR "\\"
41
42typedef CRITICAL_SECTION adb_mutex_t;
43
44#define ADB_MUTEX_DEFINE(x) adb_mutex_t x
45
46/* declare all mutexes */
47/* For win32, adb_sysdeps_init() will do the mutex runtime initialization. */
48#define ADB_MUTEX(x) extern adb_mutex_t x;
49#include "mutex_list.h"
50
51extern void adb_sysdeps_init(void);
52
53static __inline__ void adb_mutex_lock( adb_mutex_t* lock )
54{
55 EnterCriticalSection( lock );
56}
57
58static __inline__ void adb_mutex_unlock( adb_mutex_t* lock )
59{
60 LeaveCriticalSection( lock );
61}
62
63typedef struct { unsigned tid; } adb_thread_t;
64
65typedef void* (*adb_thread_func_t)(void* arg);
66
67typedef void (*win_thread_func_t)(void* arg);
68
69static __inline__ int adb_thread_create( adb_thread_t *thread, adb_thread_func_t func, void* arg)
70{
71 thread->tid = _beginthread( (win_thread_func_t)func, 0, arg );
72 if (thread->tid == (unsigned)-1L) {
73 return -1;
74 }
75 return 0;
76}
77
78static __inline__ void close_on_exec(int fd)
79{
80 /* nothing really */
81}
82
83extern void disable_tcp_nagle(int fd);
84
85#define lstat stat /* no symlinks on Win32 */
86
87#define S_ISLNK(m) 0 /* no symlinks on Win32 */
88
89static __inline__ int adb_unlink(const char* path)
90{
91 int rc = unlink(path);
92
93 if (rc == -1 && errno == EACCES) {
94 /* unlink returns EACCES when the file is read-only, so we first */
95 /* try to make it writable, then unlink again... */
96 rc = chmod(path, _S_IREAD|_S_IWRITE );
97 if (rc == 0)
98 rc = unlink(path);
99 }
100 return rc;
101}
102#undef unlink
103#define unlink ___xxx_unlink
104
105static __inline__ int adb_mkdir(const char* path, int mode)
106{
107 return _mkdir(path);
108}
109#undef mkdir
110#define mkdir ___xxx_mkdir
111
112extern int adb_open(const char* path, int options);
113extern int adb_creat(const char* path, int mode);
114extern int adb_read(int fd, void* buf, int len);
115extern int adb_write(int fd, const void* buf, int len);
116extern int adb_lseek(int fd, int pos, int where);
117extern int adb_shutdown(int fd);
118extern int adb_close(int fd);
119
120static __inline__ int unix_close(int fd)
121{
122 return close(fd);
123}
124#undef close
125#define close ____xxx_close
126
127static __inline__ int unix_read(int fd, void* buf, size_t len)
128{
129 return read(fd, buf, len);
130}
131#undef read
132#define read ___xxx_read
133
134static __inline__ int unix_write(int fd, const void* buf, size_t len)
135{
136 return write(fd, buf, len);
137}
138#undef write
139#define write ___xxx_write
140
141static __inline__ int adb_open_mode(const char* path, int options, int mode)
142{
143 return adb_open(path, options);
144}
145
146static __inline__ int unix_open(const char* path, int options,...)
147{
148 if ((options & O_CREAT) == 0)
149 {
150 return open(path, options);
151 }
152 else
153 {
154 int mode;
155 va_list args;
156 va_start( args, options );
157 mode = va_arg( args, int );
158 va_end( args );
159 return open(path, options, mode);
160 }
161}
162#define open ___xxx_unix_open
163
164
165/* normally provided by <cutils/misc.h> */
166extern void* load_file(const char* pathname, unsigned* psize);
167
168/* normally provided by <cutils/sockets.h> */
169extern int socket_loopback_client(int port, int type);
170extern int socket_network_client(const char *host, int port, int type);
171extern int socket_loopback_server(int port, int type);
172extern int socket_inaddr_any_server(int port, int type);
173
174/* normally provided by "fdevent.h" */
175
176#define FDE_READ 0x0001
177#define FDE_WRITE 0x0002
178#define FDE_ERROR 0x0004
179#define FDE_DONT_CLOSE 0x0080
180
181typedef struct fdevent fdevent;
182
183typedef void (*fd_func)(int fd, unsigned events, void *userdata);
184
185fdevent *fdevent_create(int fd, fd_func func, void *arg);
186void fdevent_destroy(fdevent *fde);
187void fdevent_install(fdevent *fde, int fd, fd_func func, void *arg);
188void fdevent_remove(fdevent *item);
189void fdevent_set(fdevent *fde, unsigned events);
190void fdevent_add(fdevent *fde, unsigned events);
191void fdevent_del(fdevent *fde, unsigned events);
192void fdevent_loop();
193
194struct fdevent {
195 fdevent *next;
196 fdevent *prev;
197
198 int fd;
199 int force_eof;
200
201 unsigned short state;
202 unsigned short events;
203
204 fd_func func;
205 void *arg;
206};
207
208static __inline__ void adb_sleep_ms( int mseconds )
209{
210 Sleep( mseconds );
211}
212
213extern int adb_socket_accept(int serverfd, struct sockaddr* addr, socklen_t *addrlen);
214
215#undef accept
216#define accept ___xxx_accept
217
218static __inline__ int adb_socket_setbufsize( int fd, int bufsize )
219{
220 int opt = bufsize;
221 return setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (const char*)&opt, sizeof(opt));
222}
223
224extern int adb_socketpair( int sv[2] );
225
226static __inline__ char* adb_dirstart( const char* path )
227{
228 char* p = strchr(path, '/');
229 char* p2 = strchr(path, '\\');
230
231 if ( !p )
232 p = p2;
233 else if ( p2 && p2 > p )
234 p = p2;
235
236 return p;
237}
238
239static __inline__ char* adb_dirstop( const char* path )
240{
241 char* p = strrchr(path, '/');
242 char* p2 = strrchr(path, '\\');
243
244 if ( !p )
245 p = p2;
246 else if ( p2 && p2 > p )
247 p = p2;
248
249 return p;
250}
251
252static __inline__ int adb_is_absolute_host_path( const char* path )
253{
254 return isalpha(path[0]) && path[1] == ':' && path[2] == '\\';
255}
256
257#else /* !_WIN32 a.k.a. Unix */
258
259#include "fdevent.h"