blob: c28e031c272e12256b484702485eda32b05f3ef7 [file] [log] [blame]
Dan Albert33134262015-03-19 15:21:08 -07001/*
2 * Copyright (C) 2015 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_SYSDEPS
18
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080019#include "sysdeps.h"
Dan Albert33134262015-03-19 15:21:08 -070020
21#include <winsock2.h> /* winsock.h *must* be included before windows.h. */
Stephen Hines2f431a82014-10-01 17:37:06 -070022#include <windows.h>
Dan Albert33134262015-03-19 15:21:08 -070023
24#include <errno.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080025#include <stdio.h>
Christopher Ferris67a7a4a2014-11-06 14:34:24 -080026#include <stdlib.h>
Dan Albert33134262015-03-19 15:21:08 -070027
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080028#include "adb.h"
29
30extern void fatal(const char *fmt, ...);
31
32#define assert(cond) do { if (!(cond)) fatal( "assertion failed '%s' on %s:%ld\n", #cond, __FILE__, __LINE__ ); } while (0)
33
34/**************************************************************************/
35/**************************************************************************/
36/***** *****/
37/***** replaces libs/cutils/load_file.c *****/
38/***** *****/
39/**************************************************************************/
40/**************************************************************************/
41
42void *load_file(const char *fn, unsigned *_sz)
43{
44 HANDLE file;
45 char *data;
46 DWORD file_size;
47
48 file = CreateFile( fn,
49 GENERIC_READ,
50 FILE_SHARE_READ,
51 NULL,
52 OPEN_EXISTING,
53 0,
54 NULL );
55
56 if (file == INVALID_HANDLE_VALUE)
57 return NULL;
58
59 file_size = GetFileSize( file, NULL );
60 data = NULL;
61
62 if (file_size > 0) {
63 data = (char*) malloc( file_size + 1 );
64 if (data == NULL) {
65 D("load_file: could not allocate %ld bytes\n", file_size );
66 file_size = 0;
67 } else {
68 DWORD out_bytes;
69
70 if ( !ReadFile( file, data, file_size, &out_bytes, NULL ) ||
71 out_bytes != file_size )
72 {
73 D("load_file: could not read %ld bytes from '%s'\n", file_size, fn);
74 free(data);
75 data = NULL;
76 file_size = 0;
77 }
78 }
79 }
80 CloseHandle( file );
81
82 *_sz = (unsigned) file_size;
83 return data;
84}
85
86/**************************************************************************/
87/**************************************************************************/
88/***** *****/
89/***** common file descriptor handling *****/
90/***** *****/
91/**************************************************************************/
92/**************************************************************************/
93
94typedef const struct FHClassRec_* FHClass;
95
96typedef struct FHRec_* FH;
97
98typedef struct EventHookRec_* EventHook;
99
100typedef struct FHClassRec_
101{
102 void (*_fh_init) ( FH f );
103 int (*_fh_close)( FH f );
104 int (*_fh_lseek)( FH f, int pos, int origin );
105 int (*_fh_read) ( FH f, void* buf, int len );
106 int (*_fh_write)( FH f, const void* buf, int len );
107 void (*_fh_hook) ( FH f, int events, EventHook hook );
108
109} FHClassRec;
110
111/* used to emulate unix-domain socket pairs */
112typedef struct SocketPairRec_* SocketPair;
113
114typedef struct FHRec_
115{
116 FHClass clazz;
117 int used;
118 int eof;
119 union {
120 HANDLE handle;
121 SOCKET socket;
122 SocketPair pair;
123 } u;
124
125 HANDLE event;
126 int mask;
127
128 char name[32];
129
130} FHRec;
131
132#define fh_handle u.handle
133#define fh_socket u.socket
134#define fh_pair u.pair
135
136#define WIN32_FH_BASE 100
137
138#define WIN32_MAX_FHS 128
139
140static adb_mutex_t _win32_lock;
141static FHRec _win32_fhs[ WIN32_MAX_FHS ];
142static int _win32_fh_count;
143
144static FH
145_fh_from_int( int fd )
146{
147 FH f;
148
149 fd -= WIN32_FH_BASE;
150
151 if (fd < 0 || fd >= _win32_fh_count) {
152 D( "_fh_from_int: invalid fd %d\n", fd + WIN32_FH_BASE );
153 errno = EBADF;
154 return NULL;
155 }
156
157 f = &_win32_fhs[fd];
158
159 if (f->used == 0) {
160 D( "_fh_from_int: invalid fd %d\n", fd + WIN32_FH_BASE );
161 errno = EBADF;
162 return NULL;
163 }
164
165 return f;
166}
167
168
169static int
170_fh_to_int( FH f )
171{
172 if (f && f->used && f >= _win32_fhs && f < _win32_fhs + WIN32_MAX_FHS)
173 return (int)(f - _win32_fhs) + WIN32_FH_BASE;
174
175 return -1;
176}
177
178static FH
179_fh_alloc( FHClass clazz )
180{
181 int nn;
182 FH f = NULL;
183
184 adb_mutex_lock( &_win32_lock );
185
186 if (_win32_fh_count < WIN32_MAX_FHS) {
187 f = &_win32_fhs[ _win32_fh_count++ ];
188 goto Exit;
189 }
190
191 for (nn = 0; nn < WIN32_MAX_FHS; nn++) {
192 if ( _win32_fhs[nn].clazz == NULL) {
193 f = &_win32_fhs[nn];
194 goto Exit;
195 }
196 }
197 D( "_fh_alloc: no more free file descriptors\n" );
198Exit:
199 if (f) {
200 f->clazz = clazz;
201 f->used = 1;
202 f->eof = 0;
203 clazz->_fh_init(f);
204 }
205 adb_mutex_unlock( &_win32_lock );
206 return f;
207}
208
209
210static int
211_fh_close( FH f )
212{
213 if ( f->used ) {
214 f->clazz->_fh_close( f );
215 f->used = 0;
216 f->eof = 0;
217 f->clazz = NULL;
218 }
219 return 0;
220}
221
222/* forward definitions */
223static const FHClassRec _fh_file_class;
224static const FHClassRec _fh_socket_class;
225
226/**************************************************************************/
227/**************************************************************************/
228/***** *****/
229/***** file-based descriptor handling *****/
230/***** *****/
231/**************************************************************************/
232/**************************************************************************/
233
234static void
235_fh_file_init( FH f )
236{
237 f->fh_handle = INVALID_HANDLE_VALUE;
238}
239
240static int
241_fh_file_close( FH f )
242{
243 CloseHandle( f->fh_handle );
244 f->fh_handle = INVALID_HANDLE_VALUE;
245 return 0;
246}
247
248static int
249_fh_file_read( FH f, void* buf, int len )
250{
251 DWORD read_bytes;
252
253 if ( !ReadFile( f->fh_handle, buf, (DWORD)len, &read_bytes, NULL ) ) {
254 D( "adb_read: could not read %d bytes from %s\n", len, f->name );
255 errno = EIO;
256 return -1;
257 } else if (read_bytes < (DWORD)len) {
258 f->eof = 1;
259 }
260 return (int)read_bytes;
261}
262
263static int
264_fh_file_write( FH f, const void* buf, int len )
265{
266 DWORD wrote_bytes;
267
268 if ( !WriteFile( f->fh_handle, buf, (DWORD)len, &wrote_bytes, NULL ) ) {
269 D( "adb_file_write: could not write %d bytes from %s\n", len, f->name );
270 errno = EIO;
271 return -1;
272 } else if (wrote_bytes < (DWORD)len) {
273 f->eof = 1;
274 }
275 return (int)wrote_bytes;
276}
277
278static int
279_fh_file_lseek( FH f, int pos, int origin )
280{
281 DWORD method;
282 DWORD result;
283
284 switch (origin)
285 {
286 case SEEK_SET: method = FILE_BEGIN; break;
287 case SEEK_CUR: method = FILE_CURRENT; break;
288 case SEEK_END: method = FILE_END; break;
289 default:
290 errno = EINVAL;
291 return -1;
292 }
293
294 result = SetFilePointer( f->fh_handle, pos, NULL, method );
295 if (result == INVALID_SET_FILE_POINTER) {
296 errno = EIO;
297 return -1;
298 } else {
299 f->eof = 0;
300 }
301 return (int)result;
302}
303
304static void _fh_file_hook( FH f, int event, EventHook eventhook ); /* forward */
305
306static const FHClassRec _fh_file_class =
307{
308 _fh_file_init,
309 _fh_file_close,
310 _fh_file_lseek,
311 _fh_file_read,
312 _fh_file_write,
313 _fh_file_hook
314};
315
316/**************************************************************************/
317/**************************************************************************/
318/***** *****/
319/***** file-based descriptor handling *****/
320/***** *****/
321/**************************************************************************/
322/**************************************************************************/
323
324int adb_open(const char* path, int options)
325{
326 FH f;
327
328 DWORD desiredAccess = 0;
329 DWORD shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
330
331 switch (options) {
332 case O_RDONLY:
333 desiredAccess = GENERIC_READ;
334 break;
335 case O_WRONLY:
336 desiredAccess = GENERIC_WRITE;
337 break;
338 case O_RDWR:
339 desiredAccess = GENERIC_READ | GENERIC_WRITE;
340 break;
341 default:
342 D("adb_open: invalid options (0x%0x)\n", options);
343 errno = EINVAL;
344 return -1;
345 }
346
347 f = _fh_alloc( &_fh_file_class );
348 if ( !f ) {
349 errno = ENOMEM;
350 return -1;
351 }
352
353 f->fh_handle = CreateFile( path, desiredAccess, shareMode, NULL, OPEN_EXISTING,
354 0, NULL );
355
356 if ( f->fh_handle == INVALID_HANDLE_VALUE ) {
357 _fh_close(f);
358 D( "adb_open: could not open '%s':", path );
359 switch (GetLastError()) {
360 case ERROR_FILE_NOT_FOUND:
361 D( "file not found\n" );
362 errno = ENOENT;
363 return -1;
364
365 case ERROR_PATH_NOT_FOUND:
366 D( "path not found\n" );
367 errno = ENOTDIR;
368 return -1;
369
370 default:
371 D( "unknown error\n" );
372 errno = ENOENT;
373 return -1;
374 }
375 }
Vladimir Chtchetkinece480832011-11-30 10:20:27 -0800376
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800377 snprintf( f->name, sizeof(f->name), "%d(%s)", _fh_to_int(f), path );
378 D( "adb_open: '%s' => fd %d\n", path, _fh_to_int(f) );
379 return _fh_to_int(f);
380}
381
382/* ignore mode on Win32 */
383int adb_creat(const char* path, int mode)
384{
385 FH f;
386
387 f = _fh_alloc( &_fh_file_class );
388 if ( !f ) {
389 errno = ENOMEM;
390 return -1;
391 }
392
393 f->fh_handle = CreateFile( path, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
394 NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
395 NULL );
396
397 if ( f->fh_handle == INVALID_HANDLE_VALUE ) {
398 _fh_close(f);
399 D( "adb_creat: could not open '%s':", path );
400 switch (GetLastError()) {
401 case ERROR_FILE_NOT_FOUND:
402 D( "file not found\n" );
403 errno = ENOENT;
404 return -1;
405
406 case ERROR_PATH_NOT_FOUND:
407 D( "path not found\n" );
408 errno = ENOTDIR;
409 return -1;
410
411 default:
412 D( "unknown error\n" );
413 errno = ENOENT;
414 return -1;
415 }
416 }
417 snprintf( f->name, sizeof(f->name), "%d(%s)", _fh_to_int(f), path );
418 D( "adb_creat: '%s' => fd %d\n", path, _fh_to_int(f) );
419 return _fh_to_int(f);
420}
421
422
423int adb_read(int fd, void* buf, int len)
424{
425 FH f = _fh_from_int(fd);
426
427 if (f == NULL) {
428 return -1;
429 }
430
431 return f->clazz->_fh_read( f, buf, len );
432}
433
434
435int adb_write(int fd, const void* buf, int len)
436{
437 FH f = _fh_from_int(fd);
438
439 if (f == NULL) {
440 return -1;
441 }
442
443 return f->clazz->_fh_write(f, buf, len);
444}
445
446
447int adb_lseek(int fd, int pos, int where)
448{
449 FH f = _fh_from_int(fd);
450
451 if (!f) {
452 return -1;
453 }
454
455 return f->clazz->_fh_lseek(f, pos, where);
456}
457
458
Mike Lockwood8cf0d592009-10-11 23:04:18 -0400459int adb_shutdown(int fd)
460{
461 FH f = _fh_from_int(fd);
462
Spencer Lowf055c192015-01-25 14:40:16 -0800463 if (!f || f->clazz != &_fh_socket_class) {
464 D("adb_shutdown: invalid fd %d\n", fd);
Mike Lockwood8cf0d592009-10-11 23:04:18 -0400465 return -1;
466 }
467
468 D( "adb_shutdown: %s\n", f->name);
469 shutdown( f->fh_socket, SD_BOTH );
470 return 0;
471}
472
473
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800474int adb_close(int fd)
475{
476 FH f = _fh_from_int(fd);
477
478 if (!f) {
479 return -1;
480 }
481
482 D( "adb_close: %s\n", f->name);
483 _fh_close(f);
484 return 0;
485}
486
487/**************************************************************************/
488/**************************************************************************/
489/***** *****/
490/***** socket-based file descriptors *****/
491/***** *****/
492/**************************************************************************/
493/**************************************************************************/
494
Spencer Lowf055c192015-01-25 14:40:16 -0800495#undef setsockopt
496
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800497static void
498_socket_set_errno( void )
499{
500 switch (WSAGetLastError()) {
501 case 0: errno = 0; break;
502 case WSAEWOULDBLOCK: errno = EAGAIN; break;
503 case WSAEINTR: errno = EINTR; break;
504 default:
505 D( "_socket_set_errno: unhandled value %d\n", WSAGetLastError() );
506 errno = EINVAL;
507 }
508}
509
510static void
511_fh_socket_init( FH f )
512{
513 f->fh_socket = INVALID_SOCKET;
514 f->event = WSACreateEvent();
515 f->mask = 0;
516}
517
518static int
519_fh_socket_close( FH f )
520{
521 /* gently tell any peer that we're closing the socket */
522 shutdown( f->fh_socket, SD_BOTH );
523 closesocket( f->fh_socket );
524 f->fh_socket = INVALID_SOCKET;
525 CloseHandle( f->event );
526 f->mask = 0;
527 return 0;
528}
529
530static int
531_fh_socket_lseek( FH f, int pos, int origin )
532{
533 errno = EPIPE;
534 return -1;
535}
536
537static int
538_fh_socket_read( FH f, void* buf, int len )
539{
540 int result = recv( f->fh_socket, buf, len, 0 );
541 if (result == SOCKET_ERROR) {
542 _socket_set_errno();
543 result = -1;
544 }
545 return result;
546}
547
548static int
549_fh_socket_write( FH f, const void* buf, int len )
550{
551 int result = send( f->fh_socket, buf, len, 0 );
552 if (result == SOCKET_ERROR) {
553 _socket_set_errno();
554 result = -1;
555 }
556 return result;
557}
558
559static void _fh_socket_hook( FH f, int event, EventHook hook ); /* forward */
560
561static const FHClassRec _fh_socket_class =
562{
563 _fh_socket_init,
564 _fh_socket_close,
565 _fh_socket_lseek,
566 _fh_socket_read,
567 _fh_socket_write,
568 _fh_socket_hook
569};
570
571/**************************************************************************/
572/**************************************************************************/
573/***** *****/
574/***** replacement for libs/cutils/socket_xxxx.c *****/
575/***** *****/
576/**************************************************************************/
577/**************************************************************************/
578
579#include <winsock2.h>
580
581static int _winsock_init;
582
583static void
584_cleanup_winsock( void )
585{
586 WSACleanup();
587}
588
589static void
590_init_winsock( void )
591{
592 if (!_winsock_init) {
593 WSADATA wsaData;
594 int rc = WSAStartup( MAKEWORD(2,2), &wsaData);
595 if (rc != 0) {
596 fatal( "adb: could not initialize Winsock\n" );
597 }
598 atexit( _cleanup_winsock );
599 _winsock_init = 1;
600 }
601}
602
603int socket_loopback_client(int port, int type)
604{
605 FH f = _fh_alloc( &_fh_socket_class );
606 struct sockaddr_in addr;
607 SOCKET s;
608
609 if (!f)
610 return -1;
611
612 if (!_winsock_init)
613 _init_winsock();
614
615 memset(&addr, 0, sizeof(addr));
616 addr.sin_family = AF_INET;
617 addr.sin_port = htons(port);
618 addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
619
620 s = socket(AF_INET, type, 0);
621 if(s == INVALID_SOCKET) {
622 D("socket_loopback_client: could not create socket\n" );
623 _fh_close(f);
624 return -1;
625 }
626
627 f->fh_socket = s;
628 if(connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
629 D("socket_loopback_client: could not connect to %s:%d\n", type != SOCK_STREAM ? "udp" : "tcp", port );
630 _fh_close(f);
631 return -1;
632 }
633 snprintf( f->name, sizeof(f->name), "%d(lo-client:%s%d)", _fh_to_int(f), type != SOCK_STREAM ? "udp:" : "", port );
634 D( "socket_loopback_client: port %d type %s => fd %d\n", port, type != SOCK_STREAM ? "udp" : "tcp", _fh_to_int(f) );
635 return _fh_to_int(f);
636}
637
638#define LISTEN_BACKLOG 4
639
640int socket_loopback_server(int port, int type)
641{
642 FH f = _fh_alloc( &_fh_socket_class );
643 struct sockaddr_in addr;
644 SOCKET s;
645 int n;
646
647 if (!f) {
648 return -1;
649 }
650
651 if (!_winsock_init)
652 _init_winsock();
653
654 memset(&addr, 0, sizeof(addr));
655 addr.sin_family = AF_INET;
656 addr.sin_port = htons(port);
657 addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
658
659 s = socket(AF_INET, type, 0);
660 if(s == INVALID_SOCKET) return -1;
661
662 f->fh_socket = s;
663
664 n = 1;
665 setsockopt(s, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (const char*)&n, sizeof(n));
666
667 if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
668 _fh_close(f);
669 return -1;
670 }
671 if (type == SOCK_STREAM) {
672 int ret;
673
674 ret = listen(s, LISTEN_BACKLOG);
675 if (ret < 0) {
676 _fh_close(f);
677 return -1;
678 }
679 }
680 snprintf( f->name, sizeof(f->name), "%d(lo-server:%s%d)", _fh_to_int(f), type != SOCK_STREAM ? "udp:" : "", port );
681 D( "socket_loopback_server: port %d type %s => fd %d\n", port, type != SOCK_STREAM ? "udp" : "tcp", _fh_to_int(f) );
682 return _fh_to_int(f);
683}
684
685
686int socket_network_client(const char *host, int port, int type)
687{
688 FH f = _fh_alloc( &_fh_socket_class );
689 struct hostent *hp;
690 struct sockaddr_in addr;
691 SOCKET s;
692
693 if (!f)
694 return -1;
695
696 if (!_winsock_init)
697 _init_winsock();
698
699 hp = gethostbyname(host);
700 if(hp == 0) {
701 _fh_close(f);
702 return -1;
703 }
704
705 memset(&addr, 0, sizeof(addr));
706 addr.sin_family = hp->h_addrtype;
707 addr.sin_port = htons(port);
708 memcpy(&addr.sin_addr, hp->h_addr, hp->h_length);
709
710 s = socket(hp->h_addrtype, type, 0);
711 if(s == INVALID_SOCKET) {
712 _fh_close(f);
713 return -1;
714 }
715 f->fh_socket = s;
716
717 if(connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
718 _fh_close(f);
719 return -1;
720 }
721
722 snprintf( f->name, sizeof(f->name), "%d(net-client:%s%d)", _fh_to_int(f), type != SOCK_STREAM ? "udp:" : "", port );
723 D( "socket_network_client: host '%s' port %d type %s => fd %d\n", host, port, type != SOCK_STREAM ? "udp" : "tcp", _fh_to_int(f) );
724 return _fh_to_int(f);
725}
726
727
Elliott Hughes0bff5bd2014-05-20 12:01:29 -0700728int socket_network_client_timeout(const char *host, int port, int type, int timeout)
729{
730 // TODO: implement timeouts for Windows.
731 return socket_network_client(host, port, type);
732}
733
734
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800735int socket_inaddr_any_server(int port, int type)
736{
737 FH f = _fh_alloc( &_fh_socket_class );
738 struct sockaddr_in addr;
739 SOCKET s;
740 int n;
741
742 if (!f)
743 return -1;
744
745 if (!_winsock_init)
746 _init_winsock();
747
748 memset(&addr, 0, sizeof(addr));
749 addr.sin_family = AF_INET;
750 addr.sin_port = htons(port);
751 addr.sin_addr.s_addr = htonl(INADDR_ANY);
752
753 s = socket(AF_INET, type, 0);
754 if(s == INVALID_SOCKET) {
755 _fh_close(f);
756 return -1;
757 }
758
759 f->fh_socket = s;
760 n = 1;
761 setsockopt(s, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (const char*)&n, sizeof(n));
762
763 if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
764 _fh_close(f);
765 return -1;
766 }
767
768 if (type == SOCK_STREAM) {
769 int ret;
770
771 ret = listen(s, LISTEN_BACKLOG);
772 if (ret < 0) {
773 _fh_close(f);
774 return -1;
775 }
776 }
777 snprintf( f->name, sizeof(f->name), "%d(any-server:%s%d)", _fh_to_int(f), type != SOCK_STREAM ? "udp:" : "", port );
778 D( "socket_inaddr_server: port %d type %s => fd %d\n", port, type != SOCK_STREAM ? "udp" : "tcp", _fh_to_int(f) );
779 return _fh_to_int(f);
780}
781
782#undef accept
783int adb_socket_accept(int serverfd, struct sockaddr* addr, socklen_t *addrlen)
784{
785 FH serverfh = _fh_from_int(serverfd);
786 FH fh;
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200787
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800788 if ( !serverfh || serverfh->clazz != &_fh_socket_class ) {
789 D( "adb_socket_accept: invalid fd %d\n", serverfd );
790 return -1;
791 }
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200792
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800793 fh = _fh_alloc( &_fh_socket_class );
794 if (!fh) {
795 D( "adb_socket_accept: not enough memory to allocate accepted socket descriptor\n" );
796 return -1;
797 }
798
799 fh->fh_socket = accept( serverfh->fh_socket, addr, addrlen );
800 if (fh->fh_socket == INVALID_SOCKET) {
801 _fh_close( fh );
802 D( "adb_socket_accept: accept on fd %d return error %ld\n", serverfd, GetLastError() );
803 return -1;
804 }
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200805
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800806 snprintf( fh->name, sizeof(fh->name), "%d(accept:%s)", _fh_to_int(fh), serverfh->name );
807 D( "adb_socket_accept on fd %d returns fd %d\n", serverfd, _fh_to_int(fh) );
808 return _fh_to_int(fh);
809}
810
811
Spencer Lowf055c192015-01-25 14:40:16 -0800812int adb_setsockopt( int fd, int level, int optname, const void* optval, socklen_t optlen )
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800813{
814 FH fh = _fh_from_int(fd);
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +0200815
Spencer Lowf055c192015-01-25 14:40:16 -0800816 if ( !fh || fh->clazz != &_fh_socket_class ) {
817 D("adb_setsockopt: invalid fd %d\n", fd);
818 return -1;
819 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800820
Spencer Lowf055c192015-01-25 14:40:16 -0800821 return setsockopt( fh->fh_socket, level, optname, optval, optlen );
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800822}
823
824/**************************************************************************/
825/**************************************************************************/
826/***** *****/
827/***** emulated socketpairs *****/
828/***** *****/
829/**************************************************************************/
830/**************************************************************************/
831
832/* we implement socketpairs directly in use space for the following reasons:
833 * - it avoids copying data from/to the Nt kernel
834 * - it allows us to implement fdevent hooks easily and cheaply, something
835 * that is not possible with standard Win32 pipes !!
836 *
837 * basically, we use two circular buffers, each one corresponding to a given
838 * direction.
839 *
840 * each buffer is implemented as two regions:
841 *
842 * region A which is (a_start,a_end)
843 * region B which is (0, b_end) with b_end <= a_start
844 *
845 * an empty buffer has: a_start = a_end = b_end = 0
846 *
847 * a_start is the pointer where we start reading data
848 * a_end is the pointer where we start writing data, unless it is BUFFER_SIZE,
849 * then you start writing at b_end
850 *
851 * the buffer is full when b_end == a_start && a_end == BUFFER_SIZE
852 *
853 * there is room when b_end < a_start || a_end < BUFER_SIZE
854 *
855 * when reading, a_start is incremented, it a_start meets a_end, then
856 * we do: a_start = 0, a_end = b_end, b_end = 0, and keep going on..
857 */
858
859#define BIP_BUFFER_SIZE 4096
860
861#if 0
862#include <stdio.h>
863# define BIPD(x) D x
864# define BIPDUMP bip_dump_hex
865
866static void bip_dump_hex( const unsigned char* ptr, size_t len )
867{
868 int nn, len2 = len;
869
870 if (len2 > 8) len2 = 8;
871
Vladimir Chtchetkinece480832011-11-30 10:20:27 -0800872 for (nn = 0; nn < len2; nn++)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800873 printf("%02x", ptr[nn]);
874 printf(" ");
875
876 for (nn = 0; nn < len2; nn++) {
877 int c = ptr[nn];
878 if (c < 32 || c > 127)
879 c = '.';
880 printf("%c", c);
881 }
882 printf("\n");
883 fflush(stdout);
884}
885
886#else
887# define BIPD(x) do {} while (0)
888# define BIPDUMP(p,l) BIPD(p)
889#endif
890
891typedef struct BipBufferRec_
892{
893 int a_start;
894 int a_end;
895 int b_end;
896 int fdin;
897 int fdout;
898 int closed;
899 int can_write; /* boolean */
900 HANDLE evt_write; /* event signaled when one can write to a buffer */
901 int can_read; /* boolean */
902 HANDLE evt_read; /* event signaled when one can read from a buffer */
903 CRITICAL_SECTION lock;
904 unsigned char buff[ BIP_BUFFER_SIZE ];
905
906} BipBufferRec, *BipBuffer;
907
908static void
909bip_buffer_init( BipBuffer buffer )
910{
911 D( "bit_buffer_init %p\n", buffer );
912 buffer->a_start = 0;
913 buffer->a_end = 0;
914 buffer->b_end = 0;
915 buffer->can_write = 1;
916 buffer->can_read = 0;
917 buffer->fdin = 0;
918 buffer->fdout = 0;
919 buffer->closed = 0;
920 buffer->evt_write = CreateEvent( NULL, TRUE, TRUE, NULL );
921 buffer->evt_read = CreateEvent( NULL, TRUE, FALSE, NULL );
922 InitializeCriticalSection( &buffer->lock );
923}
924
925static void
926bip_buffer_close( BipBuffer bip )
927{
928 bip->closed = 1;
929
930 if (!bip->can_read) {
931 SetEvent( bip->evt_read );
932 }
933 if (!bip->can_write) {
934 SetEvent( bip->evt_write );
935 }
936}
937
938static void
939bip_buffer_done( BipBuffer bip )
940{
941 BIPD(( "bip_buffer_done: %d->%d\n", bip->fdin, bip->fdout ));
942 CloseHandle( bip->evt_read );
943 CloseHandle( bip->evt_write );
944 DeleteCriticalSection( &bip->lock );
945}
946
947static int
948bip_buffer_write( BipBuffer bip, const void* src, int len )
949{
950 int avail, count = 0;
951
952 if (len <= 0)
953 return 0;
954
955 BIPD(( "bip_buffer_write: enter %d->%d len %d\n", bip->fdin, bip->fdout, len ));
956 BIPDUMP( src, len );
957
958 EnterCriticalSection( &bip->lock );
959
960 while (!bip->can_write) {
961 int ret;
962 LeaveCriticalSection( &bip->lock );
963
964 if (bip->closed) {
965 errno = EPIPE;
966 return -1;
967 }
968 /* spinlocking here is probably unfair, but let's live with it */
969 ret = WaitForSingleObject( bip->evt_write, INFINITE );
970 if (ret != WAIT_OBJECT_0) { /* buffer probably closed */
971 D( "bip_buffer_write: error %d->%d WaitForSingleObject returned %d, error %ld\n", bip->fdin, bip->fdout, ret, GetLastError() );
972 return 0;
973 }
974 if (bip->closed) {
975 errno = EPIPE;
976 return -1;
977 }
978 EnterCriticalSection( &bip->lock );
979 }
980
981 BIPD(( "bip_buffer_write: exec %d->%d len %d\n", bip->fdin, bip->fdout, len ));
982
983 avail = BIP_BUFFER_SIZE - bip->a_end;
984 if (avail > 0)
985 {
986 /* we can append to region A */
987 if (avail > len)
988 avail = len;
989
990 memcpy( bip->buff + bip->a_end, src, avail );
Mark Salyzyn60299df2014-04-30 09:10:31 -0700991 src = (const char *)src + avail;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800992 count += avail;
993 len -= avail;
994
995 bip->a_end += avail;
996 if (bip->a_end == BIP_BUFFER_SIZE && bip->a_start == 0) {
997 bip->can_write = 0;
998 ResetEvent( bip->evt_write );
999 goto Exit;
1000 }
1001 }
1002
1003 if (len == 0)
1004 goto Exit;
1005
1006 avail = bip->a_start - bip->b_end;
1007 assert( avail > 0 ); /* since can_write is TRUE */
1008
1009 if (avail > len)
1010 avail = len;
1011
1012 memcpy( bip->buff + bip->b_end, src, avail );
1013 count += avail;
1014 bip->b_end += avail;
1015
1016 if (bip->b_end == bip->a_start) {
1017 bip->can_write = 0;
1018 ResetEvent( bip->evt_write );
1019 }
1020
1021Exit:
1022 assert( count > 0 );
1023
1024 if ( !bip->can_read ) {
1025 bip->can_read = 1;
1026 SetEvent( bip->evt_read );
1027 }
1028
Vladimir Chtchetkinece480832011-11-30 10:20:27 -08001029 BIPD(( "bip_buffer_write: exit %d->%d count %d (as=%d ae=%d be=%d cw=%d cr=%d\n",
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001030 bip->fdin, bip->fdout, count, bip->a_start, bip->a_end, bip->b_end, bip->can_write, bip->can_read ));
1031 LeaveCriticalSection( &bip->lock );
1032
1033 return count;
1034 }
1035
1036static int
1037bip_buffer_read( BipBuffer bip, void* dst, int len )
1038{
1039 int avail, count = 0;
1040
1041 if (len <= 0)
1042 return 0;
1043
1044 BIPD(( "bip_buffer_read: enter %d->%d len %d\n", bip->fdin, bip->fdout, len ));
1045
1046 EnterCriticalSection( &bip->lock );
1047 while ( !bip->can_read )
1048 {
1049#if 0
1050 LeaveCriticalSection( &bip->lock );
1051 errno = EAGAIN;
1052 return -1;
Vladimir Chtchetkinece480832011-11-30 10:20:27 -08001053#else
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001054 int ret;
1055 LeaveCriticalSection( &bip->lock );
1056
1057 if (bip->closed) {
1058 errno = EPIPE;
1059 return -1;
1060 }
1061
1062 ret = WaitForSingleObject( bip->evt_read, INFINITE );
1063 if (ret != WAIT_OBJECT_0) { /* probably closed buffer */
1064 D( "bip_buffer_read: error %d->%d WaitForSingleObject returned %d, error %ld\n", bip->fdin, bip->fdout, ret, GetLastError());
1065 return 0;
1066 }
1067 if (bip->closed) {
1068 errno = EPIPE;
1069 return -1;
1070 }
1071 EnterCriticalSection( &bip->lock );
1072#endif
1073 }
1074
1075 BIPD(( "bip_buffer_read: exec %d->%d len %d\n", bip->fdin, bip->fdout, len ));
1076
1077 avail = bip->a_end - bip->a_start;
1078 assert( avail > 0 ); /* since can_read is TRUE */
1079
1080 if (avail > len)
1081 avail = len;
1082
1083 memcpy( dst, bip->buff + bip->a_start, avail );
Mark Salyzyn60299df2014-04-30 09:10:31 -07001084 dst = (char *)dst + avail;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001085 count += avail;
1086 len -= avail;
1087
1088 bip->a_start += avail;
1089 if (bip->a_start < bip->a_end)
1090 goto Exit;
1091
1092 bip->a_start = 0;
1093 bip->a_end = bip->b_end;
1094 bip->b_end = 0;
1095
1096 avail = bip->a_end;
1097 if (avail > 0) {
1098 if (avail > len)
1099 avail = len;
1100 memcpy( dst, bip->buff, avail );
1101 count += avail;
1102 bip->a_start += avail;
1103
1104 if ( bip->a_start < bip->a_end )
1105 goto Exit;
1106
1107 bip->a_start = bip->a_end = 0;
1108 }
1109
1110 bip->can_read = 0;
1111 ResetEvent( bip->evt_read );
1112
1113Exit:
1114 assert( count > 0 );
1115
1116 if (!bip->can_write ) {
1117 bip->can_write = 1;
1118 SetEvent( bip->evt_write );
1119 }
1120
1121 BIPDUMP( (const unsigned char*)dst - count, count );
Vladimir Chtchetkinece480832011-11-30 10:20:27 -08001122 BIPD(( "bip_buffer_read: exit %d->%d count %d (as=%d ae=%d be=%d cw=%d cr=%d\n",
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001123 bip->fdin, bip->fdout, count, bip->a_start, bip->a_end, bip->b_end, bip->can_write, bip->can_read ));
1124 LeaveCriticalSection( &bip->lock );
1125
1126 return count;
1127}
1128
Vladimir Chtchetkinece480832011-11-30 10:20:27 -08001129typedef struct SocketPairRec_
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001130{
1131 BipBufferRec a2b_bip;
1132 BipBufferRec b2a_bip;
1133 FH a_fd;
1134 int used;
1135
1136} SocketPairRec;
1137
1138void _fh_socketpair_init( FH f )
1139{
1140 f->fh_pair = NULL;
1141}
1142
1143static int
1144_fh_socketpair_close( FH f )
1145{
1146 if ( f->fh_pair ) {
1147 SocketPair pair = f->fh_pair;
1148
1149 if ( f == pair->a_fd ) {
1150 pair->a_fd = NULL;
1151 }
1152
1153 bip_buffer_close( &pair->b2a_bip );
1154 bip_buffer_close( &pair->a2b_bip );
1155
1156 if ( --pair->used == 0 ) {
1157 bip_buffer_done( &pair->b2a_bip );
1158 bip_buffer_done( &pair->a2b_bip );
1159 free( pair );
1160 }
1161 f->fh_pair = NULL;
1162 }
1163 return 0;
1164}
1165
1166static int
1167_fh_socketpair_lseek( FH f, int pos, int origin )
1168{
1169 errno = ESPIPE;
1170 return -1;
1171}
1172
1173static int
1174_fh_socketpair_read( FH f, void* buf, int len )
1175{
1176 SocketPair pair = f->fh_pair;
1177 BipBuffer bip;
1178
1179 if (!pair)
1180 return -1;
1181
1182 if ( f == pair->a_fd )
1183 bip = &pair->b2a_bip;
1184 else
1185 bip = &pair->a2b_bip;
1186
1187 return bip_buffer_read( bip, buf, len );
1188}
1189
1190static int
1191_fh_socketpair_write( FH f, const void* buf, int len )
1192{
1193 SocketPair pair = f->fh_pair;
1194 BipBuffer bip;
1195
1196 if (!pair)
1197 return -1;
1198
1199 if ( f == pair->a_fd )
1200 bip = &pair->a2b_bip;
1201 else
1202 bip = &pair->b2a_bip;
1203
1204 return bip_buffer_write( bip, buf, len );
1205}
1206
1207
1208static void _fh_socketpair_hook( FH f, int event, EventHook hook ); /* forward */
1209
1210static const FHClassRec _fh_socketpair_class =
1211{
1212 _fh_socketpair_init,
1213 _fh_socketpair_close,
1214 _fh_socketpair_lseek,
1215 _fh_socketpair_read,
1216 _fh_socketpair_write,
1217 _fh_socketpair_hook
1218};
1219
1220
1221int adb_socketpair( int sv[2] )
1222{
1223 FH fa, fb;
1224 SocketPair pair;
1225
1226 fa = _fh_alloc( &_fh_socketpair_class );
1227 fb = _fh_alloc( &_fh_socketpair_class );
1228
1229 if (!fa || !fb)
1230 goto Fail;
1231
1232 pair = malloc( sizeof(*pair) );
1233 if (pair == NULL) {
1234 D("adb_socketpair: not enough memory to allocate pipes\n" );
1235 goto Fail;
1236 }
1237
1238 bip_buffer_init( &pair->a2b_bip );
1239 bip_buffer_init( &pair->b2a_bip );
1240
1241 fa->fh_pair = pair;
1242 fb->fh_pair = pair;
1243 pair->used = 2;
1244 pair->a_fd = fa;
1245
1246 sv[0] = _fh_to_int(fa);
1247 sv[1] = _fh_to_int(fb);
1248
1249 pair->a2b_bip.fdin = sv[0];
1250 pair->a2b_bip.fdout = sv[1];
1251 pair->b2a_bip.fdin = sv[1];
1252 pair->b2a_bip.fdout = sv[0];
1253
1254 snprintf( fa->name, sizeof(fa->name), "%d(pair:%d)", sv[0], sv[1] );
1255 snprintf( fb->name, sizeof(fb->name), "%d(pair:%d)", sv[1], sv[0] );
1256 D( "adb_socketpair: returns (%d, %d)\n", sv[0], sv[1] );
1257 return 0;
1258
1259Fail:
1260 _fh_close(fb);
1261 _fh_close(fa);
1262 return -1;
1263}
1264
1265/**************************************************************************/
1266/**************************************************************************/
1267/***** *****/
1268/***** fdevents emulation *****/
1269/***** *****/
1270/***** this is a very simple implementation, we rely on the fact *****/
1271/***** that ADB doesn't use FDE_ERROR. *****/
1272/***** *****/
1273/**************************************************************************/
1274/**************************************************************************/
1275
1276#define FATAL(x...) fatal(__FUNCTION__, x)
1277
1278#if DEBUG
1279static void dump_fde(fdevent *fde, const char *info)
1280{
1281 fprintf(stderr,"FDE #%03d %c%c%c %s\n", fde->fd,
1282 fde->state & FDE_READ ? 'R' : ' ',
1283 fde->state & FDE_WRITE ? 'W' : ' ',
1284 fde->state & FDE_ERROR ? 'E' : ' ',
1285 info);
1286}
1287#else
1288#define dump_fde(fde, info) do { } while(0)
1289#endif
1290
1291#define FDE_EVENTMASK 0x00ff
1292#define FDE_STATEMASK 0xff00
1293
1294#define FDE_ACTIVE 0x0100
1295#define FDE_PENDING 0x0200
1296#define FDE_CREATED 0x0400
1297
1298static void fdevent_plist_enqueue(fdevent *node);
1299static void fdevent_plist_remove(fdevent *node);
1300static fdevent *fdevent_plist_dequeue(void);
1301
1302static fdevent list_pending = {
1303 .next = &list_pending,
1304 .prev = &list_pending,
1305};
1306
1307static fdevent **fd_table = 0;
1308static int fd_table_max = 0;
1309
1310typedef struct EventLooperRec_* EventLooper;
1311
1312typedef struct EventHookRec_
1313{
1314 EventHook next;
1315 FH fh;
1316 HANDLE h;
1317 int wanted; /* wanted event flags */
1318 int ready; /* ready event flags */
1319 void* aux;
1320 void (*prepare)( EventHook hook );
1321 int (*start) ( EventHook hook );
1322 void (*stop) ( EventHook hook );
1323 int (*check) ( EventHook hook );
1324 int (*peek) ( EventHook hook );
1325} EventHookRec;
1326
1327static EventHook _free_hooks;
1328
1329static EventHook
1330event_hook_alloc( FH fh )
1331{
1332 EventHook hook = _free_hooks;
1333 if (hook != NULL)
1334 _free_hooks = hook->next;
1335 else {
1336 hook = malloc( sizeof(*hook) );
1337 if (hook == NULL)
1338 fatal( "could not allocate event hook\n" );
1339 }
1340 hook->next = NULL;
1341 hook->fh = fh;
1342 hook->wanted = 0;
1343 hook->ready = 0;
1344 hook->h = INVALID_HANDLE_VALUE;
1345 hook->aux = NULL;
1346
1347 hook->prepare = NULL;
1348 hook->start = NULL;
1349 hook->stop = NULL;
1350 hook->check = NULL;
1351 hook->peek = NULL;
1352
1353 return hook;
1354}
1355
1356static void
1357event_hook_free( EventHook hook )
1358{
1359 hook->fh = NULL;
1360 hook->wanted = 0;
1361 hook->ready = 0;
1362 hook->next = _free_hooks;
1363 _free_hooks = hook;
1364}
1365
1366
1367static void
1368event_hook_signal( EventHook hook )
1369{
1370 FH f = hook->fh;
1371 int fd = _fh_to_int(f);
1372 fdevent* fde = fd_table[ fd - WIN32_FH_BASE ];
1373
1374 if (fde != NULL && fde->fd == fd) {
1375 if ((fde->state & FDE_PENDING) == 0) {
1376 fde->state |= FDE_PENDING;
1377 fdevent_plist_enqueue( fde );
1378 }
1379 fde->events |= hook->wanted;
1380 }
1381}
1382
1383
1384#define MAX_LOOPER_HANDLES WIN32_MAX_FHS
1385
1386typedef struct EventLooperRec_
1387{
1388 EventHook hooks;
1389 HANDLE htab[ MAX_LOOPER_HANDLES ];
1390 int htab_count;
1391
1392} EventLooperRec;
1393
1394static EventHook*
1395event_looper_find_p( EventLooper looper, FH fh )
1396{
1397 EventHook *pnode = &looper->hooks;
1398 EventHook node = *pnode;
1399 for (;;) {
1400 if ( node == NULL || node->fh == fh )
1401 break;
1402 pnode = &node->next;
1403 node = *pnode;
1404 }
1405 return pnode;
1406}
1407
1408static void
1409event_looper_hook( EventLooper looper, int fd, int events )
1410{
1411 FH f = _fh_from_int(fd);
1412 EventHook *pnode;
1413 EventHook node;
1414
1415 if (f == NULL) /* invalid arg */ {
1416 D("event_looper_hook: invalid fd=%d\n", fd);
1417 return;
1418 }
1419
1420 pnode = event_looper_find_p( looper, f );
1421 node = *pnode;
1422 if ( node == NULL ) {
1423 node = event_hook_alloc( f );
1424 node->next = *pnode;
1425 *pnode = node;
1426 }
1427
1428 if ( (node->wanted & events) != events ) {
1429 /* this should update start/stop/check/peek */
1430 D("event_looper_hook: call hook for %d (new=%x, old=%x)\n",
1431 fd, node->wanted, events);
1432 f->clazz->_fh_hook( f, events & ~node->wanted, node );
1433 node->wanted |= events;
1434 } else {
Vladimir Chtchetkinece480832011-11-30 10:20:27 -08001435 D("event_looper_hook: ignoring events %x for %d wanted=%x)\n",
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001436 events, fd, node->wanted);
1437 }
1438}
1439
1440static void
1441event_looper_unhook( EventLooper looper, int fd, int events )
1442{
1443 FH fh = _fh_from_int(fd);
1444 EventHook *pnode = event_looper_find_p( looper, fh );
1445 EventHook node = *pnode;
1446
1447 if (node != NULL) {
1448 int events2 = events & node->wanted;
1449 if ( events2 == 0 ) {
1450 D( "event_looper_unhook: events %x not registered for fd %d\n", events, fd );
1451 return;
1452 }
1453 node->wanted &= ~events2;
1454 if (!node->wanted) {
1455 *pnode = node->next;
1456 event_hook_free( node );
1457 }
1458 }
1459}
1460
Vladimir Chtchetkinece480832011-11-30 10:20:27 -08001461/*
1462 * A fixer for WaitForMultipleObjects on condition that there are more than 64
1463 * handles to wait on.
1464 *
1465 * In cetain cases DDMS may establish more than 64 connections with ADB. For
1466 * instance, this may happen if there are more than 64 processes running on a
1467 * device, or there are multiple devices connected (including the emulator) with
1468 * the combined number of running processes greater than 64. In this case using
1469 * WaitForMultipleObjects to wait on connection events simply wouldn't cut,
1470 * because of the API limitations (64 handles max). So, we need to provide a way
1471 * to scale WaitForMultipleObjects to accept an arbitrary number of handles. The
1472 * easiest (and "Microsoft recommended") way to do that would be dividing the
1473 * handle array into chunks with the chunk size less than 64, and fire up as many
1474 * waiting threads as there are chunks. Then each thread would wait on a chunk of
1475 * handles, and will report back to the caller which handle has been set.
1476 * Here is the implementation of that algorithm.
1477 */
1478
1479/* Number of handles to wait on in each wating thread. */
1480#define WAIT_ALL_CHUNK_SIZE 63
1481
1482/* Descriptor for a wating thread */
1483typedef struct WaitForAllParam {
1484 /* A handle to an event to signal when waiting is over. This handle is shared
1485 * accross all the waiting threads, so each waiting thread knows when any
1486 * other thread has exited, so it can exit too. */
1487 HANDLE main_event;
1488 /* Upon exit from a waiting thread contains the index of the handle that has
1489 * been signaled. The index is an absolute index of the signaled handle in
1490 * the original array. This pointer is shared accross all the waiting threads
1491 * and it's not guaranteed (due to a race condition) that when all the
1492 * waiting threads exit, the value contained here would indicate the first
1493 * handle that was signaled. This is fine, because the caller cares only
1494 * about any handle being signaled. It doesn't care about the order, nor
1495 * about the whole list of handles that were signaled. */
1496 LONG volatile *signaled_index;
1497 /* Array of handles to wait on in a waiting thread. */
1498 HANDLE* handles;
1499 /* Number of handles in 'handles' array to wait on. */
1500 int handles_count;
1501 /* Index inside the main array of the first handle in the 'handles' array. */
1502 int first_handle_index;
1503 /* Waiting thread handle. */
1504 HANDLE thread;
1505} WaitForAllParam;
1506
1507/* Waiting thread routine. */
1508static unsigned __stdcall
1509_in_waiter_thread(void* arg)
1510{
1511 HANDLE wait_on[WAIT_ALL_CHUNK_SIZE + 1];
1512 int res;
1513 WaitForAllParam* const param = (WaitForAllParam*)arg;
1514
1515 /* We have to wait on the main_event in order to be notified when any of the
1516 * sibling threads is exiting. */
1517 wait_on[0] = param->main_event;
1518 /* The rest of the handles go behind the main event handle. */
1519 memcpy(wait_on + 1, param->handles, param->handles_count * sizeof(HANDLE));
1520
1521 res = WaitForMultipleObjects(param->handles_count + 1, wait_on, FALSE, INFINITE);
1522 if (res > 0 && res < (param->handles_count + 1)) {
1523 /* One of the original handles got signaled. Save its absolute index into
1524 * the output variable. */
1525 InterlockedCompareExchange(param->signaled_index,
1526 res - 1L + param->first_handle_index, -1L);
1527 }
1528
1529 /* Notify the caller (and the siblings) that the wait is over. */
1530 SetEvent(param->main_event);
1531
1532 _endthreadex(0);
1533 return 0;
1534}
1535
1536/* WaitForMultipeObjects fixer routine.
1537 * Param:
1538 * handles Array of handles to wait on.
1539 * handles_count Number of handles in the array.
1540 * Return:
1541 * (>= 0 && < handles_count) - Index of the signaled handle in the array, or
1542 * WAIT_FAILED on an error.
1543 */
1544static int
1545_wait_for_all(HANDLE* handles, int handles_count)
1546{
1547 WaitForAllParam* threads;
1548 HANDLE main_event;
1549 int chunks, chunk, remains;
1550
1551 /* This variable is going to be accessed by several threads at the same time,
1552 * this is bound to fail randomly when the core is run on multi-core machines.
1553 * To solve this, we need to do the following (1 _and_ 2):
1554 * 1. Use the "volatile" qualifier to ensure the compiler doesn't optimize
1555 * out the reads/writes in this function unexpectedly.
1556 * 2. Ensure correct memory ordering. The "simple" way to do that is to wrap
1557 * all accesses inside a critical section. But we can also use
1558 * InterlockedCompareExchange() which always provide a full memory barrier
1559 * on Win32.
1560 */
1561 volatile LONG sig_index = -1;
1562
1563 /* Calculate number of chunks, and allocate thread param array. */
1564 chunks = handles_count / WAIT_ALL_CHUNK_SIZE;
1565 remains = handles_count % WAIT_ALL_CHUNK_SIZE;
1566 threads = (WaitForAllParam*)malloc((chunks + (remains ? 1 : 0)) *
1567 sizeof(WaitForAllParam));
1568 if (threads == NULL) {
1569 D("Unable to allocate thread array for %d handles.", handles_count);
1570 return (int)WAIT_FAILED;
1571 }
1572
1573 /* Create main event to wait on for all waiting threads. This is a "manualy
1574 * reset" event that will remain set once it was set. */
1575 main_event = CreateEvent(NULL, TRUE, FALSE, NULL);
1576 if (main_event == NULL) {
Andrew Hsiehb75d6f12014-05-07 20:21:11 +08001577 D("Unable to create main event. Error: %d", (int)GetLastError());
Vladimir Chtchetkinece480832011-11-30 10:20:27 -08001578 free(threads);
1579 return (int)WAIT_FAILED;
1580 }
1581
1582 /*
1583 * Initialize waiting thread parameters.
1584 */
1585
1586 for (chunk = 0; chunk < chunks; chunk++) {
1587 threads[chunk].main_event = main_event;
1588 threads[chunk].signaled_index = &sig_index;
1589 threads[chunk].first_handle_index = WAIT_ALL_CHUNK_SIZE * chunk;
1590 threads[chunk].handles = handles + threads[chunk].first_handle_index;
1591 threads[chunk].handles_count = WAIT_ALL_CHUNK_SIZE;
1592 }
1593 if (remains) {
1594 threads[chunk].main_event = main_event;
1595 threads[chunk].signaled_index = &sig_index;
1596 threads[chunk].first_handle_index = WAIT_ALL_CHUNK_SIZE * chunk;
1597 threads[chunk].handles = handles + threads[chunk].first_handle_index;
1598 threads[chunk].handles_count = remains;
1599 chunks++;
1600 }
1601
1602 /* Start the waiting threads. */
1603 for (chunk = 0; chunk < chunks; chunk++) {
1604 /* Note that using adb_thread_create is not appropriate here, since we
1605 * need a handle to wait on for thread termination. */
1606 threads[chunk].thread = (HANDLE)_beginthreadex(NULL, 0, _in_waiter_thread,
1607 &threads[chunk], 0, NULL);
1608 if (threads[chunk].thread == NULL) {
1609 /* Unable to create a waiter thread. Collapse. */
1610 D("Unable to create a waiting thread %d of %d. errno=%d",
1611 chunk, chunks, errno);
1612 chunks = chunk;
1613 SetEvent(main_event);
1614 break;
1615 }
1616 }
1617
1618 /* Wait on any of the threads to get signaled. */
1619 WaitForSingleObject(main_event, INFINITE);
1620
1621 /* Wait on all the waiting threads to exit. */
1622 for (chunk = 0; chunk < chunks; chunk++) {
1623 WaitForSingleObject(threads[chunk].thread, INFINITE);
1624 CloseHandle(threads[chunk].thread);
1625 }
1626
1627 CloseHandle(main_event);
1628 free(threads);
1629
1630
1631 const int ret = (int)InterlockedCompareExchange(&sig_index, -1, -1);
1632 return (ret >= 0) ? ret : (int)WAIT_FAILED;
1633}
1634
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001635static EventLooperRec win32_looper;
1636
1637static void fdevent_init(void)
1638{
1639 win32_looper.htab_count = 0;
1640 win32_looper.hooks = NULL;
1641}
1642
1643static void fdevent_connect(fdevent *fde)
1644{
1645 EventLooper looper = &win32_looper;
1646 int events = fde->state & FDE_EVENTMASK;
1647
1648 if (events != 0)
1649 event_looper_hook( looper, fde->fd, events );
1650}
1651
1652static void fdevent_disconnect(fdevent *fde)
1653{
1654 EventLooper looper = &win32_looper;
1655 int events = fde->state & FDE_EVENTMASK;
1656
1657 if (events != 0)
1658 event_looper_unhook( looper, fde->fd, events );
1659}
1660
1661static void fdevent_update(fdevent *fde, unsigned events)
1662{
1663 EventLooper looper = &win32_looper;
1664 unsigned events0 = fde->state & FDE_EVENTMASK;
1665
1666 if (events != events0) {
1667 int removes = events0 & ~events;
1668 int adds = events & ~events0;
1669 if (removes) {
1670 D("fdevent_update: remove %x from %d\n", removes, fde->fd);
1671 event_looper_unhook( looper, fde->fd, removes );
1672 }
1673 if (adds) {
1674 D("fdevent_update: add %x to %d\n", adds, fde->fd);
1675 event_looper_hook ( looper, fde->fd, adds );
1676 }
1677 }
1678}
1679
1680static void fdevent_process()
1681{
1682 EventLooper looper = &win32_looper;
1683 EventHook hook;
1684 int gotone = 0;
1685
1686 /* if we have at least one ready hook, execute it/them */
1687 for (hook = looper->hooks; hook; hook = hook->next) {
1688 hook->ready = 0;
1689 if (hook->prepare) {
1690 hook->prepare(hook);
1691 if (hook->ready != 0) {
1692 event_hook_signal( hook );
1693 gotone = 1;
1694 }
1695 }
1696 }
1697
1698 /* nothing's ready yet, so wait for something to happen */
1699 if (!gotone)
1700 {
1701 looper->htab_count = 0;
1702
Vladimir Chtchetkinece480832011-11-30 10:20:27 -08001703 for (hook = looper->hooks; hook; hook = hook->next)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001704 {
1705 if (hook->start && !hook->start(hook)) {
1706 D( "fdevent_process: error when starting a hook\n" );
1707 return;
1708 }
1709 if (hook->h != INVALID_HANDLE_VALUE) {
1710 int nn;
1711
1712 for (nn = 0; nn < looper->htab_count; nn++)
1713 {
1714 if ( looper->htab[nn] == hook->h )
1715 goto DontAdd;
1716 }
1717 looper->htab[ looper->htab_count++ ] = hook->h;
1718 DontAdd:
1719 ;
1720 }
1721 }
1722
1723 if (looper->htab_count == 0) {
1724 D( "fdevent_process: nothing to wait for !!\n" );
1725 return;
1726 }
1727
1728 do
1729 {
1730 int wait_ret;
1731
1732 D( "adb_win32: waiting for %d events\n", looper->htab_count );
1733 if (looper->htab_count > MAXIMUM_WAIT_OBJECTS) {
Vladimir Chtchetkinece480832011-11-30 10:20:27 -08001734 D("handle count %d exceeds MAXIMUM_WAIT_OBJECTS.\n", looper->htab_count);
1735 wait_ret = _wait_for_all(looper->htab, looper->htab_count);
1736 } else {
1737 wait_ret = WaitForMultipleObjects( looper->htab_count, looper->htab, FALSE, INFINITE );
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001738 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001739 if (wait_ret == (int)WAIT_FAILED) {
1740 D( "adb_win32: wait failed, error %ld\n", GetLastError() );
1741 } else {
1742 D( "adb_win32: got one (index %d)\n", wait_ret );
1743
1744 /* according to Cygwin, some objects like consoles wake up on "inappropriate" events
1745 * like mouse movements. we need to filter these with the "check" function
1746 */
1747 if ((unsigned)wait_ret < (unsigned)looper->htab_count)
1748 {
1749 for (hook = looper->hooks; hook; hook = hook->next)
1750 {
1751 if ( looper->htab[wait_ret] == hook->h &&
1752 (!hook->check || hook->check(hook)) )
1753 {
1754 D( "adb_win32: signaling %s for %x\n", hook->fh->name, hook->ready );
1755 event_hook_signal( hook );
1756 gotone = 1;
1757 break;
1758 }
1759 }
1760 }
1761 }
1762 }
1763 while (!gotone);
1764
1765 for (hook = looper->hooks; hook; hook = hook->next) {
1766 if (hook->stop)
1767 hook->stop( hook );
1768 }
1769 }
1770
1771 for (hook = looper->hooks; hook; hook = hook->next) {
1772 if (hook->peek && hook->peek(hook))
1773 event_hook_signal( hook );
1774 }
1775}
1776
1777
1778static void fdevent_register(fdevent *fde)
1779{
1780 int fd = fde->fd - WIN32_FH_BASE;
1781
1782 if(fd < 0) {
1783 FATAL("bogus negative fd (%d)\n", fde->fd);
1784 }
1785
1786 if(fd >= fd_table_max) {
1787 int oldmax = fd_table_max;
1788 if(fde->fd > 32000) {
1789 FATAL("bogus huuuuge fd (%d)\n", fde->fd);
1790 }
1791 if(fd_table_max == 0) {
1792 fdevent_init();
1793 fd_table_max = 256;
1794 }
1795 while(fd_table_max <= fd) {
1796 fd_table_max *= 2;
1797 }
1798 fd_table = realloc(fd_table, sizeof(fdevent*) * fd_table_max);
1799 if(fd_table == 0) {
1800 FATAL("could not expand fd_table to %d entries\n", fd_table_max);
1801 }
1802 memset(fd_table + oldmax, 0, sizeof(int) * (fd_table_max - oldmax));
1803 }
1804
1805 fd_table[fd] = fde;
1806}
1807
1808static void fdevent_unregister(fdevent *fde)
1809{
1810 int fd = fde->fd - WIN32_FH_BASE;
1811
1812 if((fd < 0) || (fd >= fd_table_max)) {
1813 FATAL("fd out of range (%d)\n", fde->fd);
1814 }
1815
1816 if(fd_table[fd] != fde) {
1817 FATAL("fd_table out of sync");
1818 }
1819
1820 fd_table[fd] = 0;
1821
1822 if(!(fde->state & FDE_DONT_CLOSE)) {
1823 dump_fde(fde, "close");
1824 adb_close(fde->fd);
1825 }
1826}
1827
1828static void fdevent_plist_enqueue(fdevent *node)
1829{
1830 fdevent *list = &list_pending;
1831
1832 node->next = list;
1833 node->prev = list->prev;
1834 node->prev->next = node;
1835 list->prev = node;
1836}
1837
1838static void fdevent_plist_remove(fdevent *node)
1839{
1840 node->prev->next = node->next;
1841 node->next->prev = node->prev;
1842 node->next = 0;
1843 node->prev = 0;
1844}
1845
1846static fdevent *fdevent_plist_dequeue(void)
1847{
1848 fdevent *list = &list_pending;
1849 fdevent *node = list->next;
1850
1851 if(node == list) return 0;
1852
1853 list->next = node->next;
1854 list->next->prev = list;
1855 node->next = 0;
1856 node->prev = 0;
1857
1858 return node;
1859}
1860
1861fdevent *fdevent_create(int fd, fd_func func, void *arg)
1862{
1863 fdevent *fde = (fdevent*) malloc(sizeof(fdevent));
1864 if(fde == 0) return 0;
1865 fdevent_install(fde, fd, func, arg);
1866 fde->state |= FDE_CREATED;
1867 return fde;
1868}
1869
1870void fdevent_destroy(fdevent *fde)
1871{
1872 if(fde == 0) return;
1873 if(!(fde->state & FDE_CREATED)) {
1874 FATAL("fde %p not created by fdevent_create()\n", fde);
1875 }
1876 fdevent_remove(fde);
1877}
1878
Vladimir Chtchetkinece480832011-11-30 10:20:27 -08001879void fdevent_install(fdevent *fde, int fd, fd_func func, void *arg)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001880{
1881 memset(fde, 0, sizeof(fdevent));
1882 fde->state = FDE_ACTIVE;
1883 fde->fd = fd;
1884 fde->func = func;
1885 fde->arg = arg;
1886
1887 fdevent_register(fde);
1888 dump_fde(fde, "connect");
1889 fdevent_connect(fde);
1890 fde->state |= FDE_ACTIVE;
1891}
1892
1893void fdevent_remove(fdevent *fde)
1894{
1895 if(fde->state & FDE_PENDING) {
1896 fdevent_plist_remove(fde);
1897 }
1898
1899 if(fde->state & FDE_ACTIVE) {
1900 fdevent_disconnect(fde);
Vladimir Chtchetkinece480832011-11-30 10:20:27 -08001901 dump_fde(fde, "disconnect");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001902 fdevent_unregister(fde);
1903 }
1904
1905 fde->state = 0;
1906 fde->events = 0;
1907}
1908
1909
1910void fdevent_set(fdevent *fde, unsigned events)
1911{
1912 events &= FDE_EVENTMASK;
1913
1914 if((fde->state & FDE_EVENTMASK) == (int)events) return;
1915
1916 if(fde->state & FDE_ACTIVE) {
1917 fdevent_update(fde, events);
1918 dump_fde(fde, "update");
1919 }
1920
1921 fde->state = (fde->state & FDE_STATEMASK) | events;
1922
1923 if(fde->state & FDE_PENDING) {
1924 /* if we're pending, make sure
1925 ** we don't signal an event that
1926 ** is no longer wanted.
1927 */
1928 fde->events &= (~events);
1929 if(fde->events == 0) {
1930 fdevent_plist_remove(fde);
1931 fde->state &= (~FDE_PENDING);
1932 }
1933 }
1934}
1935
1936void fdevent_add(fdevent *fde, unsigned events)
1937{
1938 fdevent_set(
1939 fde, (fde->state & FDE_EVENTMASK) | (events & FDE_EVENTMASK));
1940}
1941
1942void fdevent_del(fdevent *fde, unsigned events)
1943{
1944 fdevent_set(
1945 fde, (fde->state & FDE_EVENTMASK) & (~(events & FDE_EVENTMASK)));
1946}
1947
1948void fdevent_loop()
1949{
1950 fdevent *fde;
1951
1952 for(;;) {
1953#if DEBUG
1954 fprintf(stderr,"--- ---- waiting for events\n");
1955#endif
1956 fdevent_process();
1957
1958 while((fde = fdevent_plist_dequeue())) {
1959 unsigned events = fde->events;
1960 fde->events = 0;
1961 fde->state &= (~FDE_PENDING);
1962 dump_fde(fde, "callback");
1963 fde->func(fde->fd, events, fde->arg);
1964 }
1965 }
1966}
1967
1968/** FILE EVENT HOOKS
1969 **/
David 'Digit' Turnerf6330a22009-05-18 17:36:28 +02001970
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001971static void _event_file_prepare( EventHook hook )
1972{
1973 if (hook->wanted & (FDE_READ|FDE_WRITE)) {
1974 /* we can always read/write */
1975 hook->ready |= hook->wanted & (FDE_READ|FDE_WRITE);
1976 }
1977}
1978
1979static int _event_file_peek( EventHook hook )
1980{
1981 return (hook->wanted & (FDE_READ|FDE_WRITE));
1982}
1983
1984static void _fh_file_hook( FH f, int events, EventHook hook )
1985{
1986 hook->h = f->fh_handle;
1987 hook->prepare = _event_file_prepare;
1988 hook->peek = _event_file_peek;
1989}
1990
1991/** SOCKET EVENT HOOKS
1992 **/
1993
1994static void _event_socket_verify( EventHook hook, WSANETWORKEVENTS* evts )
1995{
1996 if ( evts->lNetworkEvents & (FD_READ|FD_ACCEPT|FD_CLOSE) ) {
1997 if (hook->wanted & FDE_READ)
1998 hook->ready |= FDE_READ;
1999 if ((evts->iErrorCode[FD_READ] != 0) && hook->wanted & FDE_ERROR)
2000 hook->ready |= FDE_ERROR;
2001 }
2002 if ( evts->lNetworkEvents & (FD_WRITE|FD_CONNECT|FD_CLOSE) ) {
2003 if (hook->wanted & FDE_WRITE)
2004 hook->ready |= FDE_WRITE;
2005 if ((evts->iErrorCode[FD_WRITE] != 0) && hook->wanted & FDE_ERROR)
2006 hook->ready |= FDE_ERROR;
2007 }
2008 if ( evts->lNetworkEvents & FD_OOB ) {
2009 if (hook->wanted & FDE_ERROR)
2010 hook->ready |= FDE_ERROR;
2011 }
2012}
2013
2014static void _event_socket_prepare( EventHook hook )
2015{
2016 WSANETWORKEVENTS evts;
2017
2018 /* look if some of the events we want already happened ? */
2019 if (!WSAEnumNetworkEvents( hook->fh->fh_socket, NULL, &evts ))
2020 _event_socket_verify( hook, &evts );
2021}
2022
2023static int _socket_wanted_to_flags( int wanted )
2024{
2025 int flags = 0;
2026 if (wanted & FDE_READ)
2027 flags |= FD_READ | FD_ACCEPT | FD_CLOSE;
2028
2029 if (wanted & FDE_WRITE)
2030 flags |= FD_WRITE | FD_CONNECT | FD_CLOSE;
2031
2032 if (wanted & FDE_ERROR)
2033 flags |= FD_OOB;
2034
2035 return flags;
2036}
2037
2038static int _event_socket_start( EventHook hook )
2039{
2040 /* create an event which we're going to wait for */
2041 FH fh = hook->fh;
2042 long flags = _socket_wanted_to_flags( hook->wanted );
2043
2044 hook->h = fh->event;
2045 if (hook->h == INVALID_HANDLE_VALUE) {
2046 D( "_event_socket_start: no event for %s\n", fh->name );
2047 return 0;
2048 }
2049
2050 if ( flags != fh->mask ) {
2051 D( "_event_socket_start: hooking %s for %x (flags %ld)\n", hook->fh->name, hook->wanted, flags );
2052 if ( WSAEventSelect( fh->fh_socket, hook->h, flags ) ) {
2053 D( "_event_socket_start: WSAEventSelect() for %s failed, error %d\n", hook->fh->name, WSAGetLastError() );
2054 CloseHandle( hook->h );
2055 hook->h = INVALID_HANDLE_VALUE;
2056 exit(1);
2057 return 0;
2058 }
2059 fh->mask = flags;
2060 }
2061 return 1;
2062}
2063
2064static void _event_socket_stop( EventHook hook )
2065{
2066 hook->h = INVALID_HANDLE_VALUE;
2067}
2068
2069static int _event_socket_check( EventHook hook )
2070{
2071 int result = 0;
2072 FH fh = hook->fh;
2073 WSANETWORKEVENTS evts;
2074
2075 if (!WSAEnumNetworkEvents( fh->fh_socket, hook->h, &evts ) ) {
2076 _event_socket_verify( hook, &evts );
2077 result = (hook->ready != 0);
2078 if (result) {
2079 ResetEvent( hook->h );
2080 }
2081 }
2082 D( "_event_socket_check %s returns %d\n", fh->name, result );
2083 return result;
2084}
2085
2086static int _event_socket_peek( EventHook hook )
2087{
2088 WSANETWORKEVENTS evts;
2089 FH fh = hook->fh;
2090
2091 /* look if some of the events we want already happened ? */
2092 if (!WSAEnumNetworkEvents( fh->fh_socket, NULL, &evts )) {
2093 _event_socket_verify( hook, &evts );
2094 if (hook->ready)
2095 ResetEvent( hook->h );
2096 }
2097
2098 return hook->ready != 0;
2099}
2100
2101
2102
2103static void _fh_socket_hook( FH f, int events, EventHook hook )
2104{
2105 hook->prepare = _event_socket_prepare;
2106 hook->start = _event_socket_start;
2107 hook->stop = _event_socket_stop;
2108 hook->check = _event_socket_check;
2109 hook->peek = _event_socket_peek;
2110
2111 _event_socket_start( hook );
2112}
2113
2114/** SOCKETPAIR EVENT HOOKS
2115 **/
2116
2117static void _event_socketpair_prepare( EventHook hook )
2118{
2119 FH fh = hook->fh;
2120 SocketPair pair = fh->fh_pair;
2121 BipBuffer rbip = (pair->a_fd == fh) ? &pair->b2a_bip : &pair->a2b_bip;
2122 BipBuffer wbip = (pair->a_fd == fh) ? &pair->a2b_bip : &pair->b2a_bip;
2123
2124 if (hook->wanted & FDE_READ && rbip->can_read)
2125 hook->ready |= FDE_READ;
2126
Vladimir Chtchetkinece480832011-11-30 10:20:27 -08002127 if (hook->wanted & FDE_WRITE && wbip->can_write)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08002128 hook->ready |= FDE_WRITE;
2129 }
2130
2131 static int _event_socketpair_start( EventHook hook )
2132 {
2133 FH fh = hook->fh;
2134 SocketPair pair = fh->fh_pair;
2135 BipBuffer rbip = (pair->a_fd == fh) ? &pair->b2a_bip : &pair->a2b_bip;
2136 BipBuffer wbip = (pair->a_fd == fh) ? &pair->a2b_bip : &pair->b2a_bip;
2137
2138 if (hook->wanted == FDE_READ)
2139 hook->h = rbip->evt_read;
2140
2141 else if (hook->wanted == FDE_WRITE)
2142 hook->h = wbip->evt_write;
2143
2144 else {
2145 D("_event_socketpair_start: can't handle FDE_READ+FDE_WRITE\n" );
2146 return 0;
2147 }
Vladimir Chtchetkinece480832011-11-30 10:20:27 -08002148 D( "_event_socketpair_start: hook %s for %x wanted=%x\n",
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08002149 hook->fh->name, _fh_to_int(fh), hook->wanted);
2150 return 1;
2151}
2152
2153static int _event_socketpair_peek( EventHook hook )
2154{
2155 _event_socketpair_prepare( hook );
2156 return hook->ready != 0;
2157}
2158
2159static void _fh_socketpair_hook( FH fh, int events, EventHook hook )
2160{
2161 hook->prepare = _event_socketpair_prepare;
2162 hook->start = _event_socketpair_start;
2163 hook->peek = _event_socketpair_peek;
2164}
2165
2166
2167void
2168adb_sysdeps_init( void )
2169{
2170#define ADB_MUTEX(x) InitializeCriticalSection( & x );
2171#include "mutex_list.h"
2172 InitializeCriticalSection( &_win32_lock );
2173}
2174
Scott Anderson1b7a7e82012-06-05 17:54:27 -07002175/* Windows doesn't have strtok_r. Use the one from bionic. */
2176
2177/*
2178 * Copyright (c) 1988 Regents of the University of California.
2179 * All rights reserved.
2180 *
2181 * Redistribution and use in source and binary forms, with or without
2182 * modification, are permitted provided that the following conditions
2183 * are met:
2184 * 1. Redistributions of source code must retain the above copyright
2185 * notice, this list of conditions and the following disclaimer.
2186 * 2. Redistributions in binary form must reproduce the above copyright
2187 * notice, this list of conditions and the following disclaimer in the
2188 * documentation and/or other materials provided with the distribution.
2189 * 3. Neither the name of the University nor the names of its contributors
2190 * may be used to endorse or promote products derived from this software
2191 * without specific prior written permission.
2192 *
2193 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2194 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2195 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2196 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2197 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2198 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2199 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2200 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2201 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2202 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2203 * SUCH DAMAGE.
2204 */
2205
2206char *
2207adb_strtok_r(char *s, const char *delim, char **last)
2208{
2209 char *spanp;
2210 int c, sc;
2211 char *tok;
2212
2213
2214 if (s == NULL && (s = *last) == NULL)
2215 return (NULL);
2216
2217 /*
2218 * Skip (span) leading delimiters (s += strspn(s, delim), sort of).
2219 */
2220cont:
2221 c = *s++;
2222 for (spanp = (char *)delim; (sc = *spanp++) != 0;) {
2223 if (c == sc)
2224 goto cont;
2225 }
2226
2227 if (c == 0) { /* no non-delimiter characters */
2228 *last = NULL;
2229 return (NULL);
2230 }
2231 tok = s - 1;
2232
2233 /*
2234 * Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
2235 * Note that delim must have one NUL; we stop if we see that, too.
2236 */
2237 for (;;) {
2238 c = *s++;
2239 spanp = (char *)delim;
2240 do {
2241 if ((sc = *spanp++) == c) {
2242 if (c == 0)
2243 s = NULL;
2244 else
2245 s[-1] = 0;
2246 *last = s;
2247 return (tok);
2248 }
2249 } while (sc != 0);
2250 }
2251 /* NOTREACHED */
2252}