Merge korg/donut into korg/master
This commit is contained in:
commit
96d58f4f52
|
@ -21,6 +21,7 @@ else
|
|||
include $(addprefix $(LOCAL_PATH)/,$(addsuffix /Android.mk, \
|
||||
adb \
|
||||
libcutils \
|
||||
libsysutils \
|
||||
liblog \
|
||||
libnetutils \
|
||||
libpixelflinger \
|
||||
|
|
|
@ -7,7 +7,6 @@ LOCAL_PATH:= $(call my-dir)
|
|||
|
||||
# adb host tool
|
||||
# =========================================================
|
||||
ifneq ($(TARGET_SIMULATOR),true) # not 64 bit clean (also unused with the sim)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
# Default to a virtual (sockets) usb interface
|
||||
|
@ -54,10 +53,13 @@ LOCAL_SRC_FILES := \
|
|||
$(USB_SRCS) \
|
||||
shlist.c \
|
||||
utils.c \
|
||||
usb_vendors.c \
|
||||
|
||||
|
||||
ifneq ($(USE_SYSDEPS_WIN32),)
|
||||
LOCAL_SRC_FILES += sysdeps_win32.c
|
||||
else
|
||||
LOCAL_SRC_FILES += fdevent.c
|
||||
endif
|
||||
|
||||
LOCAL_CFLAGS += -O2 -g -DADB_HOST=1 -Wall -Wno-unused-parameter
|
||||
|
@ -77,7 +79,6 @@ ifeq ($(HOST_OS),windows)
|
|||
$(LOCAL_INSTALLED_MODULE): $(HOST_OUT_EXECUTABLES)/AdbWinApi.dll
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
# adbd device daemon
|
||||
# =========================================================
|
||||
|
@ -100,6 +101,7 @@ include $(CLEAR_VARS)
|
|||
|
||||
LOCAL_SRC_FILES := \
|
||||
adb.c \
|
||||
fdevent.c \
|
||||
transport.c \
|
||||
transport_local.c \
|
||||
transport_usb.c \
|
||||
|
|
49
adb/adb.c
49
adb/adb.c
|
@ -23,12 +23,15 @@
|
|||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "sysdeps.h"
|
||||
#include "adb.h"
|
||||
|
||||
#if !ADB_HOST
|
||||
#include <private/android_filesystem_config.h>
|
||||
#else
|
||||
#include "usb_vendors.h"
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -655,10 +658,25 @@ void start_logging(void)
|
|||
void start_device_log(void)
|
||||
{
|
||||
int fd;
|
||||
char path[100];
|
||||
char path[PATH_MAX];
|
||||
struct tm now;
|
||||
time_t t;
|
||||
char value[PROPERTY_VALUE_MAX];
|
||||
|
||||
snprintf(path, sizeof path, "/data/adb_%ld.txt", (long)time(NULL));
|
||||
fd = unix_open(path, O_WRONLY | O_CREAT | O_APPEND, 0640);
|
||||
// read the trace mask from persistent property persist.adb.trace_mask
|
||||
// give up if the property is not set or cannot be parsed
|
||||
property_get("persist.adb.trace_mask", value, "");
|
||||
if (sscanf(value, "%x", &adb_trace_mask) != 1)
|
||||
return;
|
||||
|
||||
adb_mkdir("/data/adb", 0775);
|
||||
tzset();
|
||||
time(&t);
|
||||
localtime_r(&t, &now);
|
||||
strftime(path, sizeof(path),
|
||||
"/data/adb/adb-%Y-%m-%d-%H-%M-%S.txt",
|
||||
&now);
|
||||
fd = unix_open(path, O_WRONLY | O_CREAT | O_TRUNC, 0640);
|
||||
if (fd < 0)
|
||||
return;
|
||||
|
||||
|
@ -669,11 +687,6 @@ void start_device_log(void)
|
|||
|
||||
fd = unix_open("/dev/null", O_RDONLY);
|
||||
dup2(fd, 0);
|
||||
|
||||
// log everything
|
||||
adb_trace_mask = ~0;
|
||||
// except TRACE_RWX is a bit too verbose
|
||||
adb_trace_mask &= ~TRACE_RWX;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -818,19 +831,6 @@ int adb_main(int is_daemon)
|
|||
#if !ADB_HOST
|
||||
int secure = 0;
|
||||
char value[PROPERTY_VALUE_MAX];
|
||||
|
||||
// prevent the OOM killer from killing us
|
||||
char text[64];
|
||||
snprintf(text, sizeof text, "/proc/%d/oom_adj", (int)getpid());
|
||||
int fd = adb_open(text, O_WRONLY);
|
||||
if (fd >= 0) {
|
||||
// -17 should make us immune to OOM
|
||||
snprintf(text, sizeof text, "%d", -17);
|
||||
adb_write(fd, text, strlen(text));
|
||||
adb_close(fd);
|
||||
} else {
|
||||
D("adb: unable to open %s\n", text);
|
||||
}
|
||||
#endif
|
||||
|
||||
atexit(adb_cleanup);
|
||||
|
@ -846,6 +846,7 @@ int adb_main(int is_daemon)
|
|||
|
||||
#if ADB_HOST
|
||||
HOST = 1;
|
||||
usb_vendors_init();
|
||||
usb_init();
|
||||
local_init();
|
||||
|
||||
|
@ -885,9 +886,10 @@ int adb_main(int is_daemon)
|
|||
** AID_INET to diagnose network issues (netcfg, ping)
|
||||
** AID_GRAPHICS to access the frame buffer
|
||||
** AID_NET_BT and AID_NET_BT_ADMIN to diagnose bluetooth (hcidump)
|
||||
** AID_SDCARD_RW to allow writing to the SD card
|
||||
*/
|
||||
gid_t groups[] = { AID_ADB, AID_LOG, AID_INPUT, AID_INET, AID_GRAPHICS,
|
||||
AID_NET_BT, AID_NET_BT_ADMIN };
|
||||
AID_NET_BT, AID_NET_BT_ADMIN, AID_SDCARD_RW };
|
||||
setgroups(sizeof(groups)/sizeof(groups[0]), groups);
|
||||
|
||||
/* then switch user and group to "shell" */
|
||||
|
@ -1088,9 +1090,8 @@ int main(int argc, char **argv)
|
|||
adb_device_banner = "recovery";
|
||||
recovery_mode = 1;
|
||||
}
|
||||
#if ADB_DEVICE_LOG
|
||||
|
||||
start_device_log();
|
||||
#endif
|
||||
return adb_main(0);
|
||||
#endif
|
||||
}
|
||||
|
|
21
adb/adb.h
21
adb/adb.h
|
@ -345,11 +345,6 @@ typedef enum {
|
|||
#endif
|
||||
|
||||
|
||||
/* set this to log to /data/adb/adb_<time>.txt on the device.
|
||||
* has no effect if the /data/adb/ directory does not exist.
|
||||
*/
|
||||
#define ADB_DEVICE_LOG 0
|
||||
|
||||
#if !TRACE_PACKETS
|
||||
#define print_packet(tag,p) do {} while (0)
|
||||
#endif
|
||||
|
@ -357,18 +352,10 @@ typedef enum {
|
|||
#define ADB_PORT 5037
|
||||
#define ADB_LOCAL_TRANSPORT_PORT 5555
|
||||
|
||||
// Google's USB Vendor ID
|
||||
#define VENDOR_ID_GOOGLE 0x18d1
|
||||
// HTC's USB Vendor ID
|
||||
#define VENDOR_ID_HTC 0x0bb4
|
||||
#define ADB_CLASS 0xff
|
||||
#define ADB_SUBCLASS 0x42
|
||||
#define ADB_PROTOCOL 0x1
|
||||
|
||||
// products for VENDOR_ID_GOOGLE
|
||||
#define PRODUCT_ID_SOONER 0xd00d // Sooner bootloader
|
||||
#define PRODUCT_ID_SOONER_COMP 0xdeed // Sooner composite device
|
||||
|
||||
// products for VENDOR_ID_HTC
|
||||
#define PRODUCT_ID_DREAM 0x0c01 // Dream bootloader
|
||||
#define PRODUCT_ID_DREAM_COMP 0x0c02 // Dream composite device
|
||||
|
||||
void local_init();
|
||||
int local_connect(int port);
|
||||
|
@ -382,7 +369,9 @@ int usb_close(usb_handle *h);
|
|||
void usb_kick(usb_handle *h);
|
||||
|
||||
/* used for USB device detection */
|
||||
#if ADB_HOST
|
||||
int is_adb_interface(int vid, int pid, int usb_class, int usb_subclass, int usb_protocol);
|
||||
#endif
|
||||
|
||||
unsigned host_to_le32(unsigned n);
|
||||
int adb_commandline(int argc, char **argv);
|
||||
|
|
|
@ -213,7 +213,7 @@ int adb_connect(const char *service)
|
|||
fprintf(stdout,"* daemon started successfully *\n");
|
||||
}
|
||||
/* give the server some time to start properly and detect devices */
|
||||
adb_sleep_ms(2000);
|
||||
adb_sleep_ms(3000);
|
||||
// fall through to _adb_connect
|
||||
} else {
|
||||
// if server was running, check its version to make sure it is not out of date
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include <cutils/fdevent.h>
|
||||
#include "fdevent.h"
|
||||
|
||||
#define TRACE(x...) fprintf(stderr,x)
|
||||
|
||||
|
@ -87,7 +87,7 @@ static void fdevent_init()
|
|||
{
|
||||
/* XXX: what's a good size for the passed in hint? */
|
||||
epoll_fd = epoll_create(256);
|
||||
|
||||
|
||||
if(epoll_fd < 0) {
|
||||
perror("epoll_create() failed");
|
||||
exit(1);
|
||||
|
@ -105,7 +105,7 @@ static void fdevent_connect(fdevent *fde)
|
|||
ev.events = 0;
|
||||
ev.data.ptr = fde;
|
||||
|
||||
#if 0
|
||||
#if 0
|
||||
if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fde->fd, &ev)) {
|
||||
perror("epoll_ctl() failed\n");
|
||||
exit(1);
|
||||
|
@ -116,7 +116,7 @@ static void fdevent_connect(fdevent *fde)
|
|||
static void fdevent_disconnect(fdevent *fde)
|
||||
{
|
||||
struct epoll_event ev;
|
||||
|
||||
|
||||
memset(&ev, 0, sizeof(ev));
|
||||
ev.events = 0;
|
||||
ev.data.ptr = fde;
|
||||
|
@ -133,9 +133,9 @@ static void fdevent_update(fdevent *fde, unsigned events)
|
|||
{
|
||||
struct epoll_event ev;
|
||||
int active;
|
||||
|
||||
|
||||
active = (fde->state & FDE_EVENTMASK) != 0;
|
||||
|
||||
|
||||
memset(&ev, 0, sizeof(ev));
|
||||
ev.events = 0;
|
||||
ev.data.ptr = fde;
|
||||
|
@ -241,7 +241,7 @@ static void fdevent_connect(fdevent *fde)
|
|||
static void fdevent_disconnect(fdevent *fde)
|
||||
{
|
||||
int i, n;
|
||||
|
||||
|
||||
FD_CLR(fde->fd, &read_fds);
|
||||
FD_CLR(fde->fd, &write_fds);
|
||||
FD_CLR(fde->fd, &error_fds);
|
||||
|
@ -283,9 +283,9 @@ static void fdevent_process()
|
|||
memcpy(&rfd, &read_fds, sizeof(fd_set));
|
||||
memcpy(&wfd, &write_fds, sizeof(fd_set));
|
||||
memcpy(&efd, &error_fds, sizeof(fd_set));
|
||||
|
||||
|
||||
n = select(select_n, &rfd, &wfd, &efd, 0);
|
||||
|
||||
|
||||
if(n < 0) {
|
||||
if(errno == EINTR) return;
|
||||
perror("select");
|
||||
|
@ -300,12 +300,12 @@ static void fdevent_process()
|
|||
|
||||
if(events) {
|
||||
n--;
|
||||
|
||||
|
||||
fde = fd_table[i];
|
||||
if(fde == 0) FATAL("missing fde for fd %d\n", i);
|
||||
|
||||
fde->events |= events;
|
||||
|
||||
|
||||
if(fde->state & FDE_PENDING) continue;
|
||||
fde->state |= FDE_PENDING;
|
||||
fdevent_plist_enqueue(fde);
|
||||
|
@ -320,7 +320,7 @@ static void fdevent_register(fdevent *fde)
|
|||
if(fde->fd < 0) {
|
||||
FATAL("bogus negative fd (%d)\n", fde->fd);
|
||||
}
|
||||
|
||||
|
||||
if(fde->fd >= fd_table_max) {
|
||||
int oldmax = fd_table_max;
|
||||
if(fde->fd > 32000) {
|
||||
|
@ -383,9 +383,9 @@ static fdevent *fdevent_plist_dequeue(void)
|
|||
{
|
||||
fdevent *list = &list_pending;
|
||||
fdevent *node = list->next;
|
||||
|
||||
|
||||
if(node == list) return 0;
|
||||
|
||||
|
||||
list->next = node->next;
|
||||
list->next->prev = list;
|
||||
node->next = 0;
|
||||
|
@ -449,9 +449,9 @@ void fdevent_remove(fdevent *fde)
|
|||
void fdevent_set(fdevent *fde, unsigned events)
|
||||
{
|
||||
events &= FDE_EVENTMASK;
|
||||
|
||||
|
||||
if((fde->state & FDE_EVENTMASK) == events) return;
|
||||
|
||||
|
||||
if(fde->state & FDE_ACTIVE) {
|
||||
fdevent_update(fde, events);
|
||||
dump_fde(fde, "update");
|
||||
|
@ -487,13 +487,13 @@ void fdevent_del(fdevent *fde, unsigned events)
|
|||
void fdevent_loop()
|
||||
{
|
||||
fdevent *fde;
|
||||
|
||||
|
||||
for(;;) {
|
||||
#if DEBUG
|
||||
fprintf(stderr,"--- ---- waiting for events\n");
|
||||
#endif
|
||||
fdevent_process();
|
||||
|
||||
|
||||
while((fde = fdevent_plist_dequeue())) {
|
||||
unsigned events = fde->events;
|
||||
fde->events = 0;
|
|
@ -17,10 +17,13 @@
|
|||
#ifndef __FDEVENT_H
|
||||
#define __FDEVENT_H
|
||||
|
||||
#include <stdint.h> /* for int64_t */
|
||||
|
||||
/* events that may be observed */
|
||||
#define FDE_READ 0x0001
|
||||
#define FDE_WRITE 0x0002
|
||||
#define FDE_ERROR 0x0004
|
||||
#define FDE_TIMEOUT 0x0008
|
||||
|
||||
/* features that may be set (via the events set/add/del interface) */
|
||||
#define FDE_DONT_CLOSE 0x0080
|
||||
|
@ -30,6 +33,8 @@ typedef struct fdevent fdevent;
|
|||
typedef void (*fd_func)(int fd, unsigned events, void *userdata);
|
||||
|
||||
/* Allocate and initialize a new fdevent object
|
||||
* Note: use FD_TIMER as 'fd' to create a fd-less object
|
||||
* (used to implement timers).
|
||||
*/
|
||||
fdevent *fdevent_create(int fd, fd_func func, void *arg);
|
||||
|
||||
|
@ -53,6 +58,8 @@ void fdevent_set(fdevent *fde, unsigned events);
|
|||
void fdevent_add(fdevent *fde, unsigned events);
|
||||
void fdevent_del(fdevent *fde, unsigned events);
|
||||
|
||||
void fdevent_set_timeout(fdevent *fde, int64_t timeout_ms);
|
||||
|
||||
/* loop forever, handling events.
|
||||
*/
|
||||
void fdevent_loop();
|
||||
|
@ -65,7 +72,7 @@ struct fdevent
|
|||
int fd;
|
||||
unsigned short state;
|
||||
unsigned short events;
|
||||
|
||||
|
||||
fd_func func;
|
||||
void *arg;
|
||||
};
|
|
@ -165,7 +165,7 @@ static int sync_start_readtime(int fd, const char *path)
|
|||
}
|
||||
|
||||
static int sync_finish_readtime(int fd, unsigned int *timestamp,
|
||||
unsigned int *mode, unsigned int *size)
|
||||
unsigned int *mode, unsigned int *size)
|
||||
{
|
||||
syncmsg msg;
|
||||
|
||||
|
@ -908,12 +908,12 @@ static int copy_remote_dir_local(int fd, const char *rpath, const char *lpath,
|
|||
unsigned int timestamp, mode, size;
|
||||
if (sync_finish_readtime(fd, ×tamp, &mode, &size))
|
||||
return 1;
|
||||
if (size == ci->size) {
|
||||
if (size == ci->size) {
|
||||
/* for links, we cannot update the atime/mtime */
|
||||
if ((S_ISREG(ci->mode & mode) && timestamp == ci->time) ||
|
||||
(S_ISLNK(ci->mode & mode) && timestamp >= ci->time))
|
||||
(S_ISLNK(ci->mode & mode) && timestamp >= ci->time))
|
||||
ci->flag = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <cutils/fdevent.h>
|
||||
#include "fdevent.h"
|
||||
#include "adb.h"
|
||||
|
||||
#include <linux/fb.h>
|
||||
|
|
|
@ -23,7 +23,7 @@ implementation to be much more robust.
|
|||
|
||||
|
||||
--- protocol overview and basics ---------------------------------------
|
||||
|
||||
|
||||
The transport layer deals in "messages", which consist of a 24 byte
|
||||
header followed (optionally) by a payload. The header consists of 6
|
||||
32 bit words which are sent across the wire in little endian format.
|
||||
|
@ -52,7 +52,7 @@ The identifiers "local-id" and "remote-id" are always relative to the
|
|||
reversed.
|
||||
|
||||
|
||||
|
||||
|
||||
--- CONNECT(version, maxdata, "system-identity-string") ----------------
|
||||
|
||||
The CONNECT message establishes the presence of a remote system.
|
||||
|
@ -114,7 +114,7 @@ is used to establish the connection). Nonetheless, the local-id MUST
|
|||
not change on later READY messages sent to the same stream.
|
||||
|
||||
|
||||
|
||||
|
||||
--- WRITE(0, remote-id, "data") ----------------------------------------
|
||||
|
||||
The WRITE message sends data to the recipient's stream identified by
|
||||
|
@ -172,7 +172,7 @@ to send across the wire.
|
|||
#define A_WRTE 0x45545257
|
||||
|
||||
|
||||
|
||||
|
||||
--- implementation details ---------------------------------------------
|
||||
|
||||
The core of the bridge program will use three threads. One thread
|
||||
|
|
|
@ -244,6 +244,18 @@ static int create_subprocess(const char *cmd, const char *arg0, const char *arg1
|
|||
cmd, strerror(errno), errno);
|
||||
exit(-1);
|
||||
} else {
|
||||
#if !ADB_HOST
|
||||
// set child's OOM adjustment to zero
|
||||
char text[64];
|
||||
snprintf(text, sizeof text, "/proc/%d/oom_adj", pid);
|
||||
int fd = adb_open(text, O_WRONLY);
|
||||
if (fd >= 0) {
|
||||
adb_write(fd, "0", 1);
|
||||
adb_close(fd);
|
||||
} else {
|
||||
D("adb: unable to open %s\n", text);
|
||||
}
|
||||
#endif
|
||||
return ptm;
|
||||
}
|
||||
#endif /* !HAVE_WIN32_PROC */
|
||||
|
|
|
@ -67,16 +67,16 @@ typedef void (*win_thread_func_t)(void* arg);
|
|||
|
||||
static __inline__ int adb_thread_create( adb_thread_t *thread, adb_thread_func_t func, void* arg)
|
||||
{
|
||||
thread->tid = _beginthread( (win_thread_func_t)func, 0, arg );
|
||||
if (thread->tid == (unsigned)-1L) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
thread->tid = _beginthread( (win_thread_func_t)func, 0, arg );
|
||||
if (thread->tid == (unsigned)-1L) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __inline__ void close_on_exec(int fd)
|
||||
{
|
||||
/* nothing really */
|
||||
/* nothing really */
|
||||
}
|
||||
|
||||
extern void disable_tcp_nagle(int fd);
|
||||
|
@ -138,7 +138,7 @@ static __inline__ int unix_write(int fd, const void* buf, size_t len)
|
|||
|
||||
static __inline__ int adb_open_mode(const char* path, int options, int mode)
|
||||
{
|
||||
return adb_open(path, options);
|
||||
return adb_open(path, options);
|
||||
}
|
||||
|
||||
static __inline__ int unix_open(const char* path, int options,...)
|
||||
|
@ -169,7 +169,7 @@ extern int socket_network_client(const char *host, int port, int type);
|
|||
extern int socket_loopback_server(int port, int type);
|
||||
extern int socket_inaddr_any_server(int port, int type);
|
||||
|
||||
/* normally provided by <cutils/fdevent.h> */
|
||||
/* normally provided by "fdevent.h" */
|
||||
|
||||
#define FDE_READ 0x0001
|
||||
#define FDE_WRITE 0x0002
|
||||
|
@ -203,7 +203,7 @@ struct fdevent {
|
|||
|
||||
static __inline__ void adb_sleep_ms( int mseconds )
|
||||
{
|
||||
Sleep( mseconds );
|
||||
Sleep( mseconds );
|
||||
}
|
||||
|
||||
extern int adb_socket_accept(int serverfd, struct sockaddr* addr, socklen_t *addrlen);
|
||||
|
@ -252,7 +252,7 @@ static __inline__ int adb_is_absolute_host_path( const char* path )
|
|||
|
||||
#else /* !_WIN32 a.k.a. Unix */
|
||||
|
||||
#include <cutils/fdevent.h>
|
||||
#include "fdevent.h"
|
||||
#include <cutils/sockets.h>
|
||||
#include <cutils/properties.h>
|
||||
#include <cutils/misc.h>
|
||||
|
@ -290,7 +290,7 @@ typedef pthread_mutex_t adb_mutex_t;
|
|||
|
||||
static __inline__ void close_on_exec(int fd)
|
||||
{
|
||||
fcntl( fd, F_SETFD, FD_CLOEXEC );
|
||||
fcntl( fd, F_SETFD, FD_CLOEXEC );
|
||||
}
|
||||
|
||||
static __inline__ int unix_open(const char* path, int options,...)
|
||||
|
@ -312,7 +312,7 @@ static __inline__ int unix_open(const char* path, int options,...)
|
|||
|
||||
static __inline__ int adb_open_mode( const char* pathname, int options, int mode )
|
||||
{
|
||||
return open( pathname, options, mode );
|
||||
return open( pathname, options, mode );
|
||||
}
|
||||
|
||||
|
||||
|
@ -368,11 +368,11 @@ static __inline__ int adb_creat(const char* path, int mode)
|
|||
{
|
||||
int fd = creat(path, mode);
|
||||
|
||||
if ( fd < 0 )
|
||||
return -1;
|
||||
if ( fd < 0 )
|
||||
return -1;
|
||||
|
||||
close_on_exec(fd);
|
||||
return fd;
|
||||
return fd;
|
||||
}
|
||||
#undef creat
|
||||
#define creat ___xxx_creat
|
||||
|
@ -439,12 +439,12 @@ static __inline__ int adb_socketpair( int sv[2] )
|
|||
|
||||
static __inline__ void adb_sleep_ms( int mseconds )
|
||||
{
|
||||
usleep( mseconds*1000 );
|
||||
usleep( mseconds*1000 );
|
||||
}
|
||||
|
||||
static __inline__ int adb_mkdir(const char* path, int mode)
|
||||
{
|
||||
return mkdir(path, mode);
|
||||
return mkdir(path, mode);
|
||||
}
|
||||
#undef mkdir
|
||||
#define mkdir ___xxx_mkdir
|
||||
|
|
|
@ -739,12 +739,12 @@ int adb_socket_accept(int serverfd, struct sockaddr* addr, socklen_t *addrle
|
|||
{
|
||||
FH serverfh = _fh_from_int(serverfd);
|
||||
FH fh;
|
||||
|
||||
|
||||
if ( !serverfh || serverfh->clazz != &_fh_socket_class ) {
|
||||
D( "adb_socket_accept: invalid fd %d\n", serverfd );
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
fh = _fh_alloc( &_fh_socket_class );
|
||||
if (!fh) {
|
||||
D( "adb_socket_accept: not enough memory to allocate accepted socket descriptor\n" );
|
||||
|
@ -757,7 +757,7 @@ int adb_socket_accept(int serverfd, struct sockaddr* addr, socklen_t *addrle
|
|||
D( "adb_socket_accept: accept on fd %d return error %ld\n", serverfd, GetLastError() );
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
snprintf( fh->name, sizeof(fh->name), "%d(accept:%s)", _fh_to_int(fh), serverfh->name );
|
||||
D( "adb_socket_accept on fd %d returns fd %d\n", serverfd, _fh_to_int(fh) );
|
||||
return _fh_to_int(fh);
|
||||
|
@ -768,7 +768,7 @@ void disable_tcp_nagle(int fd)
|
|||
{
|
||||
FH fh = _fh_from_int(fd);
|
||||
int on;
|
||||
|
||||
|
||||
if ( !fh || fh->clazz != &_fh_socket_class )
|
||||
return;
|
||||
|
||||
|
@ -1746,7 +1746,7 @@ void fdevent_loop()
|
|||
|
||||
/** FILE EVENT HOOKS
|
||||
**/
|
||||
|
||||
|
||||
static void _event_file_prepare( EventHook hook )
|
||||
{
|
||||
if (hook->wanted & (FDE_READ|FDE_WRITE)) {
|
||||
|
|
|
@ -23,6 +23,10 @@
|
|||
#define TRACE_TAG TRACE_TRANSPORT
|
||||
#include "adb.h"
|
||||
|
||||
#if ADB_HOST
|
||||
#include "usb_vendors.h"
|
||||
#endif
|
||||
|
||||
/* XXX better define? */
|
||||
#ifdef __ppc__
|
||||
#define H4(x) (((x) & 0xFF000000) >> 24) | (((x) & 0x00FF0000) >> 8) | (((x) & 0x0000FF00) << 8) | (((x) & 0x000000FF) << 24)
|
||||
|
@ -125,23 +129,21 @@ void init_usb_transport(atransport *t, usb_handle *h)
|
|||
#endif
|
||||
}
|
||||
|
||||
#if ADB_HOST
|
||||
int is_adb_interface(int vid, int pid, int usb_class, int usb_subclass, int usb_protocol)
|
||||
{
|
||||
if (vid == VENDOR_ID_GOOGLE) {
|
||||
/* might support adb */
|
||||
} else if (vid == VENDOR_ID_HTC) {
|
||||
/* might support adb */
|
||||
} else {
|
||||
/* not supported */
|
||||
return 0;
|
||||
}
|
||||
unsigned i;
|
||||
for (i = 0; i < vendorIdCount; i++) {
|
||||
if (vid == vendorIds[i]) {
|
||||
if (usb_class == ADB_CLASS && usb_subclass == ADB_SUBCLASS &&
|
||||
usb_protocol == ADB_PROTOCOL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* class:vendor (0xff) subclass:android (0x42) proto:adb (0x01) */
|
||||
if(usb_class == 0xff) {
|
||||
if((usb_subclass == 0x42) && (usb_protocol == 0x01)) {
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
|
401
adb/usb_osx.c
401
adb/usb_osx.c
|
@ -28,24 +28,12 @@
|
|||
|
||||
#define TRACE_TAG TRACE_USB
|
||||
#include "adb.h"
|
||||
#include "usb_vendors.h"
|
||||
|
||||
#define DBG D
|
||||
|
||||
typedef struct {
|
||||
int vid;
|
||||
int pid;
|
||||
} VendorProduct;
|
||||
|
||||
#define kSupportedDeviceCount 4
|
||||
VendorProduct kSupportedDevices[kSupportedDeviceCount] = {
|
||||
{ VENDOR_ID_GOOGLE, PRODUCT_ID_SOONER },
|
||||
{ VENDOR_ID_GOOGLE, PRODUCT_ID_SOONER_COMP },
|
||||
{ VENDOR_ID_HTC, PRODUCT_ID_DREAM },
|
||||
{ VENDOR_ID_HTC, PRODUCT_ID_DREAM_COMP },
|
||||
};
|
||||
|
||||
static IONotificationPortRef notificationPort = 0;
|
||||
static io_iterator_t notificationIterators[kSupportedDeviceCount];
|
||||
static io_iterator_t* notificationIterators;
|
||||
|
||||
struct usb_handle
|
||||
{
|
||||
|
@ -61,17 +49,20 @@ static pthread_mutex_t start_lock;
|
|||
static pthread_cond_t start_cond;
|
||||
|
||||
|
||||
static void AndroidDeviceAdded(void *refCon, io_iterator_t iterator);
|
||||
static void AndroidDeviceNotify(void *refCon, io_iterator_t iterator, natural_t messageType, void *messageArgument);
|
||||
static usb_handle* FindDeviceInterface(IOUSBDeviceInterface **dev, UInt16 vendor, UInt16 product);
|
||||
static void AndroidInterfaceAdded(void *refCon, io_iterator_t iterator);
|
||||
static void AndroidInterfaceNotify(void *refCon, io_iterator_t iterator,
|
||||
natural_t messageType,
|
||||
void *messageArgument);
|
||||
static usb_handle* CheckInterface(IOUSBInterfaceInterface **iface,
|
||||
UInt16 vendor, UInt16 product);
|
||||
|
||||
static int
|
||||
InitUSB()
|
||||
{
|
||||
CFMutableDictionaryRef matchingDict;
|
||||
CFRunLoopSourceRef runLoopSource;
|
||||
SInt32 vendor, product;
|
||||
int i;
|
||||
SInt32 vendor, if_subclass, if_protocol;
|
||||
unsigned i;
|
||||
|
||||
//* To set up asynchronous notifications, create a notification port and
|
||||
//* add its run loop event source to the program's run loop
|
||||
|
@ -81,51 +72,57 @@ InitUSB()
|
|||
|
||||
memset(notificationIterators, 0, sizeof(notificationIterators));
|
||||
|
||||
//* loop through all supported vendor/product pairs
|
||||
for (i = 0; i < kSupportedDeviceCount; i++) {
|
||||
//* Create our matching dictionary to find the Android device
|
||||
//* IOServiceAddMatchingNotification consumes the reference, so we do not need to release this
|
||||
matchingDict = IOServiceMatching(kIOUSBDeviceClassName);
|
||||
//* loop through all supported vendors
|
||||
for (i = 0; i < vendorIdCount; i++) {
|
||||
//* Create our matching dictionary to find the Android device's
|
||||
//* adb interface
|
||||
//* IOServiceAddMatchingNotification consumes the reference, so we do
|
||||
//* not need to release this
|
||||
matchingDict = IOServiceMatching(kIOUSBInterfaceClassName);
|
||||
|
||||
if (!matchingDict) {
|
||||
DBG("ERR: Couldn't create USB matching dictionary.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
//* Set up two matching dictionaries, one for each product ID we support.
|
||||
//* This will cause the kernel to notify us only if the vendor and product IDs match.
|
||||
vendor = kSupportedDevices[i].vid;
|
||||
product = kSupportedDevices[i].pid;
|
||||
CFDictionarySetValue(matchingDict, CFSTR(kUSBVendorID), CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vendor));
|
||||
CFDictionarySetValue(matchingDict, CFSTR(kUSBProductID), CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &product));
|
||||
|
||||
//* Now set up two notifications: one to be called when a raw device
|
||||
//* is first matched by the I/O Kit and another to be called when the
|
||||
//* device is terminated.
|
||||
//* we need to do this with each matching dictionary.
|
||||
//* Match based on vendor id, interface subclass and protocol
|
||||
vendor = vendorIds[i];
|
||||
if_subclass = ADB_SUBCLASS;
|
||||
if_protocol = ADB_PROTOCOL;
|
||||
CFDictionarySetValue(matchingDict, CFSTR(kUSBVendorID),
|
||||
CFNumberCreate(kCFAllocatorDefault,
|
||||
kCFNumberSInt32Type, &vendor));
|
||||
CFDictionarySetValue(matchingDict, CFSTR(kUSBInterfaceSubClass),
|
||||
CFNumberCreate(kCFAllocatorDefault,
|
||||
kCFNumberSInt32Type, &if_subclass));
|
||||
CFDictionarySetValue(matchingDict, CFSTR(kUSBInterfaceProtocol),
|
||||
CFNumberCreate(kCFAllocatorDefault,
|
||||
kCFNumberSInt32Type, &if_protocol));
|
||||
IOServiceAddMatchingNotification(
|
||||
notificationPort,
|
||||
kIOFirstMatchNotification,
|
||||
matchingDict,
|
||||
AndroidDeviceAdded,
|
||||
AndroidInterfaceAdded,
|
||||
NULL,
|
||||
¬ificationIterators[i]);
|
||||
|
||||
//* Iterate over set of matching devices to access already-present devices
|
||||
//* and to arm the notification
|
||||
AndroidDeviceAdded(NULL, notificationIterators[i]);
|
||||
//* Iterate over set of matching interfaces to access already-present
|
||||
//* devices and to arm the notification
|
||||
AndroidInterfaceAdded(NULL, notificationIterators[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
AndroidDeviceAdded(void *refCon, io_iterator_t iterator)
|
||||
AndroidInterfaceAdded(void *refCon, io_iterator_t iterator)
|
||||
{
|
||||
kern_return_t kr;
|
||||
io_service_t usbDevice;
|
||||
io_service_t usbInterface;
|
||||
IOCFPlugInInterface **plugInInterface = NULL;
|
||||
IOUSBDeviceInterface182 **dev = NULL;
|
||||
IOUSBInterfaceInterface220 **iface = NULL;
|
||||
IOUSBDeviceInterface197 **dev = NULL;
|
||||
HRESULT result;
|
||||
SInt32 score;
|
||||
UInt16 vendor;
|
||||
|
@ -133,28 +130,66 @@ AndroidDeviceAdded(void *refCon, io_iterator_t iterator)
|
|||
UInt8 serialIndex;
|
||||
char serial[256];
|
||||
|
||||
while ((usbDevice = IOIteratorNext(iterator))) {
|
||||
//* Create an intermediate plugin
|
||||
while ((usbInterface = IOIteratorNext(iterator))) {
|
||||
//* Create an intermediate interface plugin
|
||||
kr = IOCreatePlugInInterfaceForService(usbInterface,
|
||||
kIOUSBInterfaceUserClientTypeID,
|
||||
kIOCFPlugInInterfaceID,
|
||||
&plugInInterface, &score);
|
||||
IOObjectRelease(usbInterface);
|
||||
if ((kIOReturnSuccess != kr) || (!plugInInterface)) {
|
||||
DBG("ERR: Unable to create an interface plug-in (%08x)\n", kr);
|
||||
continue;
|
||||
}
|
||||
|
||||
//* This gets us the interface object
|
||||
result = (*plugInInterface)->QueryInterface(plugInInterface,
|
||||
CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID), (LPVOID)
|
||||
&iface);
|
||||
//* We only needed the plugin to get the interface, so discard it
|
||||
(*plugInInterface)->Release(plugInInterface);
|
||||
if (result || !iface) {
|
||||
DBG("ERR: Couldn't query the interface (%08x)\n", (int) result);
|
||||
continue;
|
||||
}
|
||||
|
||||
//* this gets us an ioservice, with which we will find the actual
|
||||
//* device; after getting a plugin, and querying the interface, of
|
||||
//* course.
|
||||
//* Gotta love OS X
|
||||
kr = (*iface)->GetDevice(iface, &usbDevice);
|
||||
if (kIOReturnSuccess != kr || !usbDevice) {
|
||||
DBG("ERR: Couldn't grab device from interface (%08x)\n", kr);
|
||||
continue;
|
||||
}
|
||||
|
||||
plugInInterface = NULL;
|
||||
score = 0;
|
||||
//* create an intermediate device plugin
|
||||
kr = IOCreatePlugInInterfaceForService(usbDevice,
|
||||
kIOUSBDeviceUserClientTypeID,
|
||||
kIOCFPlugInInterfaceID,
|
||||
&plugInInterface, &score);
|
||||
|
||||
//* only needed this to find the plugin
|
||||
(void)IOObjectRelease(usbDevice);
|
||||
if ((kIOReturnSuccess != kr) || (!plugInInterface)) {
|
||||
DBG("ERR: Unable to create a plug-in (%08x)\n", kr);
|
||||
goto continue1;
|
||||
DBG("ERR: Unable to create a device plug-in (%08x)\n", kr);
|
||||
continue;
|
||||
}
|
||||
|
||||
//* Now create the device interface
|
||||
result = (*plugInInterface)->QueryInterface(plugInInterface,
|
||||
CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (LPVOID) &dev);
|
||||
|
||||
//* only needed this to query the plugin
|
||||
(*plugInInterface)->Release(plugInInterface);
|
||||
if (result || !dev) {
|
||||
DBG("ERR: Couldn't create a device interface (%08x)\n", (int) result);
|
||||
goto continue2;
|
||||
DBG("ERR: Couldn't create a device interface (%08x)\n",
|
||||
(int) result);
|
||||
continue;
|
||||
}
|
||||
|
||||
//* Check the device to see if it's ours
|
||||
//* Now after all that, we actually have a ref to the device and
|
||||
//* the interface that matched our criteria
|
||||
|
||||
kr = (*dev)->GetDeviceVendor(dev, &vendor);
|
||||
kr = (*dev)->GetDeviceProduct(dev, &product);
|
||||
kr = (*dev)->USBGetSerialNumberStringIndex(dev, &serialIndex);
|
||||
|
@ -163,7 +198,8 @@ AndroidDeviceAdded(void *refCon, io_iterator_t iterator)
|
|||
IOUSBDevRequest req;
|
||||
UInt16 buffer[256];
|
||||
|
||||
req.bmRequestType = USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice);
|
||||
req.bmRequestType =
|
||||
USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice);
|
||||
req.bRequest = kUSBRqGetDescriptor;
|
||||
req.wValue = (kUSBStringDesc << 8) | serialIndex;
|
||||
req.wIndex = 0;
|
||||
|
@ -174,219 +210,149 @@ AndroidDeviceAdded(void *refCon, io_iterator_t iterator)
|
|||
if (kr == kIOReturnSuccess && req.wLenDone > 0) {
|
||||
int i, count;
|
||||
|
||||
// skip first word, and copy the rest to the serial string, changing shorts to bytes.
|
||||
// skip first word, and copy the rest to the serial string,
|
||||
// changing shorts to bytes.
|
||||
count = (req.wLenDone - 1) / 2;
|
||||
for (i = 0; i < count; i++)
|
||||
serial[i] = buffer[i + 1];
|
||||
serial[i] = 0;
|
||||
}
|
||||
}
|
||||
(*dev)->Release(dev);
|
||||
|
||||
usb_handle* handle = NULL;
|
||||
|
||||
//* Open the device
|
||||
kr = (*dev)->USBDeviceOpen(dev);
|
||||
|
||||
if (kr != kIOReturnSuccess) {
|
||||
DBG("ERR: Could not open device: %08x\n", kr);
|
||||
goto continue3;
|
||||
} else {
|
||||
//* Find an interface for the device
|
||||
handle = FindDeviceInterface((IOUSBDeviceInterface**)dev, vendor, product);
|
||||
}
|
||||
DBG("INFO: Found vid=%04x pid=%04x serial=%s\n", vendor, product,
|
||||
serial);
|
||||
|
||||
usb_handle* handle = CheckInterface((IOUSBInterfaceInterface**)iface,
|
||||
vendor, product);
|
||||
if (handle == NULL) {
|
||||
DBG("ERR: Could not find device interface: %08x\n", kr);
|
||||
(*dev)->USBDeviceClose(dev);
|
||||
goto continue3;
|
||||
(*iface)->Release(iface);
|
||||
continue;
|
||||
}
|
||||
|
||||
DBG("AndroidDeviceAdded calling register_usb_transport\n");
|
||||
register_usb_transport(handle, (serial[0] ? serial : NULL));
|
||||
|
||||
// Register for an interest notification of this device being removed. Pass the reference to our
|
||||
// private data as the refCon for the notification.
|
||||
// Register for an interest notification of this device being removed.
|
||||
// Pass the reference to our private data as the refCon for the
|
||||
// notification.
|
||||
kr = IOServiceAddInterestNotification(notificationPort,
|
||||
usbDevice,
|
||||
usbInterface,
|
||||
kIOGeneralInterest,
|
||||
AndroidDeviceNotify,
|
||||
AndroidInterfaceNotify,
|
||||
handle,
|
||||
&handle->usbNotification);
|
||||
|
||||
if (kIOReturnSuccess != kr) {
|
||||
DBG("ERR: Unable to create interest notification (%08x)\n", kr);
|
||||
}
|
||||
|
||||
continue3:
|
||||
(void)(*dev)->Release(dev);
|
||||
continue2:
|
||||
IODestroyPlugInInterface(plugInInterface);
|
||||
continue1:
|
||||
IOObjectRelease(usbDevice);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
AndroidDeviceNotify(void *refCon, io_service_t service, natural_t messageType, void *messageArgument)
|
||||
AndroidInterfaceNotify(void *refCon, io_service_t service, natural_t messageType, void *messageArgument)
|
||||
{
|
||||
usb_handle *handle = (usb_handle *)refCon;
|
||||
|
||||
if (messageType == kIOMessageServiceIsTerminated) {
|
||||
DBG("AndroidDeviceNotify\n");
|
||||
if (!handle) {
|
||||
DBG("ERR: NULL handle\n");
|
||||
return;
|
||||
}
|
||||
DBG("AndroidInterfaceNotify\n");
|
||||
IOObjectRelease(handle->usbNotification);
|
||||
usb_kick(handle);
|
||||
}
|
||||
}
|
||||
|
||||
//* TODO: simplify this further since we only register to get ADB interface
|
||||
//* subclass+protocol events
|
||||
static usb_handle*
|
||||
FindDeviceInterface(IOUSBDeviceInterface **dev, UInt16 vendor, UInt16 product)
|
||||
CheckInterface(IOUSBInterfaceInterface **interface, UInt16 vendor, UInt16 product)
|
||||
{
|
||||
usb_handle* handle = NULL;
|
||||
IOReturn kr;
|
||||
IOUSBFindInterfaceRequest request;
|
||||
io_iterator_t iterator;
|
||||
io_service_t usbInterface;
|
||||
IOCFPlugInInterface **plugInInterface;
|
||||
IOUSBInterfaceInterface **interface = NULL;
|
||||
HRESULT result;
|
||||
SInt32 score;
|
||||
UInt8 interfaceNumEndpoints, interfaceClass, interfaceSubClass, interfaceProtocol;
|
||||
UInt8 endpoint, configuration;
|
||||
UInt8 endpoint;
|
||||
|
||||
//* Placing the constant KIOUSBFindInterfaceDontCare into the following
|
||||
//* fields of the IOUSBFindInterfaceRequest structure will allow us to
|
||||
//* find all of the interfaces
|
||||
request.bInterfaceClass = kIOUSBFindInterfaceDontCare;
|
||||
request.bInterfaceSubClass = kIOUSBFindInterfaceDontCare;
|
||||
request.bInterfaceProtocol = kIOUSBFindInterfaceDontCare;
|
||||
request.bAlternateSetting = kIOUSBFindInterfaceDontCare;
|
||||
|
||||
//* SetConfiguration will kill an existing UMS connection, so let's not do this if not necessary.
|
||||
configuration = 0;
|
||||
(*dev)->GetConfiguration(dev, &configuration);
|
||||
if (configuration != 1)
|
||||
(*dev)->SetConfiguration(dev, 1);
|
||||
|
||||
//* Get an iterator for the interfaces on the device
|
||||
kr = (*dev)->CreateInterfaceIterator(dev, &request, &iterator);
|
||||
|
||||
//* Now open the interface. This will cause the pipes associated with
|
||||
//* the endpoints in the interface descriptor to be instantiated
|
||||
kr = (*interface)->USBInterfaceOpen(interface);
|
||||
if (kr != kIOReturnSuccess) {
|
||||
DBG("ERR: Couldn't create a device interface iterator: (%08x)\n", kr);
|
||||
DBG("ERR: Could not open interface: (%08x)\n", kr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while ((usbInterface = IOIteratorNext(iterator))) {
|
||||
//* Create an intermediate plugin
|
||||
kr = IOCreatePlugInInterfaceForService(
|
||||
usbInterface,
|
||||
kIOUSBInterfaceUserClientTypeID,
|
||||
kIOCFPlugInInterfaceID,
|
||||
&plugInInterface,
|
||||
&score);
|
||||
|
||||
//* No longer need the usbInterface object now that we have the plugin
|
||||
(void) IOObjectRelease(usbInterface);
|
||||
|
||||
if ((kr != kIOReturnSuccess) || (!plugInInterface)) {
|
||||
DBG("ERR: Unable to create plugin (%08x)\n", kr);
|
||||
break;
|
||||
}
|
||||
|
||||
//* Now create the interface interface for the interface
|
||||
result = (*plugInInterface)->QueryInterface(
|
||||
plugInInterface,
|
||||
CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID),
|
||||
(LPVOID) &interface);
|
||||
|
||||
//* No longer need the intermediate plugin
|
||||
(*plugInInterface)->Release(plugInInterface);
|
||||
|
||||
if (result || !interface) {
|
||||
DBG("ERR: Couldn't create interface interface: (%08x)\n",
|
||||
(unsigned int) result);
|
||||
break;
|
||||
}
|
||||
|
||||
//* Now open the interface. This will cause the pipes associated with
|
||||
//* the endpoints in the interface descriptor to be instantiated
|
||||
kr = (*interface)->USBInterfaceOpen(interface);
|
||||
|
||||
if (kr != kIOReturnSuccess)
|
||||
{
|
||||
DBG("ERR: Could not open interface: (%08x)\n", kr);
|
||||
(void) (*interface)->Release(interface);
|
||||
//* continue so we can try the next interface
|
||||
continue;
|
||||
}
|
||||
|
||||
//* Get the number of endpoints associated with this interface
|
||||
kr = (*interface)->GetNumEndpoints(interface, &interfaceNumEndpoints);
|
||||
|
||||
if (kr != kIOReturnSuccess) {
|
||||
DBG("ERR: Unable to get number of endpoints: (%08x)\n", kr);
|
||||
goto next_interface;
|
||||
}
|
||||
|
||||
//* Get interface class, subclass and protocol
|
||||
if ((*interface)->GetInterfaceClass(interface, &interfaceClass) != kIOReturnSuccess ||
|
||||
(*interface)->GetInterfaceSubClass(interface, &interfaceSubClass) != kIOReturnSuccess ||
|
||||
(*interface)->GetInterfaceProtocol(interface, &interfaceProtocol) != kIOReturnSuccess)
|
||||
{
|
||||
DBG("ERR: Unable to get interface class, subclass and protocol\n");
|
||||
goto next_interface;
|
||||
}
|
||||
|
||||
//* check to make sure interface class, subclass and protocol match ADB
|
||||
//* avoid opening mass storage endpoints
|
||||
if (is_adb_interface(vendor, product, interfaceClass, interfaceSubClass, interfaceProtocol)) {
|
||||
handle = calloc(1, sizeof(usb_handle));
|
||||
|
||||
//* Iterate over the endpoints for this interface and find the first
|
||||
//* bulk in/out pipes available. These will be our read/write pipes.
|
||||
for (endpoint = 0; endpoint <= interfaceNumEndpoints; endpoint++) {
|
||||
UInt8 transferType;
|
||||
UInt16 maxPacketSize;
|
||||
UInt8 interval;
|
||||
UInt8 number;
|
||||
UInt8 direction;
|
||||
|
||||
kr = (*interface)->GetPipeProperties(interface, endpoint, &direction,
|
||||
&number, &transferType, &maxPacketSize, &interval);
|
||||
|
||||
if (kIOReturnSuccess == kr) {
|
||||
if (kUSBBulk != transferType)
|
||||
continue;
|
||||
|
||||
if (kUSBIn == direction)
|
||||
handle->bulkIn = endpoint;
|
||||
|
||||
if (kUSBOut == direction)
|
||||
handle->bulkOut = endpoint;
|
||||
|
||||
if (interfaceProtocol == 0x01) {
|
||||
handle->zero_mask = maxPacketSize - 1;
|
||||
}
|
||||
|
||||
} else {
|
||||
DBG("ERR: FindDeviceInterface - could not get pipe properties\n");
|
||||
}
|
||||
}
|
||||
|
||||
handle->interface = interface;
|
||||
break;
|
||||
}
|
||||
|
||||
next_interface:
|
||||
(*interface)->USBInterfaceClose(interface);
|
||||
(*interface)->Release(interface);
|
||||
//* Get the number of endpoints associated with this interface
|
||||
kr = (*interface)->GetNumEndpoints(interface, &interfaceNumEndpoints);
|
||||
if (kr != kIOReturnSuccess) {
|
||||
DBG("ERR: Unable to get number of endpoints: (%08x)\n", kr);
|
||||
goto err_get_num_ep;
|
||||
}
|
||||
|
||||
//* Get interface class, subclass and protocol
|
||||
if ((*interface)->GetInterfaceClass(interface, &interfaceClass) != kIOReturnSuccess ||
|
||||
(*interface)->GetInterfaceSubClass(interface, &interfaceSubClass) != kIOReturnSuccess ||
|
||||
(*interface)->GetInterfaceProtocol(interface, &interfaceProtocol) != kIOReturnSuccess) {
|
||||
DBG("ERR: Unable to get interface class, subclass and protocol\n");
|
||||
goto err_get_interface_class;
|
||||
}
|
||||
|
||||
//* check to make sure interface class, subclass and protocol match ADB
|
||||
//* avoid opening mass storage endpoints
|
||||
if (!is_adb_interface(vendor, product, interfaceClass,
|
||||
interfaceSubClass, interfaceProtocol))
|
||||
goto err_bad_adb_interface;
|
||||
|
||||
handle = calloc(1, sizeof(usb_handle));
|
||||
|
||||
//* Iterate over the endpoints for this interface and find the first
|
||||
//* bulk in/out pipes available. These will be our read/write pipes.
|
||||
for (endpoint = 0; endpoint <= interfaceNumEndpoints; endpoint++) {
|
||||
UInt8 transferType;
|
||||
UInt16 maxPacketSize;
|
||||
UInt8 interval;
|
||||
UInt8 number;
|
||||
UInt8 direction;
|
||||
|
||||
kr = (*interface)->GetPipeProperties(interface, endpoint, &direction,
|
||||
&number, &transferType, &maxPacketSize, &interval);
|
||||
|
||||
if (kIOReturnSuccess == kr) {
|
||||
if (kUSBBulk != transferType)
|
||||
continue;
|
||||
|
||||
if (kUSBIn == direction)
|
||||
handle->bulkIn = endpoint;
|
||||
|
||||
if (kUSBOut == direction)
|
||||
handle->bulkOut = endpoint;
|
||||
|
||||
handle->zero_mask = maxPacketSize - 1;
|
||||
} else {
|
||||
DBG("ERR: FindDeviceInterface - could not get pipe properties\n");
|
||||
goto err_get_pipe_props;
|
||||
}
|
||||
}
|
||||
|
||||
handle->interface = interface;
|
||||
return handle;
|
||||
|
||||
err_get_pipe_props:
|
||||
free(handle);
|
||||
err_bad_adb_interface:
|
||||
err_get_interface_class:
|
||||
err_get_num_ep:
|
||||
(*interface)->USBInterfaceClose(interface);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void* RunLoopThread(void* unused)
|
||||
{
|
||||
int i;
|
||||
unsigned i;
|
||||
|
||||
InitUSB();
|
||||
|
||||
|
@ -400,7 +366,7 @@ void* RunLoopThread(void* unused)
|
|||
CFRunLoopRun();
|
||||
currentRunLoop = 0;
|
||||
|
||||
for (i = 0; i < kSupportedDeviceCount; i++) {
|
||||
for (i = 0; i < vendorIdCount; i++) {
|
||||
IOObjectRelease(notificationIterators[i]);
|
||||
}
|
||||
IONotificationPortDestroy(notificationPort);
|
||||
|
@ -417,6 +383,9 @@ void usb_init()
|
|||
{
|
||||
adb_thread_t tid;
|
||||
|
||||
notificationIterators = (io_iterator_t*)malloc(
|
||||
vendorIdCount * sizeof(io_iterator_t));
|
||||
|
||||
adb_mutex_init(&start_lock, NULL);
|
||||
adb_cond_init(&start_cond, NULL);
|
||||
|
||||
|
@ -441,6 +410,11 @@ void usb_cleanup()
|
|||
close_usb_devices();
|
||||
if (currentRunLoop)
|
||||
CFRunLoopStop(currentRunLoop);
|
||||
|
||||
if (notificationIterators != NULL) {
|
||||
free(notificationIterators);
|
||||
notificationIterators = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int usb_write(usb_handle *handle, const void *buf, int len)
|
||||
|
@ -527,6 +501,9 @@ int usb_close(usb_handle *handle)
|
|||
void usb_kick(usb_handle *handle)
|
||||
{
|
||||
/* release the interface */
|
||||
if (!handle)
|
||||
return;
|
||||
|
||||
if (handle->interface)
|
||||
{
|
||||
(*handle->interface)->USBInterfaceClose(handle->interface);
|
||||
|
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
* Copyright (C) 2009 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "usb_vendors.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# include "windows.h"
|
||||
# include "shlobj.h"
|
||||
#else
|
||||
# include <unistd.h>
|
||||
# include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#include "sysdeps.h"
|
||||
#include "adb.h"
|
||||
|
||||
#define ANDROID_PATH ".android"
|
||||
#define ANDROID_ADB_INI "adb_usb.ini"
|
||||
|
||||
#define TRACE_TAG TRACE_USB
|
||||
|
||||
// Google's USB Vendor ID
|
||||
#define VENDOR_ID_GOOGLE 0x18d1
|
||||
// HTC's USB Vendor ID
|
||||
#define VENDOR_ID_HTC 0x0bb4
|
||||
|
||||
/** built-in vendor list */
|
||||
int builtInVendorIds[] = {
|
||||
VENDOR_ID_GOOGLE,
|
||||
VENDOR_ID_HTC,
|
||||
};
|
||||
|
||||
#define BUILT_IN_VENDOR_COUNT (sizeof(builtInVendorIds)/sizeof(builtInVendorIds[0]))
|
||||
|
||||
/* max number of supported vendor ids (built-in + 3rd party). increase as needed */
|
||||
#define VENDOR_COUNT_MAX 128
|
||||
|
||||
int vendorIds[VENDOR_COUNT_MAX];
|
||||
unsigned vendorIdCount = 0;
|
||||
|
||||
int get_adb_usb_ini(char* buff, size_t len);
|
||||
|
||||
void usb_vendors_init(void)
|
||||
{
|
||||
if (VENDOR_COUNT_MAX < BUILT_IN_VENDOR_COUNT) {
|
||||
fprintf(stderr, "VENDOR_COUNT_MAX not big enough for built-in vendor list.\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
/* add the built-in vendors at the beginning of the array */
|
||||
memcpy(vendorIds, builtInVendorIds, sizeof(builtInVendorIds));
|
||||
|
||||
/* default array size is the number of built-in vendors */
|
||||
vendorIdCount = BUILT_IN_VENDOR_COUNT;
|
||||
|
||||
if (VENDOR_COUNT_MAX == BUILT_IN_VENDOR_COUNT)
|
||||
return;
|
||||
|
||||
char temp[PATH_MAX];
|
||||
if (get_adb_usb_ini(temp, sizeof(temp)) == 0) {
|
||||
FILE * f = fopen(temp, "rt");
|
||||
|
||||
if (f != NULL) {
|
||||
/* The vendor id file is pretty basic. 1 vendor id per line.
|
||||
Lines starting with # are comments */
|
||||
while (fgets(temp, sizeof(temp), f) != NULL) {
|
||||
if (temp[0] == '#')
|
||||
continue;
|
||||
|
||||
long value = strtol(temp, NULL, 0);
|
||||
if (errno == EINVAL || errno == ERANGE || value > INT_MAX || value < 0) {
|
||||
fprintf(stderr, "Invalid content in %s. Quitting.\n", ANDROID_ADB_INI);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
vendorIds[vendorIdCount++] = (int)value;
|
||||
|
||||
/* make sure we don't go beyond the array */
|
||||
if (vendorIdCount == VENDOR_COUNT_MAX) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Utils methods */
|
||||
|
||||
/* builds the path to the adb vendor id file. returns 0 if success */
|
||||
int build_path(char* buff, size_t len, const char* format, const char* home)
|
||||
{
|
||||
if (snprintf(buff, len, format, home, ANDROID_PATH, ANDROID_ADB_INI) >= len) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* fills buff with the path to the adb vendor id file. returns 0 if success */
|
||||
int get_adb_usb_ini(char* buff, size_t len)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
const char* home = getenv("ANDROID_SDK_HOME");
|
||||
if (home != NULL) {
|
||||
return build_path(buff, len, "%s\\%s\\%s", home);
|
||||
} else {
|
||||
char path[MAX_PATH];
|
||||
SHGetFolderPath( NULL, CSIDL_PROFILE, NULL, 0, path);
|
||||
return build_path(buff, len, "%s\\%s\\%s", path);
|
||||
}
|
||||
#else
|
||||
const char* home = getenv("HOME");
|
||||
if (home == NULL)
|
||||
home = "/tmp";
|
||||
|
||||
return build_path(buff, len, "%s/%s/%s", home);
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Copyright (C) 2009 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __USB_VENDORS_H
|
||||
#define __USB_VENDORS_H
|
||||
|
||||
extern int vendorIds[];
|
||||
extern unsigned vendorIdCount;
|
||||
|
||||
void usb_vendors_init(void);
|
||||
|
||||
#endif
|
|
@ -446,7 +446,7 @@ int recognized_device(usb_handle* handle) {
|
|||
}
|
||||
|
||||
void find_devices() {
|
||||
usb_handle* handle = NULL;
|
||||
usb_handle* handle = NULL;
|
||||
char entry_buffer[2048];
|
||||
char interf_name[2048];
|
||||
AdbInterfaceInfo* next_interface = (AdbInterfaceInfo*)(&entry_buffer[0]);
|
||||
|
|
|
@ -40,7 +40,7 @@ void bootimg_set_cmdline(boot_img_hdr *h, const char *cmdline)
|
|||
boot_img_hdr *mkbootimg(void *kernel, unsigned kernel_size,
|
||||
void *ramdisk, unsigned ramdisk_size,
|
||||
void *second, unsigned second_size,
|
||||
unsigned page_size,
|
||||
unsigned page_size, unsigned base,
|
||||
unsigned *bootimg_size)
|
||||
{
|
||||
unsigned kernel_actual;
|
||||
|
@ -65,15 +65,14 @@ boot_img_hdr *mkbootimg(void *kernel, unsigned kernel_size,
|
|||
|
||||
memcpy(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE);
|
||||
|
||||
hdr->kernel_size = kernel_size;
|
||||
hdr->kernel_addr = 0x10008000;
|
||||
hdr->kernel_size = kernel_size;
|
||||
hdr->ramdisk_size = ramdisk_size;
|
||||
hdr->ramdisk_addr = 0x11000000;
|
||||
hdr->second_size = second_size;
|
||||
hdr->second_addr = 0x10F00000;
|
||||
|
||||
hdr->tags_addr = 0x10000100;
|
||||
hdr->page_size = page_size;
|
||||
hdr->second_size = second_size;
|
||||
hdr->kernel_addr = base + 0x00008000;
|
||||
hdr->ramdisk_addr = base + 0x01000000;
|
||||
hdr->second_addr = base + 0x00F00000;
|
||||
hdr->tags_addr = base + 0x00000100;
|
||||
hdr->page_size = page_size;
|
||||
|
||||
memcpy(hdr->magic + page_size,
|
||||
kernel, kernel_size);
|
||||
|
|
|
@ -42,6 +42,14 @@
|
|||
|
||||
#include "fastboot.h"
|
||||
|
||||
void bootimg_set_cmdline(boot_img_hdr *h, const char *cmdline);
|
||||
|
||||
boot_img_hdr *mkbootimg(void *kernel, unsigned kernel_size,
|
||||
void *ramdisk, unsigned ramdisk_size,
|
||||
void *second, unsigned second_size,
|
||||
unsigned page_size, unsigned base,
|
||||
unsigned *bootimg_size);
|
||||
|
||||
static usb_handle *usb = 0;
|
||||
static const char *serial = 0;
|
||||
static const char *product = 0;
|
||||
|
@ -49,6 +57,8 @@ static const char *cmdline = 0;
|
|||
static int wipe_data = 0;
|
||||
static unsigned short vendor_id = 0;
|
||||
|
||||
static unsigned base_addr = 0x10000000;
|
||||
|
||||
void die(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
@ -212,6 +222,7 @@ void usage(void)
|
|||
" -p <product> specify product name\n"
|
||||
" -c <cmdline> override kernel commandline\n"
|
||||
" -i <vendor id> specify a custom USB vendor id\n"
|
||||
" -b <base_addr> specify a custom kernel base address\n"
|
||||
);
|
||||
exit(1);
|
||||
}
|
||||
|
@ -257,7 +268,7 @@ void *load_bootable_image(const char *kernel, const char *ramdisk,
|
|||
}
|
||||
|
||||
fprintf(stderr,"creating boot image...\n");
|
||||
bdata = mkbootimg(kdata, ksize, rdata, rsize, 0, 0, 2048, &bsize);
|
||||
bdata = mkbootimg(kdata, ksize, rdata, rsize, 0, 0, 2048, base_addr, &bsize);
|
||||
if(bdata == 0) {
|
||||
fprintf(stderr,"failed to create boot.img\n");
|
||||
return 0;
|
||||
|
@ -545,6 +556,10 @@ int main(int argc, char **argv)
|
|||
if(!strcmp(*argv, "-w")) {
|
||||
wants_wipe = 1;
|
||||
skip(1);
|
||||
} else if(!strcmp(*argv, "-b")) {
|
||||
require(2);
|
||||
base_addr = strtoul(argv[1], 0, 16);
|
||||
skip(2);
|
||||
} else if(!strcmp(*argv, "-s")) {
|
||||
require(2);
|
||||
serial = argv[1];
|
||||
|
|
|
@ -0,0 +1,128 @@
|
|||
/*
|
||||
* Copyright (C) 2009 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _ANDROID_LOG_H
|
||||
#define _ANDROID_LOG_H
|
||||
|
||||
/******************************************************************
|
||||
*
|
||||
* IMPORTANT NOTICE:
|
||||
*
|
||||
* This file is part of Android's set of stable system headers
|
||||
* exposed by the Android NDK (Native Development Kit) since
|
||||
* platform release 1.5
|
||||
*
|
||||
* Third-party source AND binary code relies on the definitions
|
||||
* here to be FROZEN ON ALL UPCOMING PLATFORM RELEASES.
|
||||
*
|
||||
* - DO NOT MODIFY ENUMS (EXCEPT IF YOU ADD NEW 32-BIT VALUES)
|
||||
* - DO NOT MODIFY CONSTANTS OR FUNCTIONAL MACROS
|
||||
* - DO NOT CHANGE THE SIGNATURE OF FUNCTIONS IN ANY WAY
|
||||
* - DO NOT CHANGE THE LAYOUT OR SIZE OF STRUCTURES
|
||||
*/
|
||||
|
||||
/*
|
||||
* Support routines to send messages to the Android in-kernel log buffer,
|
||||
* which can later be accessed through the 'logcat' utility.
|
||||
*
|
||||
* Each log message must have
|
||||
* - a priority
|
||||
* - a log tag
|
||||
* - some text
|
||||
*
|
||||
* The tag normally corresponds to the component that emits the log message,
|
||||
* and should be reasonably small.
|
||||
*
|
||||
* Log message text may be truncated to less than an implementation-specific
|
||||
* limit (e.g. 1023 characters max).
|
||||
*
|
||||
* Note that a newline character ("\n") will be appended automatically to your
|
||||
* log message, if not already there. It is not possible to send several messages
|
||||
* and have them appear on a single line in logcat.
|
||||
*
|
||||
* PLEASE USE LOGS WITH MODERATION:
|
||||
*
|
||||
* - Sending log messages eats CPU and slow down your application and the
|
||||
* system.
|
||||
*
|
||||
* - The circular log buffer is pretty small (<64KB), sending many messages
|
||||
* might push off other important log messages from the rest of the system.
|
||||
*
|
||||
* - In release builds, only send log messages to account for exceptional
|
||||
* conditions.
|
||||
*
|
||||
* NOTE: These functions MUST be implemented by /system/lib/liblog.so
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Android log priority values, in ascending priority order.
|
||||
*/
|
||||
typedef enum android_LogPriority {
|
||||
ANDROID_LOG_UNKNOWN = 0,
|
||||
ANDROID_LOG_DEFAULT, /* only for SetMinPriority() */
|
||||
ANDROID_LOG_VERBOSE,
|
||||
ANDROID_LOG_DEBUG,
|
||||
ANDROID_LOG_INFO,
|
||||
ANDROID_LOG_WARN,
|
||||
ANDROID_LOG_ERROR,
|
||||
ANDROID_LOG_FATAL,
|
||||
ANDROID_LOG_SILENT, /* only for SetMinPriority(); must be last */
|
||||
} android_LogPriority;
|
||||
|
||||
/*
|
||||
* Send a simple string to the log.
|
||||
*/
|
||||
int __android_log_write(int prio, const char *tag, const char *text);
|
||||
|
||||
/*
|
||||
* Send a formatted string to the log, used like printf(fmt,...)
|
||||
*/
|
||||
int __android_log_print(int prio, const char *tag, const char *fmt, ...)
|
||||
#if defined(__GNUC__)
|
||||
__attribute__ ((format(printf, 3, 4)))
|
||||
#endif
|
||||
;
|
||||
|
||||
/*
|
||||
* A variant of __android_log_print() that takes a va_list to list
|
||||
* additional parameters.
|
||||
*/
|
||||
int __android_log_vprint(int prio, const char *tag,
|
||||
const char *fmt, va_list ap);
|
||||
|
||||
/*
|
||||
* Log an assertion failure and SIGTRAP the process to have a chance
|
||||
* to inspect it, if a debugger is attached. This uses the FATAL priority.
|
||||
*/
|
||||
void __android_log_assert(const char *cond, const char *tag,
|
||||
const char *fmt, ...)
|
||||
#if defined(__GNUC__)
|
||||
__attribute__ ((noreturn))
|
||||
__attribute__ ((format(printf, 3, 4)))
|
||||
#endif
|
||||
;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ANDROID_LOG_H */
|
|
@ -18,6 +18,7 @@ int ashmem_create_region(const char *name, size_t size);
|
|||
int ashmem_set_prot_region(int fd, int prot);
|
||||
int ashmem_pin_region(int fd, size_t offset, size_t len);
|
||||
int ashmem_unpin_region(int fd, size_t offset, size_t len);
|
||||
int ashmem_get_size_region(int fd);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2006 The Android Open Source Project
|
||||
* Copyright (C) 2009 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -17,6 +17,12 @@
|
|||
#ifndef _ANDROID_CUTILS_LOGD_H
|
||||
#define _ANDROID_CUTILS_LOGD_H
|
||||
|
||||
/* the stable/frozen log-related definitions have been
|
||||
* moved to this header, which is exposed by the NDK
|
||||
*/
|
||||
#include <android/log.h>
|
||||
|
||||
/* the rest is only used internally by the system */
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
@ -32,45 +38,10 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Priority values, in ascending priority order.
|
||||
*/
|
||||
typedef enum android_LogPriority {
|
||||
ANDROID_LOG_UNKNOWN = 0,
|
||||
ANDROID_LOG_DEFAULT, /* only for SetMinPriority() */
|
||||
ANDROID_LOG_VERBOSE,
|
||||
ANDROID_LOG_DEBUG,
|
||||
ANDROID_LOG_INFO,
|
||||
ANDROID_LOG_WARN,
|
||||
ANDROID_LOG_ERROR,
|
||||
ANDROID_LOG_FATAL,
|
||||
ANDROID_LOG_SILENT, /* only for SetMinPriority(); must be last */
|
||||
} android_LogPriority;
|
||||
|
||||
int __android_log_write(int prio, const char *tag, const char *text);
|
||||
|
||||
int __android_log_vprint(int prio, const char *tag,
|
||||
const char *fmt, va_list ap);
|
||||
|
||||
int __android_log_bwrite(int32_t tag, const void *payload, size_t len);
|
||||
int __android_log_btwrite(int32_t tag, char type, const void *payload,
|
||||
size_t len);
|
||||
|
||||
int __android_log_print(int prio, const char *tag, const char *fmt, ...)
|
||||
#if defined(__GNUC__)
|
||||
__attribute__ ((format(printf, 3, 4)))
|
||||
#endif
|
||||
;
|
||||
|
||||
|
||||
void __android_log_assert(const char *cond, const char *tag,
|
||||
const char *fmt, ...)
|
||||
#if defined(__GNUC__)
|
||||
__attribute__ ((noreturn))
|
||||
__attribute__ ((format(printf, 3, 4)))
|
||||
#endif
|
||||
;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -17,12 +17,57 @@
|
|||
#ifndef NATIVE_HANDLE_H_
|
||||
#define NATIVE_HANDLE_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int version; /* sizeof(native_handle) */
|
||||
int version; /* sizeof(native_handle_t) */
|
||||
int numFds; /* number of file-descriptors at &data[0] */
|
||||
int numInts; /* number of ints at &data[numFds] */
|
||||
int data[0]; /* numFds + numInts ints */
|
||||
} native_handle;
|
||||
} native_handle_t;
|
||||
|
||||
|
||||
/* keep the old definition for backward source-compatibility */
|
||||
typedef native_handle_t native_handle;
|
||||
|
||||
/*
|
||||
* native_handle_close
|
||||
*
|
||||
* closes the file descriptors contained in this native_handle_t
|
||||
*
|
||||
* return 0 on success, or a negative error code on failure
|
||||
*
|
||||
*/
|
||||
int native_handle_close(const native_handle_t* h);
|
||||
|
||||
|
||||
/*
|
||||
* native_handle_create
|
||||
*
|
||||
* creates a native_handle_t and initializes it. must be destroyed with
|
||||
* native_handle_delete().
|
||||
*
|
||||
*/
|
||||
native_handle_t* native_handle_create(int numFds, int numInts);
|
||||
|
||||
/*
|
||||
* native_handle_delete
|
||||
*
|
||||
* frees a native_handle_t allocated with native_handle_create().
|
||||
* This ONLY frees the memory allocated for the native_handle_t, but doesn't
|
||||
* close the file descriptors; which can be achieved with native_handle_close().
|
||||
*
|
||||
* return 0 on success, or a negative error code on failure
|
||||
*
|
||||
*/
|
||||
int native_handle_delete(native_handle_t* h);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* NATIVE_HANDLE_H_ */
|
||||
|
|
|
@ -27,6 +27,7 @@ void localtime_tz(const time_t * const timep, struct tm * tmp, const char* tz);
|
|||
struct strftime_locale {
|
||||
const char *mon[12]; /* short names */
|
||||
const char *month[12]; /* long names */
|
||||
const char *standalone_month[12]; /* long standalone names */
|
||||
const char *wday[7]; /* short names */
|
||||
const char *weekday[7]; /* long names */
|
||||
const char *X_fmt;
|
||||
|
|
|
@ -48,6 +48,9 @@
|
|||
#define AID_INSTALL 1012 /* group for installing packages */
|
||||
#define AID_MEDIA 1013 /* mediaserver process */
|
||||
#define AID_DHCP 1014 /* dhcp client */
|
||||
#define AID_SDCARD_RW 1015 /* external storage write access */
|
||||
#define AID_VPN 1016 /* vpn system */
|
||||
#define AID_KEYSTORE 1017 /* keystore subsystem */
|
||||
|
||||
#define AID_SHELL 2000 /* adb and debug shell user */
|
||||
#define AID_CACHE 2001 /* cache access */
|
||||
|
@ -59,6 +62,7 @@
|
|||
#define AID_NET_BT 3002 /* bluetooth: create sco, rfcomm or l2cap sockets */
|
||||
#define AID_INET 3003 /* can create AF_INET and AF_INET6 sockets */
|
||||
#define AID_NET_RAW 3004 /* can create raw INET sockets */
|
||||
#define AID_NET_ADMIN 3005 /* can configure interfaces and routing tables. */
|
||||
|
||||
#define AID_MISC 9998 /* access to misc storage */
|
||||
#define AID_NOBODY 9999
|
||||
|
@ -93,8 +97,12 @@ static struct android_id_info android_ids[] = {
|
|||
{ "diag", AID_DIAG, },
|
||||
{ "net_bt_admin", AID_NET_BT_ADMIN, },
|
||||
{ "net_bt", AID_NET_BT, },
|
||||
{ "inet", AID_INET, },
|
||||
{ "sdcard_rw", AID_SDCARD_RW, },
|
||||
{ "vpn", AID_VPN, },
|
||||
{ "keystore", AID_KEYSTORE, },
|
||||
{ "inet", AID_INET, },
|
||||
{ "net_raw", AID_NET_RAW, },
|
||||
{ "net_admin", AID_NET_ADMIN, },
|
||||
{ "misc", AID_MISC, },
|
||||
{ "nobody", AID_NOBODY, },
|
||||
};
|
||||
|
@ -129,7 +137,7 @@ static struct fs_path_config android_dirs[] = {
|
|||
{ 00750, AID_ROOT, AID_SHELL, "sbin" },
|
||||
{ 00755, AID_ROOT, AID_SHELL, "system/bin" },
|
||||
{ 00755, AID_ROOT, AID_SHELL, "system/xbin" },
|
||||
{ 00777, AID_ROOT, AID_ROOT, "system/etc/ppp" }, /* REMOVE */
|
||||
{ 00755, AID_ROOT, AID_ROOT, "system/etc/ppp" },
|
||||
{ 00777, AID_ROOT, AID_ROOT, "sdcard" },
|
||||
{ 00755, AID_ROOT, AID_ROOT, 0 },
|
||||
};
|
||||
|
@ -141,20 +149,18 @@ static struct fs_path_config android_dirs[] = {
|
|||
** and will allow partial matches.
|
||||
*/
|
||||
static struct fs_path_config android_files[] = {
|
||||
{ 00555, AID_ROOT, AID_ROOT, "system/etc/ppp/ip-up" },
|
||||
{ 00555, AID_ROOT, AID_ROOT, "system/etc/ppp/ip-down" },
|
||||
{ 00440, AID_ROOT, AID_SHELL, "system/etc/init.goldfish.rc" },
|
||||
{ 00550, AID_ROOT, AID_SHELL, "system/etc/init.goldfish.sh" },
|
||||
{ 00440, AID_ROOT, AID_SHELL, "system/etc/init.trout.rc" },
|
||||
{ 00550, AID_ROOT, AID_SHELL, "system/etc/init.ril" },
|
||||
{ 00550, AID_ROOT, AID_SHELL, "system/etc/init.testmenu" },
|
||||
{ 00550, AID_ROOT, AID_SHELL, "system/etc/init.gprs-pppd" },
|
||||
{ 00550, AID_DHCP, AID_SHELL, "system/etc/dhcpcd/dhcpcd-run-hooks" },
|
||||
{ 00440, AID_BLUETOOTH, AID_BLUETOOTH, "system/etc/dbus.conf" },
|
||||
{ 00440, AID_BLUETOOTH, AID_BLUETOOTH, "system/etc/bluez/hcid.conf" },
|
||||
{ 00440, AID_BLUETOOTH, AID_BLUETOOTH, "system/etc/bluez/input.conf" },
|
||||
{ 00440, AID_BLUETOOTH, AID_BLUETOOTH, "system/etc/bluez/audio.conf" },
|
||||
{ 00440, AID_RADIO, AID_AUDIO, "/system/etc/AudioPara4.csv" },
|
||||
{ 00440, AID_RADIO, AID_AUDIO, "system/etc/AudioPara4.csv" },
|
||||
{ 00555, AID_ROOT, AID_ROOT, "system/etc/ppp/*" },
|
||||
{ 00644, AID_SYSTEM, AID_SYSTEM, "data/app/*" },
|
||||
{ 00644, AID_SYSTEM, AID_SYSTEM, "data/app-private/*" },
|
||||
{ 00644, AID_APP, AID_APP, "data/data/*" },
|
||||
|
@ -168,6 +174,7 @@ static struct fs_path_config android_files[] = {
|
|||
{ 06755, AID_ROOT, AID_ROOT, "system/xbin/librank" },
|
||||
{ 06755, AID_ROOT, AID_ROOT, "system/xbin/procrank" },
|
||||
{ 06755, AID_ROOT, AID_ROOT, "system/xbin/procmem" },
|
||||
{ 06755, AID_ROOT, AID_ROOT, "system/xbin/tcpdump" },
|
||||
{ 00755, AID_ROOT, AID_SHELL, "system/bin/*" },
|
||||
{ 00755, AID_ROOT, AID_SHELL, "system/xbin/*" },
|
||||
{ 00750, AID_ROOT, AID_SHELL, "sbin/*" },
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
#ifndef _FRAMEWORK_CLIENT_H
|
||||
#define _FRAMEWORK_CLIENT_H
|
||||
|
||||
#include "../../../frameworks/base/include/utils/List.h"
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
class FrameworkClient {
|
||||
int mSocket;
|
||||
pthread_mutex_t mWriteMutex;
|
||||
|
||||
public:
|
||||
FrameworkClient(int sock);
|
||||
virtual ~FrameworkClient() {}
|
||||
|
||||
int sendMsg(const char *msg);
|
||||
int sendMsg(const char *msg, const char *data);
|
||||
};
|
||||
|
||||
typedef android::List<FrameworkClient *> FrameworkClientCollection;
|
||||
#endif
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef __FRAMEWORK_CMD_HANDLER_H
|
||||
#define __FRAMEWORK_CMD_HANDLER_H
|
||||
|
||||
#include "../../../frameworks/base/include/utils/List.h"
|
||||
|
||||
class SocketClient;
|
||||
|
||||
class FrameworkCommand {
|
||||
private:
|
||||
const char *mCommand;
|
||||
|
||||
public:
|
||||
|
||||
FrameworkCommand(const char *cmd);
|
||||
virtual ~FrameworkCommand() { }
|
||||
|
||||
virtual int runCommand(SocketClient *c, int argc, char **argv) = 0;
|
||||
|
||||
const char *getCommand() { return mCommand; }
|
||||
};
|
||||
|
||||
typedef android::List<FrameworkCommand *> FrameworkCommandCollection;
|
||||
#endif
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef _FRAMEWORKSOCKETLISTENER_H
|
||||
#define _FRAMEWORKSOCKETLISTENER_H
|
||||
|
||||
#include "SocketListener.h"
|
||||
#include "FrameworkCommand.h"
|
||||
|
||||
class SocketClient;
|
||||
|
||||
class FrameworkListener : public SocketListener {
|
||||
public:
|
||||
static const int CMD_ARGS_MAX = 8;
|
||||
private:
|
||||
FrameworkCommandCollection *mCommands;
|
||||
|
||||
public:
|
||||
FrameworkListener(const char *socketName);
|
||||
virtual ~FrameworkListener() {}
|
||||
|
||||
protected:
|
||||
void registerCmd(FrameworkCommand *cmd);
|
||||
virtual bool onDataAvailable(SocketClient *c);
|
||||
|
||||
private:
|
||||
void dispatchCommand(SocketClient *c, char *data);
|
||||
};
|
||||
#endif
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef _NETLINKEVENT_H
|
||||
#define _NETLINKEVENT_H
|
||||
|
||||
#define NL_PARAMS_MAX 32
|
||||
|
||||
class NetlinkEvent {
|
||||
int mSeq;
|
||||
char *mPath;
|
||||
int mAction;
|
||||
char *mSubsystem;
|
||||
char *mParams[NL_PARAMS_MAX];
|
||||
|
||||
public:
|
||||
const static int NlActionUnknown;
|
||||
const static int NlActionAdd;
|
||||
const static int NlActionRemove;
|
||||
const static int NlActionChange;
|
||||
|
||||
NetlinkEvent();
|
||||
virtual ~NetlinkEvent();
|
||||
|
||||
bool decode(char *buffer, int size);
|
||||
const char *findParam(const char *paramName);
|
||||
|
||||
const char *getSubsystem() { return mSubsystem; }
|
||||
int getAction() { return mAction; }
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef _NETLINKLISTENER_H
|
||||
#define _NETLINKLISTENER_H
|
||||
|
||||
#include "SocketListener.h"
|
||||
|
||||
class NetlinkEvent;
|
||||
|
||||
class NetlinkListener : public SocketListener {
|
||||
char mBuffer[64 * 1024];
|
||||
|
||||
public:
|
||||
NetlinkListener(int socket);
|
||||
virtual ~NetlinkListener() {}
|
||||
protected:
|
||||
virtual bool onDataAvailable(SocketClient *cli);
|
||||
};
|
||||
#endif
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _SERVICE_MANAGER_H
|
||||
#define _SERVICE_MANAGER_H
|
||||
|
||||
class ServiceManager {
|
||||
public:
|
||||
ServiceManager();
|
||||
virtual ~ServiceManager() {}
|
||||
|
||||
int start(const char *name);
|
||||
int stop(const char *name);
|
||||
bool isRunning(const char *name);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,23 @@
|
|||
#ifndef _SOCKET_CLIENT_H
|
||||
#define _SOCKET_CLIENT_H
|
||||
|
||||
#include "../../../frameworks/base/include/utils/List.h"
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
class SocketClient {
|
||||
int mSocket;
|
||||
pthread_mutex_t mWriteMutex;
|
||||
|
||||
public:
|
||||
SocketClient(int sock);
|
||||
virtual ~SocketClient() {}
|
||||
|
||||
int getSocket() { return mSocket; }
|
||||
|
||||
int sendMsg(int code, const char *msg, bool addErrno);
|
||||
int sendMsg(const char *msg);
|
||||
};
|
||||
|
||||
typedef android::List<SocketClient *> SocketClientCollection;
|
||||
#endif
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef _SOCKETLISTENER_H
|
||||
#define _SOCKETLISTENER_H
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include <sysutils/SocketClient.h>
|
||||
|
||||
class SocketListener {
|
||||
int mSock;
|
||||
const char *mSocketName;
|
||||
SocketClientCollection *mClients;
|
||||
pthread_mutex_t mClientsLock;
|
||||
bool mListen;
|
||||
int mCtrlPipe[2];
|
||||
pthread_t mThread;
|
||||
|
||||
public:
|
||||
SocketListener(const char *socketNames, bool listen);
|
||||
SocketListener(int socketFd, bool listen);
|
||||
|
||||
virtual ~SocketListener() {}
|
||||
int startListener();
|
||||
int stopListener();
|
||||
|
||||
void sendBroadcast(int code, const char *msg, bool addErrno);
|
||||
void sendBroadcast(const char *msg);
|
||||
|
||||
protected:
|
||||
virtual bool onDataAvailable(SocketClient *c) = 0;
|
||||
|
||||
private:
|
||||
static void *threadStart(void *obj);
|
||||
void runListener();
|
||||
};
|
||||
#endif
|
|
@ -127,7 +127,7 @@ done:
|
|||
static void service_start_if_not_disabled(struct service *svc)
|
||||
{
|
||||
if (!(svc->flags & SVC_DISABLED)) {
|
||||
service_start(svc);
|
||||
service_start(svc, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -372,7 +372,7 @@ int do_start(int nargs, char **args)
|
|||
struct service *svc;
|
||||
svc = service_find_by_name(args[1]);
|
||||
if (svc) {
|
||||
service_start(svc);
|
||||
service_start(svc, NULL);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -393,7 +393,7 @@ int do_restart(int nargs, char **args)
|
|||
svc = service_find_by_name(args[1]);
|
||||
if (svc) {
|
||||
service_stop(svc);
|
||||
service_start(svc);
|
||||
service_start(svc, NULL);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -115,6 +115,7 @@ static struct perms_ devperms[] = {
|
|||
{ "/dev/oncrpc/", 0660, AID_ROOT, AID_SYSTEM, 1 },
|
||||
{ "/dev/adsp/", 0660, AID_SYSTEM, AID_AUDIO, 1 },
|
||||
{ "/dev/mt9t013", 0660, AID_SYSTEM, AID_SYSTEM, 0 },
|
||||
{ "/dev/msm_camera/", 0660, AID_SYSTEM, AID_SYSTEM, 1 },
|
||||
{ "/dev/akm8976_daemon",0640, AID_COMPASS, AID_SYSTEM, 0 },
|
||||
{ "/dev/akm8976_aot", 0640, AID_COMPASS, AID_SYSTEM, 0 },
|
||||
{ "/dev/akm8976_pffd", 0640, AID_COMPASS, AID_SYSTEM, 0 },
|
||||
|
@ -126,10 +127,13 @@ static struct perms_ devperms[] = {
|
|||
{ "/dev/msm_audpre", 0660, AID_SYSTEM, AID_AUDIO, 0 },
|
||||
{ "/dev/htc-acoustic", 0660, AID_SYSTEM, AID_AUDIO, 0 },
|
||||
{ "/dev/smd0", 0640, AID_RADIO, AID_RADIO, 0 },
|
||||
{ "/dev/qemu_trace", 0666, AID_SYSTEM, AID_SYSTEM, 0 },
|
||||
{ "/dev/qmi", 0640, AID_RADIO, AID_RADIO, 0 },
|
||||
{ "/dev/qmi0", 0640, AID_RADIO, AID_RADIO, 0 },
|
||||
{ "/dev/qmi1", 0640, AID_RADIO, AID_RADIO, 0 },
|
||||
{ "/dev/qmi2", 0640, AID_RADIO, AID_RADIO, 0 },
|
||||
{ "/dev/ppp", 0660, AID_RADIO, AID_VPN, 0 },
|
||||
{ "/dev/tun", 0640, AID_VPN, AID_VPN, 0 },
|
||||
{ NULL, 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
|
@ -380,7 +384,10 @@ static void handle_device_event(struct uevent *uevent)
|
|||
} else if (!strncmp(uevent->subsystem, "adsp", 4)) {
|
||||
base = "/dev/adsp/";
|
||||
mkdir(base, 0755);
|
||||
} else if(!strncmp(uevent->subsystem, "input", 5)) {
|
||||
} else if (!strncmp(uevent->subsystem, "msm_camera", 10)) {
|
||||
base = "/dev/msm_camera/";
|
||||
mkdir(base, 0755);
|
||||
} else if(!strncmp(uevent->subsystem, "input", 5)) {
|
||||
base = "/dev/input/";
|
||||
mkdir(base, 0755);
|
||||
} else if(!strncmp(uevent->subsystem, "mtd", 3)) {
|
||||
|
|
57
init/init.c
57
init/init.c
|
@ -156,7 +156,7 @@ static void publish_socket(const char *name, int fd)
|
|||
fcntl(fd, F_SETFD, 0);
|
||||
}
|
||||
|
||||
void service_start(struct service *svc)
|
||||
void service_start(struct service *svc, const char *dynamic_args)
|
||||
{
|
||||
struct stat s;
|
||||
pid_t pid;
|
||||
|
@ -192,6 +192,13 @@ void service_start(struct service *svc)
|
|||
return;
|
||||
}
|
||||
|
||||
if ((!(svc->flags & SVC_ONESHOT)) && dynamic_args) {
|
||||
ERROR("service '%s' must be one-shot to use dynamic args, disabling\n",
|
||||
svc->args[0]);
|
||||
svc->flags |= SVC_DISABLED;
|
||||
return;
|
||||
}
|
||||
|
||||
NOTICE("starting '%s'\n", svc->name);
|
||||
|
||||
pid = fork();
|
||||
|
@ -248,8 +255,27 @@ void service_start(struct service *svc)
|
|||
setuid(svc->uid);
|
||||
}
|
||||
|
||||
if (execve(svc->args[0], (char**) svc->args, (char**) ENV) < 0) {
|
||||
ERROR("cannot execve('%s'): %s\n", svc->args[0], strerror(errno));
|
||||
if (!dynamic_args)
|
||||
if (execve(svc->args[0], (char**) svc->args, (char**) ENV) < 0)
|
||||
ERROR("cannot execve('%s'): %s\n", svc->args[0], strerror(errno));
|
||||
else {
|
||||
char *arg_ptrs[SVC_MAXARGS+1];
|
||||
int arg_idx = svc->nargs;
|
||||
char *tmp = strdup(dynamic_args);
|
||||
char *next = tmp;
|
||||
char *bword;
|
||||
|
||||
/* Copy the static arguments */
|
||||
memcpy(arg_ptrs, svc->args, (svc->nargs * sizeof(char *)));
|
||||
|
||||
while((bword = strsep(&next, " "))) {
|
||||
arg_ptrs[arg_idx++] = bword;
|
||||
if (arg_idx == SVC_MAXARGS)
|
||||
break;
|
||||
}
|
||||
arg_ptrs[arg_idx] = '\0';
|
||||
if (execve(svc->args[0], (char**) arg_ptrs, (char**) ENV) < 0)
|
||||
ERROR("cannot execve('%s'): %s\n", svc->args[0], strerror(errno));
|
||||
}
|
||||
_exit(127);
|
||||
}
|
||||
|
@ -381,7 +407,7 @@ static void restart_service_if_needed(struct service *svc)
|
|||
|
||||
if (next_start_time <= gettime()) {
|
||||
svc->flags &= (~SVC_RESTARTING);
|
||||
service_start(svc);
|
||||
service_start(svc, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -407,13 +433,28 @@ static void sigchld_handler(int s)
|
|||
|
||||
static void msg_start(const char *name)
|
||||
{
|
||||
struct service *svc = service_find_by_name(name);
|
||||
struct service *svc;
|
||||
char *tmp = NULL;
|
||||
char *args = NULL;
|
||||
|
||||
if (!strchr(name, ':'))
|
||||
svc = service_find_by_name(name);
|
||||
else {
|
||||
tmp = strdup(name);
|
||||
args = strchr(tmp, ':');
|
||||
*args = '\0';
|
||||
args++;
|
||||
|
||||
svc = service_find_by_name(tmp);
|
||||
}
|
||||
|
||||
if (svc) {
|
||||
service_start(svc);
|
||||
service_start(svc, args);
|
||||
} else {
|
||||
ERROR("no such service '%s'\n", name);
|
||||
}
|
||||
if (tmp)
|
||||
free(tmp);
|
||||
}
|
||||
|
||||
static void msg_stop(const char *name)
|
||||
|
@ -423,7 +464,7 @@ static void msg_stop(const char *name)
|
|||
if (svc) {
|
||||
service_stop(svc);
|
||||
} else {
|
||||
ERROR("no such service '%s'\n");
|
||||
ERROR("no such service '%s'\n", name);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -739,7 +780,7 @@ void handle_keychord(int fd)
|
|||
svc = service_find_by_keychord(id);
|
||||
if (svc) {
|
||||
INFO("starting service %s from keychord\n", svc->name);
|
||||
service_start(svc);
|
||||
service_start(svc, NULL);
|
||||
} else {
|
||||
ERROR("service for keychord %d not found\n", id);
|
||||
}
|
||||
|
|
15
init/init.h
15
init/init.h
|
@ -29,7 +29,8 @@ void *read_file(const char *fn, unsigned *_sz);
|
|||
void log_init(void);
|
||||
void log_set_level(int level);
|
||||
void log_close(void);
|
||||
void log_write(int level, const char *fmt, ...);
|
||||
void log_write(int level, const char *fmt, ...)
|
||||
__attribute__ ((format(printf, 2, 3)));
|
||||
|
||||
#define ERROR(x...) log_write(3, "<3>init: " x)
|
||||
#define NOTICE(x...) log_write(5, "<5>init: " x)
|
||||
|
@ -115,6 +116,8 @@ struct svcenvinfo {
|
|||
|
||||
#define NR_SVC_SUPP_GIDS 6 /* six supplementary groups */
|
||||
|
||||
#define SVC_MAXARGS 64
|
||||
|
||||
struct service {
|
||||
/* list of all services */
|
||||
struct listnode slist;
|
||||
|
@ -136,15 +139,17 @@ struct service {
|
|||
struct socketinfo *sockets;
|
||||
struct svcenvinfo *envvars;
|
||||
|
||||
int nargs;
|
||||
char *args[1];
|
||||
struct action onrestart; /* Actions to execute on restart. */
|
||||
|
||||
/* keycodes for triggering this service via /dev/keychord */
|
||||
int *keycodes;
|
||||
int nkeycodes;
|
||||
int keychord_id;
|
||||
};
|
||||
|
||||
int nargs;
|
||||
/* "MUST BE AT THE END OF THE STRUCT" */
|
||||
char *args[1];
|
||||
}; /* ^-------'args' MUST be at the end of this struct! */
|
||||
|
||||
int parse_config_file(const char *fn);
|
||||
|
||||
|
@ -157,7 +162,7 @@ void service_for_each_class(const char *classname,
|
|||
void service_for_each_flags(unsigned matchflags,
|
||||
void (*func)(struct service *svc));
|
||||
void service_stop(struct service *svc);
|
||||
void service_start(struct service *svc);
|
||||
void service_start(struct service *svc, const char *dynamic_args);
|
||||
void property_changed(const char *name, const char *value);
|
||||
|
||||
struct action *action_remove_queue_head(void);
|
||||
|
|
|
@ -60,8 +60,6 @@ void DUMP(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
#define MAXARGS 64
|
||||
|
||||
#define T_EOF 0
|
||||
#define T_TEXT 1
|
||||
#define T_NEWLINE 2
|
||||
|
@ -357,7 +355,7 @@ void parse_new_section(struct parse_state *state, int kw,
|
|||
static void parse_config(const char *fn, char *s)
|
||||
{
|
||||
struct parse_state state;
|
||||
char *args[MAXARGS];
|
||||
char *args[SVC_MAXARGS];
|
||||
int nargs;
|
||||
|
||||
nargs = 0;
|
||||
|
@ -384,7 +382,7 @@ static void parse_config(const char *fn, char *s)
|
|||
}
|
||||
break;
|
||||
case T_TEXT:
|
||||
if (nargs < MAXARGS) {
|
||||
if (nargs < SVC_MAXARGS) {
|
||||
args[nargs++] = state.text;
|
||||
}
|
||||
break;
|
||||
|
@ -536,7 +534,7 @@ void queue_all_property_triggers()
|
|||
const char* name = act->name + strlen("property:");
|
||||
const char* equals = strchr(name, '=');
|
||||
if (equals) {
|
||||
char* prop_name[PROP_NAME_MAX + 1];
|
||||
char prop_name[PROP_NAME_MAX + 1];
|
||||
const char* value;
|
||||
int length = equals - name;
|
||||
if (length > PROP_NAME_MAX) {
|
||||
|
@ -546,7 +544,7 @@ void queue_all_property_triggers()
|
|||
prop_name[length] = 0;
|
||||
|
||||
/* does the property exist, and match the trigger value? */
|
||||
value = property_get((const char *)&prop_name[0]);
|
||||
value = property_get(prop_name);
|
||||
if (value && !strcmp(equals + 1, value)) {
|
||||
action_add_queue_tail(act);
|
||||
}
|
||||
|
|
|
@ -67,6 +67,8 @@ struct {
|
|||
{ "wlan.", AID_SYSTEM },
|
||||
{ "dhcp.", AID_SYSTEM },
|
||||
{ "dhcp.", AID_DHCP },
|
||||
{ "vpn.", AID_SYSTEM },
|
||||
{ "vpn.", AID_VPN },
|
||||
{ "debug.", AID_SHELL },
|
||||
{ "log.", AID_SHELL },
|
||||
{ "service.adb.root", AID_SHELL },
|
||||
|
@ -296,7 +298,7 @@ int property_set(const char *name, const char *value)
|
|||
__futex_wake(&pa->serial, INT32_MAX);
|
||||
}
|
||||
/* If name starts with "net." treat as a DNS property. */
|
||||
if (strncmp("net.", name, sizeof("net.") - 1) == 0) {
|
||||
if (strncmp("net.", name, strlen("net.")) == 0) {
|
||||
if (strcmp("net.change", name) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -307,7 +309,7 @@ int property_set(const char *name, const char *value)
|
|||
*/
|
||||
property_set("net.change", name);
|
||||
} else if (persistent_properties_loaded &&
|
||||
strncmp("persist.", name, sizeof("persist.") - 1) == 0) {
|
||||
strncmp("persist.", name, strlen("persist.")) == 0) {
|
||||
/*
|
||||
* Don't write properties to disk until after we have read all default properties
|
||||
* to prevent them from being overwritten by default values.
|
||||
|
@ -446,8 +448,7 @@ static void load_persistent_properties()
|
|||
|
||||
if (dir) {
|
||||
while ((entry = readdir(dir)) != NULL) {
|
||||
if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..") ||
|
||||
strncmp("persist.", entry->d_name, sizeof("persist.") - 1))
|
||||
if (strncmp("persist.", entry->d_name, strlen("persist.")))
|
||||
continue;
|
||||
#if HAVE_DIRENT_D_TYPE
|
||||
if (entry->d_type != DT_REG)
|
||||
|
|
|
@ -21,6 +21,7 @@ commonSources := \
|
|||
array.c \
|
||||
hashmap.c \
|
||||
atomic.c \
|
||||
native_handle.c \
|
||||
buffer.c \
|
||||
socket_inaddr_any_server.c \
|
||||
socket_local_client.c \
|
||||
|
@ -59,7 +60,6 @@ else
|
|||
commonSources += \
|
||||
mspace.c \
|
||||
selector.c \
|
||||
fdevent.c \
|
||||
tztime.c \
|
||||
tzstrftime.c \
|
||||
adb_networking.c \
|
||||
|
|
|
@ -83,3 +83,8 @@ int ashmem_unpin_region(int fd, size_t offset, size_t len)
|
|||
struct ashmem_pin pin = { offset, len };
|
||||
return ioctl(fd, ASHMEM_UNPIN, &pin);
|
||||
}
|
||||
|
||||
int ashmem_get_size_region(int fd)
|
||||
{
|
||||
return ioctl(fd, ASHMEM_GET_SIZE, NULL);
|
||||
}
|
||||
|
|
|
@ -92,3 +92,23 @@ int ashmem_unpin_region(int fd, size_t offset, size_t len)
|
|||
{
|
||||
return ASHMEM_IS_UNPINNED;
|
||||
}
|
||||
|
||||
int ashmem_get_size_region(int fd)
|
||||
{
|
||||
struct stat buf;
|
||||
int result;
|
||||
|
||||
result = fstat(fd, &buf);
|
||||
if (result == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Check if this is an "ashmem" region.
|
||||
// TODO: This is very hacky, and can easily break. We need some reliable indicator.
|
||||
if (!(buf.st_nlink == 0 && S_ISREG(buf.st_mode))) {
|
||||
errno = ENOTTY;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (int)buf.st_size; // TODO: care about overflow (> 2GB file)?
|
||||
}
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "NativeHandle"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <cutils/log.h>
|
||||
#include <cutils/native_handle.h>
|
||||
|
||||
native_handle_t* native_handle_create(int numFds, int numInts)
|
||||
{
|
||||
native_handle_t* h = malloc(
|
||||
sizeof(native_handle_t) + sizeof(int)*(numFds+numInts));
|
||||
|
||||
h->version = sizeof(native_handle_t);
|
||||
h->numFds = numFds;
|
||||
h->numInts = numInts;
|
||||
return h;
|
||||
}
|
||||
|
||||
int native_handle_delete(native_handle_t* h)
|
||||
{
|
||||
if (h) {
|
||||
if (h->version != sizeof(native_handle_t))
|
||||
return -EINVAL;
|
||||
free(h);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int native_handle_close(const native_handle_t* h)
|
||||
{
|
||||
if (h->version != sizeof(native_handle_t))
|
||||
return -EINVAL;
|
||||
|
||||
const int numFds = h->numFds;
|
||||
int i;
|
||||
for (i=0 ; i<numFds ; i++) {
|
||||
close(h->data[i]);
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -172,10 +172,17 @@ label:
|
|||
pt, ptlim, modifier);
|
||||
continue;
|
||||
case 'B':
|
||||
pt = _add((t->tm_mon < 0 ||
|
||||
t->tm_mon >= MONSPERYEAR) ?
|
||||
"?" : Locale->month[t->tm_mon],
|
||||
pt, ptlim, modifier);
|
||||
if (modifier == '-') {
|
||||
pt = _add((t->tm_mon < 0 ||
|
||||
t->tm_mon >= MONSPERYEAR) ?
|
||||
"?" : Locale->standalone_month[t->tm_mon],
|
||||
pt, ptlim, modifier);
|
||||
} else {
|
||||
pt = _add((t->tm_mon < 0 ||
|
||||
t->tm_mon >= MONSPERYEAR) ?
|
||||
"?" : Locale->month[t->tm_mon],
|
||||
pt, ptlim, modifier);
|
||||
}
|
||||
continue;
|
||||
case 'b':
|
||||
case 'h':
|
||||
|
|
|
@ -143,12 +143,16 @@ int __android_log_write(int prio, const char *tag, const char *msg)
|
|||
/* XXX: This needs to go! */
|
||||
if (!strcmp(tag, "HTC_RIL") ||
|
||||
!strcmp(tag, "RILJ") ||
|
||||
!strcmp(tag, "RILB") ||
|
||||
!strcmp(tag, "RILC") ||
|
||||
!strcmp(tag, "RILD") ||
|
||||
!strcmp(tag, "RIL") ||
|
||||
!strcmp(tag, "AT") ||
|
||||
!strcmp(tag, "GSM") ||
|
||||
!strcmp(tag, "STK"))
|
||||
!strcmp(tag, "STK") ||
|
||||
!strcmp(tag, "CDMA") ||
|
||||
!strcmp(tag, "PHONE") ||
|
||||
!strcmp(tag, "SMS"))
|
||||
log_id = LOG_ID_RADIO;
|
||||
|
||||
vec[0].iov_base = (unsigned char *) &prio;
|
||||
|
|
|
@ -21,8 +21,9 @@
|
|||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <utils/Vector.h>
|
||||
#include <utils/KeyedVector.h>
|
||||
#include "tinyutils/Vector.h"
|
||||
#include "tinyutils/KeyedVector.h"
|
||||
#include "tinyutils/smartpointer.h"
|
||||
|
||||
#include "tinyutils/smartpointer.h"
|
||||
#include "codeflinger/ARMAssemblerInterface.h"
|
||||
|
|
|
@ -23,8 +23,7 @@
|
|||
#include <pthread.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <utils/KeyedVector.h>
|
||||
|
||||
#include "tinyutils/KeyedVector.h"
|
||||
#include "tinyutils/smartpointer.h"
|
||||
|
||||
namespace android {
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef ANDROID_ERRORS_H
|
||||
#define ANDROID_ERRORS_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <errno.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
// use this type to return error codes
|
||||
typedef int32_t status_t;
|
||||
|
||||
/*
|
||||
* Error codes.
|
||||
* All error codes are negative values.
|
||||
*/
|
||||
|
||||
enum {
|
||||
OK = 0, // Everything's swell.
|
||||
NO_ERROR = 0, // No errors.
|
||||
|
||||
UNKNOWN_ERROR = 0x80000000,
|
||||
|
||||
NO_MEMORY = -ENOMEM,
|
||||
INVALID_OPERATION = -ENOSYS,
|
||||
BAD_VALUE = -EINVAL,
|
||||
BAD_TYPE = 0x80000001,
|
||||
NAME_NOT_FOUND = -ENOENT,
|
||||
PERMISSION_DENIED = -EPERM,
|
||||
NO_INIT = -ENODEV,
|
||||
ALREADY_EXISTS = -EEXIST,
|
||||
DEAD_OBJECT = -EPIPE,
|
||||
FAILED_TRANSACTION = 0x80000002,
|
||||
JPARKS_BROKE_IT = -EPIPE,
|
||||
BAD_INDEX = -EOVERFLOW,
|
||||
NOT_ENOUGH_DATA = -ENODATA,
|
||||
WOULD_BLOCK = -EWOULDBLOCK,
|
||||
TIMED_OUT = -ETIME,
|
||||
UNKNOWN_TRANSACTION = -EBADMSG,
|
||||
};
|
||||
|
||||
|
||||
}; // namespace android
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#endif // ANDROID_ERRORS_H
|
|
@ -0,0 +1,282 @@
|
|||
/*
|
||||
* Copyright (C) 2005 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef ANDROID_SORTED_VECTOR_H
|
||||
#define ANDROID_SORTED_VECTOR_H
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "tinyutils/Vector.h"
|
||||
#include "tinyutils/VectorImpl.h"
|
||||
#include "tinyutils/TypeHelpers.h"
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
namespace android {
|
||||
|
||||
template <class TYPE>
|
||||
class SortedVector : private SortedVectorImpl
|
||||
{
|
||||
public:
|
||||
typedef TYPE value_type;
|
||||
|
||||
/*!
|
||||
* Constructors and destructors
|
||||
*/
|
||||
|
||||
SortedVector();
|
||||
SortedVector(const SortedVector<TYPE>& rhs);
|
||||
virtual ~SortedVector();
|
||||
|
||||
/*! copy operator */
|
||||
const SortedVector<TYPE>& operator = (const SortedVector<TYPE>& rhs) const;
|
||||
SortedVector<TYPE>& operator = (const SortedVector<TYPE>& rhs);
|
||||
|
||||
/*
|
||||
* empty the vector
|
||||
*/
|
||||
|
||||
inline void clear() { VectorImpl::clear(); }
|
||||
|
||||
/*!
|
||||
* vector stats
|
||||
*/
|
||||
|
||||
//! returns number of items in the vector
|
||||
inline size_t size() const { return VectorImpl::size(); }
|
||||
//! returns wether or not the vector is empty
|
||||
inline bool isEmpty() const { return VectorImpl::isEmpty(); }
|
||||
//! returns how many items can be stored without reallocating the backing store
|
||||
inline size_t capacity() const { return VectorImpl::capacity(); }
|
||||
//! setst the capacity. capacity can never be reduced less than size()
|
||||
inline ssize_t setCapacity(size_t size) { return VectorImpl::setCapacity(size); }
|
||||
|
||||
/*!
|
||||
* C-style array access
|
||||
*/
|
||||
|
||||
//! read-only C-style access
|
||||
inline const TYPE* array() const;
|
||||
|
||||
//! read-write C-style access. BE VERY CAREFUL when modifying the array
|
||||
//! you ust keep it sorted! You usually don't use this function.
|
||||
TYPE* editArray();
|
||||
|
||||
//! finds the index of an item
|
||||
ssize_t indexOf(const TYPE& item) const;
|
||||
|
||||
//! finds where this item should be inserted
|
||||
size_t orderOf(const TYPE& item) const;
|
||||
|
||||
|
||||
/*!
|
||||
* accessors
|
||||
*/
|
||||
|
||||
//! read-only access to an item at a given index
|
||||
inline const TYPE& operator [] (size_t index) const;
|
||||
//! alternate name for operator []
|
||||
inline const TYPE& itemAt(size_t index) const;
|
||||
//! stack-usage of the vector. returns the top of the stack (last element)
|
||||
const TYPE& top() const;
|
||||
//! same as operator [], but allows to access the vector backward (from the end) with a negative index
|
||||
const TYPE& mirrorItemAt(ssize_t index) const;
|
||||
|
||||
/*!
|
||||
* modifing the array
|
||||
*/
|
||||
|
||||
//! add an item in the right place (and replace the one that is there)
|
||||
ssize_t add(const TYPE& item);
|
||||
|
||||
//! editItemAt() MUST NOT change the order of this item
|
||||
TYPE& editItemAt(size_t index) {
|
||||
return *( static_cast<TYPE *>(VectorImpl::editItemLocation(index)) );
|
||||
}
|
||||
|
||||
//! merges a vector into this one
|
||||
ssize_t merge(const Vector<TYPE>& vector);
|
||||
ssize_t merge(const SortedVector<TYPE>& vector);
|
||||
|
||||
//! removes an item
|
||||
ssize_t remove(const TYPE&);
|
||||
|
||||
//! remove several items
|
||||
inline ssize_t removeItemsAt(size_t index, size_t count = 1);
|
||||
//! remove one item
|
||||
inline ssize_t removeAt(size_t index) { return removeItemsAt(index); }
|
||||
|
||||
protected:
|
||||
virtual void do_construct(void* storage, size_t num) const;
|
||||
virtual void do_destroy(void* storage, size_t num) const;
|
||||
virtual void do_copy(void* dest, const void* from, size_t num) const;
|
||||
virtual void do_splat(void* dest, const void* item, size_t num) const;
|
||||
virtual void do_move_forward(void* dest, const void* from, size_t num) const;
|
||||
virtual void do_move_backward(void* dest, const void* from, size_t num) const;
|
||||
virtual int do_compare(const void* lhs, const void* rhs) const;
|
||||
};
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// No user serviceable parts from here...
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
template<class TYPE> inline
|
||||
SortedVector<TYPE>::SortedVector()
|
||||
: SortedVectorImpl(sizeof(TYPE),
|
||||
((traits<TYPE>::has_trivial_ctor ? HAS_TRIVIAL_CTOR : 0)
|
||||
|(traits<TYPE>::has_trivial_dtor ? HAS_TRIVIAL_DTOR : 0)
|
||||
|(traits<TYPE>::has_trivial_copy ? HAS_TRIVIAL_COPY : 0)
|
||||
|(traits<TYPE>::has_trivial_assign ? HAS_TRIVIAL_ASSIGN : 0))
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
SortedVector<TYPE>::SortedVector(const SortedVector<TYPE>& rhs)
|
||||
: SortedVectorImpl(rhs) {
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
SortedVector<TYPE>::~SortedVector() {
|
||||
finish_vector();
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
SortedVector<TYPE>& SortedVector<TYPE>::operator = (const SortedVector<TYPE>& rhs) {
|
||||
SortedVectorImpl::operator = (rhs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
const SortedVector<TYPE>& SortedVector<TYPE>::operator = (const SortedVector<TYPE>& rhs) const {
|
||||
SortedVectorImpl::operator = (rhs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
const TYPE* SortedVector<TYPE>::array() const {
|
||||
return static_cast<const TYPE *>(arrayImpl());
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
TYPE* SortedVector<TYPE>::editArray() {
|
||||
return static_cast<TYPE *>(editArrayImpl());
|
||||
}
|
||||
|
||||
|
||||
template<class TYPE> inline
|
||||
const TYPE& SortedVector<TYPE>::operator[](size_t index) const {
|
||||
assert( index<size() );
|
||||
return *(array() + index);
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
const TYPE& SortedVector<TYPE>::itemAt(size_t index) const {
|
||||
return operator[](index);
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
const TYPE& SortedVector<TYPE>::mirrorItemAt(ssize_t index) const {
|
||||
assert( (index>0 ? index : -index)<size() );
|
||||
return *(array() + ((index<0) ? (size()-index) : index));
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
const TYPE& SortedVector<TYPE>::top() const {
|
||||
return *(array() + size() - 1);
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
ssize_t SortedVector<TYPE>::add(const TYPE& item) {
|
||||
return SortedVectorImpl::add(&item);
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
ssize_t SortedVector<TYPE>::indexOf(const TYPE& item) const {
|
||||
return SortedVectorImpl::indexOf(&item);
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
size_t SortedVector<TYPE>::orderOf(const TYPE& item) const {
|
||||
return SortedVectorImpl::orderOf(&item);
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
ssize_t SortedVector<TYPE>::merge(const Vector<TYPE>& vector) {
|
||||
return SortedVectorImpl::merge(reinterpret_cast<const VectorImpl&>(vector));
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
ssize_t SortedVector<TYPE>::merge(const SortedVector<TYPE>& vector) {
|
||||
return SortedVectorImpl::merge(reinterpret_cast<const SortedVectorImpl&>(vector));
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
ssize_t SortedVector<TYPE>::remove(const TYPE& item) {
|
||||
return SortedVectorImpl::remove(&item);
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
ssize_t SortedVector<TYPE>::removeItemsAt(size_t index, size_t count) {
|
||||
return VectorImpl::removeItemsAt(index, count);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
template<class TYPE>
|
||||
void SortedVector<TYPE>::do_construct(void* storage, size_t num) const {
|
||||
construct_type( reinterpret_cast<TYPE*>(storage), num );
|
||||
}
|
||||
|
||||
template<class TYPE>
|
||||
void SortedVector<TYPE>::do_destroy(void* storage, size_t num) const {
|
||||
destroy_type( reinterpret_cast<TYPE*>(storage), num );
|
||||
}
|
||||
|
||||
template<class TYPE>
|
||||
void SortedVector<TYPE>::do_copy(void* dest, const void* from, size_t num) const {
|
||||
copy_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(from), num );
|
||||
}
|
||||
|
||||
template<class TYPE>
|
||||
void SortedVector<TYPE>::do_splat(void* dest, const void* item, size_t num) const {
|
||||
splat_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(item), num );
|
||||
}
|
||||
|
||||
template<class TYPE>
|
||||
void SortedVector<TYPE>::do_move_forward(void* dest, const void* from, size_t num) const {
|
||||
move_forward_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(from), num );
|
||||
}
|
||||
|
||||
template<class TYPE>
|
||||
void SortedVector<TYPE>::do_move_backward(void* dest, const void* from, size_t num) const {
|
||||
move_backward_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(from), num );
|
||||
}
|
||||
|
||||
template<class TYPE>
|
||||
int SortedVector<TYPE>::do_compare(const void* lhs, const void* rhs) const {
|
||||
return compare_type( *reinterpret_cast<const TYPE*>(lhs), *reinterpret_cast<const TYPE*>(rhs) );
|
||||
}
|
||||
|
||||
}; // namespace android
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#endif // ANDROID_SORTED_VECTOR_H
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include <cutils/log.h>
|
||||
|
||||
#include "tinyutils/Errors.h"
|
||||
#include "tinyutils/VectorImpl.h"
|
||||
#include "tinyutils/TypeHelpers.h"
|
||||
|
||||
|
@ -302,16 +303,6 @@ ssize_t Vector<TYPE>::removeItemsAt(size_t index, size_t count) {
|
|||
return VectorImpl::removeItemsAt(index, count);
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
status_t Vector<TYPE>::sort(Vector<TYPE>::compar_t cmp) {
|
||||
return VectorImpl::sort((VectorImpl::compar_t)cmp);
|
||||
}
|
||||
|
||||
template<class TYPE> inline
|
||||
status_t Vector<TYPE>::sort(Vector<TYPE>::compar_r_t cmp, void* state) {
|
||||
return VectorImpl::sort((VectorImpl::compar_r_t)cmp, state);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
template<class TYPE>
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
BUILD_LIBSYSUTILS := false
|
||||
ifneq ($(TARGET_SIMULATOR),true)
|
||||
BUILD_LIBSYSUTILS := true
|
||||
endif
|
||||
|
||||
ifeq ($(BUILD_LIBSYSUTILS),true)
|
||||
|
||||
LOCAL_PATH:= $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_SRC_FILES:= \
|
||||
src/SocketListener.cpp \
|
||||
src/FrameworkListener.cpp \
|
||||
src/NetlinkListener.cpp \
|
||||
src/NetlinkEvent.cpp \
|
||||
src/FrameworkCommand.cpp \
|
||||
src/SocketClient.cpp \
|
||||
src/ServiceManager.cpp \
|
||||
|
||||
LOCAL_MODULE:= libsysutils
|
||||
|
||||
LOCAL_C_INCLUDES := $(KERNEL_HEADERS)
|
||||
|
||||
LOCAL_CFLAGS :=
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := libcutils
|
||||
|
||||
ifeq ($(TARGET_SIMULATOR),true)
|
||||
LOCAL_LDLIBS += -lpthread
|
||||
endif
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
||||
endif
|
|
@ -0,0 +1,40 @@
|
|||
#include <alloca.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#define LOG_TAG "FrameworkClient"
|
||||
#include <cutils/log.h>
|
||||
|
||||
#include <sysutils/FrameworkClient.h>
|
||||
|
||||
FrameworkClient::FrameworkClient(int socket) {
|
||||
mSocket = socket;
|
||||
pthread_mutex_init(&mWriteMutex, NULL);
|
||||
}
|
||||
|
||||
int FrameworkClient::sendMsg(const char *msg) {
|
||||
if (mSocket < 0) {
|
||||
errno = EHOSTUNREACH;
|
||||
return -1;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&mWriteMutex);
|
||||
if (write(mSocket, msg, strlen(msg) +1) < 0) {
|
||||
LOGW("Unable to send msg '%s' (%s)", msg, strerror(errno));
|
||||
}
|
||||
pthread_mutex_unlock(&mWriteMutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FrameworkClient::sendMsg(const char *msg, const char *data) {
|
||||
char *buffer = (char *) alloca(strlen(msg) + strlen(data) + 1);
|
||||
if (!buffer) {
|
||||
errno = -ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
strcpy(buffer, msg);
|
||||
strcat(buffer, data);
|
||||
return sendMsg(buffer);
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <errno.h>
|
||||
|
||||
#define LOG_TAG "FrameworkCommand"
|
||||
|
||||
#include <cutils/log.h>
|
||||
|
||||
#include <sysutils/FrameworkCommand.h>
|
||||
|
||||
FrameworkCommand::FrameworkCommand(const char *cmd) {
|
||||
mCommand = cmd;
|
||||
}
|
||||
|
||||
int FrameworkCommand::runCommand(SocketClient *c, int argc, char **argv) {
|
||||
LOGW("Command %s has no run handler!", getCommand());
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#define LOG_TAG "FrameworkListener"
|
||||
|
||||
#include <cutils/log.h>
|
||||
|
||||
#include <sysutils/FrameworkListener.h>
|
||||
#include <sysutils/FrameworkCommand.h>
|
||||
#include <sysutils/SocketClient.h>
|
||||
|
||||
FrameworkListener::FrameworkListener(const char *socketName) :
|
||||
SocketListener(socketName, true) {
|
||||
mCommands = new FrameworkCommandCollection();
|
||||
}
|
||||
|
||||
bool FrameworkListener::onDataAvailable(SocketClient *c) {
|
||||
char buffer[255];
|
||||
int len;
|
||||
|
||||
if ((len = read(c->getSocket(), buffer, sizeof(buffer) -1)) < 0) {
|
||||
LOGE("read() failed (%s)", strerror(errno));
|
||||
return errno;
|
||||
} else if (!len)
|
||||
return false;
|
||||
|
||||
int offset = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (buffer[i] == '\0') {
|
||||
dispatchCommand(c, buffer + offset);
|
||||
offset = i + 1;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void FrameworkListener::registerCmd(FrameworkCommand *cmd) {
|
||||
mCommands->push_back(cmd);
|
||||
}
|
||||
|
||||
void FrameworkListener::dispatchCommand(SocketClient *cli, char *data) {
|
||||
int argc;
|
||||
char *argv[FrameworkListener::CMD_ARGS_MAX];
|
||||
|
||||
if (!index(data, '"')) {
|
||||
char *next = data;
|
||||
char *field;
|
||||
int i;
|
||||
|
||||
for (i = 0; (i < FrameworkListener::CMD_ARGS_MAX) &&
|
||||
(argv[i] = strsep(&next, " ")); i++);
|
||||
argc = i+1;
|
||||
} else {
|
||||
LOGD("blehhh not supported");
|
||||
return;
|
||||
}
|
||||
|
||||
FrameworkCommandCollection::iterator i;
|
||||
|
||||
for (i = mCommands->begin(); i != mCommands->end(); ++i) {
|
||||
FrameworkCommand *c = *i;
|
||||
|
||||
if (!strcmp(argv[0], c->getCommand())) {
|
||||
if (c->runCommand(cli, argc, argv)) {
|
||||
LOGW("Handler '%s' error (%s)", c->getCommand(), strerror(errno));
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
cli->sendMsg(500, "Command not recognized", false);
|
||||
return;
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define LOG_TAG "NetlinkEvent"
|
||||
#include <cutils/log.h>
|
||||
|
||||
#include <sysutils/NetlinkEvent.h>
|
||||
|
||||
const int NetlinkEvent::NlActionUnknown = 0;
|
||||
const int NetlinkEvent::NlActionAdd = 1;
|
||||
const int NetlinkEvent::NlActionRemove = 2;
|
||||
const int NetlinkEvent::NlActionChange = 3;
|
||||
|
||||
NetlinkEvent::NetlinkEvent() {
|
||||
mAction = NlActionUnknown;
|
||||
}
|
||||
|
||||
NetlinkEvent::~NetlinkEvent() {
|
||||
int i;
|
||||
if (mPath)
|
||||
free(mPath);
|
||||
if (mSubsystem)
|
||||
free(mSubsystem);
|
||||
for (i = 0; i < NL_PARAMS_MAX; i++) {
|
||||
if (!mParams[i])
|
||||
break;
|
||||
free(mParams[i]);
|
||||
}
|
||||
}
|
||||
|
||||
bool NetlinkEvent::decode(char *buffer, int size) {
|
||||
char *s = buffer;
|
||||
char *end;
|
||||
int param_idx = 0;
|
||||
int i;
|
||||
int first = 1;
|
||||
|
||||
end = s + size;
|
||||
while (s < end) {
|
||||
if (first) {
|
||||
char *p;
|
||||
for (p = s; *p != '@'; p++);
|
||||
p++;
|
||||
mPath = strdup(p);
|
||||
first = 0;
|
||||
} else {
|
||||
if (!strncmp(s, "ACTION=", strlen("ACTION="))) {
|
||||
char *a = s + strlen("ACTION=");
|
||||
if (!strcmp(a, "add"))
|
||||
mAction = NlActionAdd;
|
||||
else if (!strcmp(a, "remove"))
|
||||
mAction = NlActionRemove;
|
||||
else if (!strcmp(a, "change"))
|
||||
mAction = NlActionChange;
|
||||
} else if (!strncmp(s, "SEQNUM=", strlen("SEQNUM=")))
|
||||
mSeq = atoi(s + strlen("SEQNUM="));
|
||||
else if (!strncmp(s, "SUBSYSTEM=", strlen("SUBSYSTEM=")))
|
||||
mSubsystem = strdup(s + strlen("SUBSYSTEM="));
|
||||
else
|
||||
mParams[param_idx++] = strdup(s);
|
||||
}
|
||||
s+= strlen(s) + 1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const char *NetlinkEvent::findParam(const char *paramName) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NL_PARAMS_MAX; i++) {
|
||||
if (!mParams[i])
|
||||
break;
|
||||
if (!strncmp(mParams[i], paramName, strlen(paramName)))
|
||||
return &mParams[i][strlen(paramName) + 1];
|
||||
}
|
||||
|
||||
LOGE("NetlinkEvent::FindParam(): Parameter '%s' not found", paramName);
|
||||
return NULL;
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <errno.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <string.h>
|
||||
|
||||
#define LOG_TAG "NetlinkListener"
|
||||
#include <cutils/log.h>
|
||||
|
||||
#include <sysutils/NetlinkListener.h>
|
||||
#include <sysutils/NetlinkEvent.h>
|
||||
|
||||
NetlinkListener::NetlinkListener(int socket) :
|
||||
SocketListener(socket, false) {
|
||||
}
|
||||
|
||||
bool NetlinkListener::onDataAvailable(SocketClient *cli)
|
||||
{
|
||||
int socket = cli->getSocket();
|
||||
LOGD("NetlinkListener::onDataAvailable()");
|
||||
|
||||
int count;
|
||||
|
||||
if ((count = recv(socket, mBuffer, sizeof(mBuffer), 0)) < 0) {
|
||||
LOGE("recv failed (%s)", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
NetlinkEvent *evt = new NetlinkEvent();
|
||||
if (!evt->decode(mBuffer, count)) {
|
||||
LOGE("Error decoding NetlinkEvent");
|
||||
goto out;
|
||||
}
|
||||
|
||||
LOGD("Ignoring '%s' netlink event", evt->getSubsystem());
|
||||
|
||||
out:
|
||||
delete evt;
|
||||
return true;
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
#include <errno.h>
|
||||
|
||||
#include <sysutils/ServiceManager.h>
|
||||
|
||||
#define LOG_TAG "Service"
|
||||
#include <cutils/log.h>
|
||||
#include <cutils/properties.h>
|
||||
|
||||
ServiceManager::ServiceManager() {
|
||||
}
|
||||
|
||||
int ServiceManager::start(const char *name) {
|
||||
if (isRunning(name)) {
|
||||
LOGW("Service '%s' is already running", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
LOGD("Starting service '%s'", name);
|
||||
property_set("ctl.start", name);
|
||||
|
||||
int count = 200;
|
||||
while(count--) {
|
||||
sched_yield();
|
||||
if (isRunning(name))
|
||||
break;
|
||||
}
|
||||
if (!count) {
|
||||
LOGW("Timed out waiting for service '%s' to start", name);
|
||||
errno = ETIMEDOUT;
|
||||
return -1;
|
||||
}
|
||||
LOGD("Sucessfully started '%s'", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ServiceManager::stop(const char *name) {
|
||||
if (!isRunning(name)) {
|
||||
LOGW("Service '%s' is already stopped", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
LOGD("Stopping service '%s'", name);
|
||||
property_set("ctl.stop", name);
|
||||
|
||||
int count = 200;
|
||||
while(count--) {
|
||||
sched_yield();
|
||||
if (!isRunning(name))
|
||||
break;
|
||||
}
|
||||
|
||||
if (!count) {
|
||||
LOGW("Timed out waiting for service '%s' to stop", name);
|
||||
errno = ETIMEDOUT;
|
||||
return -1;
|
||||
}
|
||||
LOGD("Sucessfully stopped '%s'", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool ServiceManager::isRunning(const char *name) {
|
||||
char propVal[PROPERTY_VALUE_MAX];
|
||||
char propName[255];
|
||||
|
||||
snprintf(propName, sizeof(propVal), "init.svc.%s", name);
|
||||
|
||||
|
||||
if (property_get(propName, propVal, NULL)) {
|
||||
if (!strcmp(propVal, "running"))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
#include <alloca.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <pthread.h>
|
||||
#include <string.h>
|
||||
|
||||
#define LOG_TAG "SocketClient"
|
||||
#include <cutils/log.h>
|
||||
|
||||
#include <sysutils/SocketClient.h>
|
||||
|
||||
SocketClient::SocketClient(int socket) {
|
||||
mSocket = socket;
|
||||
pthread_mutex_init(&mWriteMutex, NULL);
|
||||
}
|
||||
|
||||
int SocketClient::sendMsg(int code, const char *msg, bool addErrno) {
|
||||
char *buf;
|
||||
|
||||
if (addErrno) {
|
||||
buf = (char *) alloca(strlen(msg) + strlen(strerror(errno)) + 8);
|
||||
sprintf(buf, "%.3d %s (%s)", code, msg, strerror(errno));
|
||||
} else {
|
||||
buf = (char *) alloca(strlen(msg) + strlen("XXX "));
|
||||
sprintf(buf, "%.3d %s", code, msg);
|
||||
}
|
||||
return sendMsg(buf);
|
||||
}
|
||||
|
||||
int SocketClient::sendMsg(const char *msg) {
|
||||
if (mSocket < 0) {
|
||||
errno = EHOSTUNREACH;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Send the message including null character
|
||||
int rc = 0;
|
||||
const char *p = msg;
|
||||
int brtw = strlen(msg) + 1;
|
||||
|
||||
pthread_mutex_lock(&mWriteMutex);
|
||||
while(brtw) {
|
||||
if ((rc = write(mSocket,p, brtw)) < 0) {
|
||||
LOGW("Unable to send msg '%s' (%s)", msg, strerror(errno));
|
||||
pthread_mutex_unlock(&mWriteMutex);
|
||||
return -1;
|
||||
} else if (!rc) {
|
||||
LOGW("0 length write :(");
|
||||
errno = EIO;
|
||||
pthread_mutex_unlock(&mWriteMutex);
|
||||
return -1;
|
||||
}
|
||||
p += rc;
|
||||
brtw -= rc;
|
||||
}
|
||||
pthread_mutex_unlock(&mWriteMutex);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,197 @@
|
|||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#define LOG_TAG "SocketListener"
|
||||
#include <cutils/log.h>
|
||||
#include <cutils/sockets.h>
|
||||
|
||||
#include <sysutils/SocketListener.h>
|
||||
#include <sysutils/SocketClient.h>
|
||||
|
||||
SocketListener::SocketListener(const char *socketName, bool listen) {
|
||||
mListen = listen;
|
||||
mSocketName = socketName;
|
||||
mSock = -1;
|
||||
pthread_mutex_init(&mClientsLock, NULL);
|
||||
mClients = new SocketClientCollection();
|
||||
}
|
||||
|
||||
SocketListener::SocketListener(int socketFd, bool listen) {
|
||||
mListen = listen;
|
||||
mSocketName = NULL;
|
||||
mSock = socketFd;
|
||||
pthread_mutex_init(&mClientsLock, NULL);
|
||||
mClients = new SocketClientCollection();
|
||||
}
|
||||
|
||||
int SocketListener::startListener() {
|
||||
|
||||
if (!mSocketName && mSock == -1) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
} else if (mSocketName) {
|
||||
if ((mSock = android_get_control_socket(mSocketName)) < 0) {
|
||||
LOGE("Obtaining file descriptor socket '%s' failed: %s",
|
||||
mSocketName, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (mListen && listen(mSock, 4) < 0) {
|
||||
LOGE("Unable to listen on socket (%s)", strerror(errno));
|
||||
return -1;
|
||||
} else if (!mListen)
|
||||
mClients->push_back(new SocketClient(mSock));
|
||||
|
||||
if (pipe(mCtrlPipe))
|
||||
return -1;
|
||||
|
||||
if (pthread_create(&mThread, NULL, SocketListener::threadStart, this))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SocketListener::stopListener() {
|
||||
char c = 0;
|
||||
|
||||
if (write(mCtrlPipe[1], &c, 1) != 1) {
|
||||
LOGE("Error writing to control pipe (%s)", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
void *ret;
|
||||
if (pthread_join(mThread, &ret)) {
|
||||
LOGE("Error joining to listener thread (%s)", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
close(mCtrlPipe[0]);
|
||||
close(mCtrlPipe[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *SocketListener::threadStart(void *obj) {
|
||||
SocketListener *me = reinterpret_cast<SocketListener *>(obj);
|
||||
|
||||
me->runListener();
|
||||
pthread_exit(NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void SocketListener::runListener() {
|
||||
|
||||
while(1) {
|
||||
SocketClientCollection::iterator it;
|
||||
fd_set read_fds;
|
||||
int rc = 0;
|
||||
int max = 0;
|
||||
|
||||
FD_ZERO(&read_fds);
|
||||
|
||||
if (mListen) {
|
||||
max = mSock;
|
||||
FD_SET(mSock, &read_fds);
|
||||
}
|
||||
|
||||
FD_SET(mCtrlPipe[0], &read_fds);
|
||||
if (mCtrlPipe[0] > max)
|
||||
max = mCtrlPipe[0];
|
||||
|
||||
pthread_mutex_lock(&mClientsLock);
|
||||
for (it = mClients->begin(); it != mClients->end(); ++it) {
|
||||
FD_SET((*it)->getSocket(), &read_fds);
|
||||
if ((*it)->getSocket() > max)
|
||||
max = (*it)->getSocket();
|
||||
}
|
||||
pthread_mutex_unlock(&mClientsLock);
|
||||
|
||||
if ((rc = select(max + 1, &read_fds, NULL, NULL, NULL)) < 0) {
|
||||
LOGE("select failed (%s)", strerror(errno));
|
||||
sleep(1);
|
||||
continue;
|
||||
} else if (!rc)
|
||||
continue;
|
||||
|
||||
if (FD_ISSET(mCtrlPipe[0], &read_fds))
|
||||
break;
|
||||
if (mListen && FD_ISSET(mSock, &read_fds)) {
|
||||
struct sockaddr addr;
|
||||
socklen_t alen = sizeof(addr);
|
||||
int c;
|
||||
|
||||
if ((c = accept(mSock, &addr, &alen)) < 0) {
|
||||
LOGE("accept failed (%s)", strerror(errno));
|
||||
sleep(1);
|
||||
continue;
|
||||
}
|
||||
pthread_mutex_lock(&mClientsLock);
|
||||
mClients->push_back(new SocketClient(c));
|
||||
pthread_mutex_unlock(&mClientsLock);
|
||||
}
|
||||
|
||||
do {
|
||||
pthread_mutex_lock(&mClientsLock);
|
||||
for (it = mClients->begin(); it != mClients->end(); ++it) {
|
||||
int fd = (*it)->getSocket();
|
||||
if (FD_ISSET(fd, &read_fds)) {
|
||||
pthread_mutex_unlock(&mClientsLock);
|
||||
if (!onDataAvailable(*it)) {
|
||||
close(fd);
|
||||
pthread_mutex_lock(&mClientsLock);
|
||||
delete *it;
|
||||
it = mClients->erase(it);
|
||||
pthread_mutex_unlock(&mClientsLock);
|
||||
}
|
||||
FD_CLR(fd, &read_fds);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&mClientsLock);
|
||||
} while (0);
|
||||
}
|
||||
}
|
||||
|
||||
void SocketListener::sendBroadcast(int code, const char *msg, bool addErrno) {
|
||||
pthread_mutex_lock(&mClientsLock);
|
||||
SocketClientCollection::iterator i;
|
||||
|
||||
for (i = mClients->begin(); i != mClients->end(); ++i) {
|
||||
if ((*i)->sendMsg(code, msg, addErrno)) {
|
||||
LOGW("Error sending broadcast (%s)", strerror(errno));
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&mClientsLock);
|
||||
}
|
||||
|
||||
void SocketListener::sendBroadcast(const char *msg) {
|
||||
pthread_mutex_lock(&mClientsLock);
|
||||
SocketClientCollection::iterator i;
|
||||
|
||||
for (i = mClients->begin(); i != mClients->end(); ++i) {
|
||||
if ((*i)->sendMsg(msg)) {
|
||||
LOGW("Error sending broadcast (%s)", strerror(errno));
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&mClientsLock);
|
||||
}
|
|
@ -323,6 +323,12 @@
|
|||
# PDP drop caused by network
|
||||
50109 pdp_network_drop (cid|1|5), (network_type|1|5)
|
||||
|
||||
# CDMA data network setup failure
|
||||
50110 cdma_data_setup_failed (cause|1|5), (cid|1|5), (network_type|1|5)
|
||||
|
||||
# CDMA data network drop
|
||||
50111 cdma_data_drop (cid|1|5), (network_type|1|5)
|
||||
|
||||
# Do not change these names without updating tag in:
|
||||
#//device/dalvik/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.c
|
||||
51000 socket_stats (send|1|2),(recv|1|2),(ip|1|5),(port|1|5),(close|1|5)
|
||||
|
@ -344,3 +350,6 @@
|
|||
# browser stats for diary study
|
||||
70101 browser_zoom_level_change (start level|1|5),(end level|1|5),(time|2|3)
|
||||
70102 browser_double_tap_duration (duration|1|3),(time|2|3)
|
||||
|
||||
# NOTE - the range 1000000-2000000 is reserved for partners and others who
|
||||
# want to define their own log tags without conflicting with the core platform.
|
||||
|
|
|
@ -63,6 +63,7 @@ int usage(void)
|
|||
" [ --second <2ndbootloader-filename> ]\n"
|
||||
" [ --cmdline <kernel-commandline> ]\n"
|
||||
" [ --board <boardname> ]\n"
|
||||
" [ --base <address> ]\n"
|
||||
" -o|--output <filename>\n"
|
||||
);
|
||||
return 1;
|
||||
|
@ -104,7 +105,6 @@ int main(int argc, char **argv)
|
|||
char *bootimg = 0;
|
||||
char *board = "";
|
||||
unsigned pagesize = 2048;
|
||||
unsigned saddr = 0;
|
||||
int fd;
|
||||
SHA_CTX ctx;
|
||||
uint8_t* sha;
|
||||
|
@ -114,6 +114,14 @@ int main(int argc, char **argv)
|
|||
|
||||
memset(&hdr, 0, sizeof(hdr));
|
||||
|
||||
/* default load addresses */
|
||||
hdr.kernel_addr = 0x10008000;
|
||||
hdr.ramdisk_addr = 0x11000000;
|
||||
hdr.second_addr = 0x10F00000;
|
||||
hdr.tags_addr = 0x10000100;
|
||||
|
||||
hdr.page_size = pagesize;
|
||||
|
||||
while(argc > 0){
|
||||
char *arg = argv[0];
|
||||
char *val = argv[1];
|
||||
|
@ -132,8 +140,12 @@ int main(int argc, char **argv)
|
|||
second_fn = val;
|
||||
} else if(!strcmp(arg, "--cmdline")) {
|
||||
cmdline = val;
|
||||
} else if(!strcmp(arg, "--saddr")) {
|
||||
saddr = strtoul(val, 0, 16);
|
||||
} else if(!strcmp(arg, "--base")) {
|
||||
unsigned base = strtoul(val, 0, 16);
|
||||
hdr.kernel_addr = base + 0x00008000;
|
||||
hdr.ramdisk_addr = base + 0x01000000;
|
||||
hdr.second_addr = base + 0x00F00000;
|
||||
hdr.tags_addr = base + 0x00000100;
|
||||
} else if(!strcmp(arg, "--board")) {
|
||||
board = val;
|
||||
} else {
|
||||
|
@ -163,16 +175,6 @@ int main(int argc, char **argv)
|
|||
|
||||
strcpy(hdr.name, board);
|
||||
|
||||
hdr.kernel_addr = 0x10008000;
|
||||
hdr.ramdisk_addr = 0x11000000;
|
||||
if(saddr) {
|
||||
hdr.second_addr = 0x00300000;
|
||||
} else {
|
||||
hdr.second_addr = 0x10F00000;
|
||||
}
|
||||
hdr.tags_addr = 0x10000100;
|
||||
hdr.page_size = pagesize;
|
||||
|
||||
memcpy(hdr.magic, BOOT_MAGIC, BOOT_MAGIC_SIZE);
|
||||
|
||||
if(strlen(cmdline) > (BOOT_ARGS_SIZE - 1)) {
|
||||
|
|
774
mountd/ASEC.c
774
mountd/ASEC.c
|
@ -1,774 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
** Android Secure External Cache
|
||||
*/
|
||||
|
||||
#include "mountd.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <dirent.h>
|
||||
#include <ctype.h>
|
||||
#include <pwd.h>
|
||||
#include <stdlib.h>
|
||||
#include <poll.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <linux/dm-ioctl.h>
|
||||
#include <linux/loop.h>
|
||||
|
||||
#include <cutils/properties.h>
|
||||
#include <cutils/misc.h>
|
||||
|
||||
#include "ASEC.h"
|
||||
|
||||
//#define MODULE_FAILURE_IS_FATAL
|
||||
|
||||
extern int init_module(void *, unsigned long, const char *);
|
||||
extern int delete_module(const char *, unsigned int);
|
||||
|
||||
struct asec_context
|
||||
{
|
||||
char *name; // Device mapper volume name
|
||||
char *srcPath; // Path to the source (original) mount
|
||||
char *backingFile; // Name of the image file
|
||||
unsigned int sectors; // Number of sectors
|
||||
char *dstPath; // Destination mount point
|
||||
char *crypt; // Crypt options
|
||||
|
||||
boolean needs_format;
|
||||
boolean started;
|
||||
int cacheFd;
|
||||
int lo_num;
|
||||
int dm_num;
|
||||
unsigned char key[16];
|
||||
};
|
||||
|
||||
static const char *MODULES[] = { "dm_mod", "crypto", "crypto_algapi", "crypto_blkcipher",
|
||||
"cryptomgr", "dm_crypt", "jbd",
|
||||
"twofish_common", "twofish", "cbc",
|
||||
"mbcache", "ext3",
|
||||
NULL };
|
||||
static const char KEY_PATH[] = "/data/system/asec.key";
|
||||
static const char MODULE_PATH[] = "/system/lib/modules";
|
||||
static const char MKE2FS_PATH[] = "/system/bin/mke2fs";
|
||||
static const char E2FSCK_PATH[] = "/system/bin/e2fsck";
|
||||
|
||||
boolean AsecIsStarted(void *Handle)
|
||||
{
|
||||
struct asec_context *ctx = (struct asec_context *) Handle;
|
||||
|
||||
return ctx->started;
|
||||
}
|
||||
|
||||
const char *AsecMountPoint(void *Handle)
|
||||
{
|
||||
struct asec_context *ctx = (struct asec_context *) Handle;
|
||||
|
||||
return ctx->dstPath;
|
||||
}
|
||||
|
||||
static boolean AsecIsEnabled()
|
||||
{
|
||||
char value[PROPERTY_VALUE_MAX];
|
||||
int enabled;
|
||||
|
||||
property_get(ASEC_ENABLED, value, "0");
|
||||
|
||||
if (atoi(value) == 1)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void *AsecInit(const char *Name, const char *SrcPath, const char *BackingFile,
|
||||
const char *Size, const char *DstPath, const char *Crypt)
|
||||
{
|
||||
struct asec_context *ctx;
|
||||
|
||||
if (!AsecIsEnabled())
|
||||
return NULL;
|
||||
|
||||
LOG_ASEC("AsecInit(%s, %s, %s, %s, %s, %s):\n",
|
||||
Name, SrcPath, BackingFile, Size, DstPath, Crypt);
|
||||
|
||||
if (!Name || !SrcPath || !BackingFile || !Size || !DstPath || !Crypt) {
|
||||
LOG_ERROR("AsecInit(): Invalid arguments\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(ctx = malloc(sizeof(struct asec_context)))) {
|
||||
LOG_ERROR("AsecInit(): Out of memory\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(ctx, 0, sizeof(struct asec_context));
|
||||
ctx->name = strdup(Name);
|
||||
ctx->srcPath = strdup(SrcPath);
|
||||
ctx->backingFile = strdup(BackingFile);
|
||||
ctx->sectors = atoi(Size);
|
||||
ctx->dstPath = strdup(DstPath);
|
||||
ctx->crypt = strdup(Crypt);
|
||||
return ctx;
|
||||
}
|
||||
|
||||
void AsecDeinit(void *Handle)
|
||||
{
|
||||
struct asec_context *ctx = (struct asec_context *) Handle;
|
||||
|
||||
free(ctx->name);
|
||||
free(ctx->srcPath);
|
||||
free(ctx->backingFile);
|
||||
free(ctx->dstPath);
|
||||
free(ctx->crypt);
|
||||
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
static int AsecLoadModules()
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; MODULES[i] != NULL; i++) {
|
||||
const char *moduleName = MODULES[i];
|
||||
char moduleFile[255];
|
||||
int rc = 0;
|
||||
void *module;
|
||||
unsigned int size;
|
||||
|
||||
sprintf(moduleFile, "%s/%s.ko", MODULE_PATH, moduleName);
|
||||
module = load_file(moduleFile, &size);
|
||||
if (!module) {
|
||||
LOG_ERROR("Failed to load module %s (%d)\n", moduleFile, errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = init_module(module, size, "");
|
||||
free(module);
|
||||
if (rc && errno != EEXIST) {
|
||||
LOG_ERROR("Failed to init module %s (%d)\n", moduleFile, errno);
|
||||
return -errno;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int AsecUnloadModules()
|
||||
{
|
||||
int i, j, rc;
|
||||
|
||||
for (i = 0; MODULES[i] != NULL; i++);
|
||||
|
||||
for (j = (i - 1); j >= 0; j--) {
|
||||
const char *moduleName = MODULES[j];
|
||||
int maxretry = 10;
|
||||
while(maxretry-- > 0) {
|
||||
rc = delete_module(moduleName, O_NONBLOCK | O_EXCL);
|
||||
if (rc < 0 && errno == EAGAIN)
|
||||
usleep(500000);
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (rc != 0) {
|
||||
LOG_ERROR("Failed to unload module %s\n", moduleName);
|
||||
return -errno;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int AsecGenerateKey(struct asec_context *ctx)
|
||||
{
|
||||
LOG_ASEC("AsecGenerateKey():\n");
|
||||
|
||||
memset((void *) ctx->key, 0x69, sizeof(ctx->key));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int AsecLoadGenerateKey(struct asec_context *ctx)
|
||||
{
|
||||
int fd;
|
||||
int rc = 0;
|
||||
|
||||
if ((fd = open(KEY_PATH, O_RDWR | O_CREAT, 0600)) < 0) {
|
||||
LOG_ERROR("Error opening / creating keyfile (%d)\n", errno);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (read(fd, ctx->key, sizeof(ctx->key)) != sizeof(ctx->key)) {
|
||||
LOG_ASEC("Generating key\n");
|
||||
if ((rc = AsecGenerateKey(ctx)) < 0) {
|
||||
LOG_ERROR("Error generating key (%d)\n", rc);
|
||||
goto out;
|
||||
}
|
||||
if (write(fd, ctx->key, sizeof(ctx->key)) != sizeof(ctx->key)) {
|
||||
LOG_ERROR("Error writing keyfile (%d)\n", errno);
|
||||
rc = -1;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
close (fd);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int AsecFormatFilesystem(struct asec_context *ctx)
|
||||
{
|
||||
char cmdline[255];
|
||||
int rc;
|
||||
|
||||
sprintf(cmdline,
|
||||
"%s -b 4096 -m 1 -j -L \"%s\" /dev/block/dm-%d",
|
||||
MKE2FS_PATH, ctx->name, ctx->dm_num);
|
||||
|
||||
LOG_ASEC("Formatting filesystem (%s)\n", cmdline);
|
||||
// XXX: PROTECT FROM VIKING KILLER
|
||||
if ((rc = system(cmdline)) < 0) {
|
||||
LOG_ERROR("Error executing format command (%d)\n", errno);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
rc = WEXITSTATUS(rc);
|
||||
|
||||
if (!rc) {
|
||||
LOG_ASEC("Format completed\n");
|
||||
} else {
|
||||
LOG_ASEC("Format failed (%d)\n", rc);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int AsecCheckFilesystem(struct asec_context *ctx)
|
||||
{
|
||||
char cmdline[255];
|
||||
int rc;
|
||||
|
||||
sprintf(cmdline, "%s -p /dev/block/dm-%d", E2FSCK_PATH, ctx->dm_num);
|
||||
|
||||
LOG_ASEC("Checking filesystem (%s)\n", cmdline);
|
||||
// XXX: PROTECT FROM VIKING KILLER
|
||||
if ((rc = system(cmdline)) < 0) {
|
||||
LOG_ERROR("Error executing check command (%d)\n", errno);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
rc = WEXITSTATUS(rc);
|
||||
|
||||
if (rc == 0) {
|
||||
LOG_ASEC("ASEC volume '%s' had no errors\n", ctx->name);
|
||||
} else if (rc == 1) {
|
||||
LOG_ASEC("ASEC volume '%s' had corrected errors\n", ctx->name);
|
||||
rc = 0;
|
||||
} else if (rc == 2) {
|
||||
LOG_ERROR("ASEC volume '%s' had corrected errors (system should be rebooted)\n", ctx->name);
|
||||
} else if (rc == 4) {
|
||||
LOG_ERROR("ASEC volume '%s' had uncorrectable errors\n", ctx->name);
|
||||
} else if (rc == 8) {
|
||||
LOG_ERROR("Operational error while checking volume '%s'\n", ctx->name);
|
||||
} else {
|
||||
LOG_ERROR("Unknown e2fsck exit code (%d)\n", rc);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int AsecOpenCreateCache(struct asec_context *ctx)
|
||||
{
|
||||
char filepath[255];
|
||||
|
||||
sprintf(filepath, "%s/%s", ctx->srcPath, ctx->backingFile);
|
||||
|
||||
if ((ctx->cacheFd = open(filepath, O_RDWR)) < 0) {
|
||||
if (errno == ENOENT) {
|
||||
int rc = 0;
|
||||
|
||||
LOG_ASEC("Creating cache file (%u sectors)\n", ctx->sectors);
|
||||
if ((ctx->cacheFd = creat(filepath, 0600)) < 0) {
|
||||
LOG_ERROR("Error creating cache (%d)\n", errno);
|
||||
return -errno;
|
||||
}
|
||||
if (ftruncate(ctx->cacheFd, ctx->sectors * 512) < 0) {
|
||||
LOG_ERROR("Error truncating cache (%d)\n", errno);
|
||||
close(ctx->cacheFd);
|
||||
unlink(filepath);
|
||||
return -errno;
|
||||
}
|
||||
LOG_ASEC("Cache created (%u sectors) \n", ctx->sectors);
|
||||
close(ctx->cacheFd); // creat() is WRONLY
|
||||
|
||||
if ((ctx->cacheFd = open(filepath, O_RDWR)) < 0) {
|
||||
LOG_ERROR("Error opening cache file (%d)\n", errno);
|
||||
close(ctx->cacheFd);
|
||||
unlink(filepath);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
ctx->needs_format = 1;
|
||||
} else
|
||||
return -errno;
|
||||
} else {
|
||||
struct stat stat_buf;
|
||||
|
||||
if (fstat(ctx->cacheFd, &stat_buf) < 0) {
|
||||
LOG_ERROR("Failed to fstat cache (%d)\n", errno);
|
||||
close(ctx->cacheFd);
|
||||
return -errno;
|
||||
}
|
||||
if (stat_buf.st_size != ctx->sectors * 512) {
|
||||
LOG_ERROR("Cache size %lld != configured size %u\n",
|
||||
stat_buf.st_size, ctx->sectors * 512);
|
||||
}
|
||||
|
||||
// XXX: Verify volume label matches ctx->name
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void AsecCloseCache(struct asec_context *ctx)
|
||||
{
|
||||
close(ctx->cacheFd);
|
||||
}
|
||||
|
||||
static void *_align(void *ptr, unsigned int a)
|
||||
{
|
||||
register unsigned long agn = --a;
|
||||
|
||||
return (void *) (((unsigned long) ptr + agn) & ~agn);
|
||||
}
|
||||
|
||||
static struct dm_ioctl *_dm_ioctl_setup(struct asec_context *ctx, int flags)
|
||||
{
|
||||
void *buffer;
|
||||
void *p;
|
||||
const size_t min_size = 16 * 1024;
|
||||
size_t len = sizeof(struct dm_ioctl);
|
||||
struct dm_ioctl *io;
|
||||
struct dm_target_spec *tgt;
|
||||
int i;
|
||||
char params[1024];
|
||||
char key[80];
|
||||
|
||||
key[0] = '\0';
|
||||
|
||||
for (i = 0; i < (int) sizeof(ctx->key); i++) {
|
||||
char tmp[8];
|
||||
|
||||
sprintf(tmp, "%02x", ctx->key[i]);
|
||||
strcat(key, tmp);
|
||||
}
|
||||
|
||||
// XXX: Handle ctx->crypt
|
||||
sprintf(params, "twofish %s 0 /dev/block/loop%d 0", key, ctx->lo_num);
|
||||
|
||||
if (len < min_size)
|
||||
len = min_size;
|
||||
|
||||
if (!(buffer = malloc(len))) {
|
||||
LOG_ERROR("Unable to allocate memory\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(buffer, 0, len);
|
||||
io = buffer;
|
||||
tgt = (struct dm_target_spec *) &buffer[sizeof(struct dm_ioctl)];
|
||||
|
||||
io->version[0] = 4;
|
||||
io->version[1] = 0;
|
||||
io->version[2] = 0;
|
||||
|
||||
io->data_size = len;
|
||||
io->data_start = sizeof(struct dm_ioctl);
|
||||
|
||||
io->flags = flags;
|
||||
io->dev = 0;
|
||||
|
||||
io->target_count = 1;
|
||||
io->event_nr = 1;
|
||||
strncpy(io->name, ctx->name, sizeof(io->name));
|
||||
|
||||
tgt->status = 0;
|
||||
tgt->sector_start = 0;
|
||||
tgt->length = ctx->sectors;
|
||||
strncpy(tgt->target_type, "crypt", sizeof(tgt->target_type));
|
||||
|
||||
p = buffer + sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec);
|
||||
strcpy((char *) p, params);
|
||||
p+= strlen(params) + 1;
|
||||
|
||||
p = _align(p, 8);
|
||||
tgt->next = p - buffer;
|
||||
|
||||
return io;
|
||||
}
|
||||
|
||||
static int FindNextAvailableDm()
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
char path[255];
|
||||
sprintf(path, "/dev/block/dm-%d", i);
|
||||
if ((access(path, F_OK) < 0) && (errno == ENOENT))
|
||||
return i;
|
||||
}
|
||||
|
||||
LOG_ERROR("Out of device mapper numbers\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int AsecCreateDeviceMapping(struct asec_context *ctx)
|
||||
{
|
||||
struct dm_ioctl *io;
|
||||
int dmFd;
|
||||
int rc = 0;
|
||||
|
||||
ctx->dm_num = FindNextAvailableDm();
|
||||
|
||||
if ((dmFd = open("/dev/device-mapper", O_RDWR)) < 0) {
|
||||
LOG_ERROR("Error opening device mapper (%d)\n", errno);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (!(io = _dm_ioctl_setup(ctx, 0))) {
|
||||
LOG_ERROR("Unable to setup ioctl (out of memory)\n");
|
||||
close(dmFd);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if ((rc = ioctl(dmFd, DM_DEV_CREATE, io)) < 0) {
|
||||
LOG_ERROR("device-mapper create ioctl failed (%d)\n", errno);
|
||||
rc = -errno;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
free(io);
|
||||
|
||||
if (!(io = _dm_ioctl_setup(ctx, DM_STATUS_TABLE_FLAG))) {
|
||||
LOG_ERROR("Unable to setup ioctl (out of memory)\n");
|
||||
rc = -ENOMEM;
|
||||
goto out_nofree;
|
||||
}
|
||||
|
||||
if ((rc = ioctl(dmFd, DM_TABLE_LOAD, io)) < 0) {
|
||||
LOG_ERROR("device-mapper load ioctl failed (%d)\n", errno);
|
||||
rc = -errno;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
free(io);
|
||||
|
||||
if (!(io = _dm_ioctl_setup(ctx, 0))) {
|
||||
LOG_ERROR("Unable to setup ioctl (out of memory)\n");
|
||||
rc = -ENOMEM;
|
||||
goto out_nofree;
|
||||
}
|
||||
|
||||
if ((rc = ioctl(dmFd, DM_DEV_SUSPEND, io)) < 0) {
|
||||
LOG_ERROR("device-mapper resume ioctl failed (%d)\n", errno);
|
||||
rc = -errno;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
out_free:
|
||||
free (io);
|
||||
out_nofree:
|
||||
close (dmFd);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int AsecDestroyDeviceMapping(struct asec_context *ctx)
|
||||
{
|
||||
struct dm_ioctl *io;
|
||||
int dmFd;
|
||||
int rc = 0;
|
||||
|
||||
if ((dmFd = open("/dev/device-mapper", O_RDWR)) < 0) {
|
||||
LOG_ERROR("Error opening device mapper (%d)\n", errno);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (!(io = _dm_ioctl_setup(ctx, DM_PERSISTENT_DEV_FLAG))) {
|
||||
LOG_ERROR("Unable to setup ioctl (out of memory)\n");
|
||||
rc = -ENOMEM;
|
||||
goto out_nofree;
|
||||
}
|
||||
|
||||
if ((rc = ioctl(dmFd, DM_DEV_REMOVE, io)) < 0) {
|
||||
LOG_ERROR("device-mapper remove ioctl failed (%d)\n", errno);
|
||||
rc = -errno;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
out_free:
|
||||
free (io);
|
||||
out_nofree:
|
||||
close (dmFd);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int AsecMountCache(struct asec_context *ctx)
|
||||
{
|
||||
int flags = MS_NODEV | MS_NOEXEC | MS_NOSUID | MS_NOATIME | MS_NODIRATIME;
|
||||
char devname[255];
|
||||
|
||||
if (access(ctx->dstPath, R_OK)) {
|
||||
LOG_ERROR("Destination mount point '%s' unavailable (%d)\n", ctx->dstPath, errno);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
sprintf(devname, "/dev/block/dm-%d", ctx->dm_num);
|
||||
|
||||
if (mount(devname, ctx->dstPath, "ext3", flags, NULL)) {
|
||||
LOG_ERROR("ASEC mount failed (%d)\n", errno);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int AsecUnmountCache(struct asec_context *ctx)
|
||||
{
|
||||
if (umount(ctx->dstPath)) {
|
||||
if (errno == EBUSY) {
|
||||
LOG_ASEC("ASEC volume '%s' still busy\n", ctx->name);
|
||||
} else {
|
||||
LOG_ERROR("ASEC umount failed (%d)\n", errno);
|
||||
}
|
||||
return -errno;
|
||||
}
|
||||
LOG_ASEC("ASEC volume '%s' unmounted\n", ctx->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int FindNextAvailableLoop()
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_LOOP; i++) {
|
||||
struct loop_info info;
|
||||
char devname[255];
|
||||
int fd;
|
||||
|
||||
sprintf(devname, "/dev/block/loop%d", i);
|
||||
|
||||
if ((fd = open(devname, O_RDONLY)) < 0) {
|
||||
LOG_ERROR("Unable to open %s (%d)\n", devname, errno);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (ioctl(fd, LOOP_GET_STATUS, &info) < 0) {
|
||||
close(fd);
|
||||
|
||||
if (errno == ENXIO)
|
||||
return i;
|
||||
|
||||
LOG_ERROR("Unable to get loop status for %s (%d)\n", devname, errno);
|
||||
return -errno;
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
static int AsecCreateLoop(struct asec_context *ctx)
|
||||
{
|
||||
char devname[255];
|
||||
int device_fd;
|
||||
int rc = 0;
|
||||
|
||||
ctx->lo_num = FindNextAvailableLoop();
|
||||
if (ctx->lo_num < 0) {
|
||||
LOG_ERROR("No loop devices available\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
sprintf(devname, "/dev/block/loop%d", ctx->lo_num);
|
||||
device_fd = open(devname, O_RDWR);
|
||||
if (device_fd < 0) {
|
||||
LOG_ERROR("failed to open loop device (%d)\n", errno);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (ioctl(device_fd, LOOP_SET_FD, ctx->cacheFd) < 0) {
|
||||
LOG_ERROR("loop_set_fd ioctl failed (%d)\n", errno);
|
||||
rc = -errno;
|
||||
}
|
||||
close(device_fd);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int AsecDestroyLoop(struct asec_context *ctx)
|
||||
{
|
||||
char devname[255];
|
||||
int device_fd;
|
||||
int rc = 0;
|
||||
|
||||
sprintf(devname, "/dev/block/loop%d", ctx->lo_num);
|
||||
device_fd = open(devname, O_RDONLY);
|
||||
if (device_fd < 0) {
|
||||
LOG_ERROR("Failed to open loop (%d)\n", errno);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (ioctl(device_fd, LOOP_CLR_FD, 0) < 0) {
|
||||
LOG_ERROR("Failed to destroy loop (%d)\n", errno);
|
||||
rc = -errno;
|
||||
}
|
||||
|
||||
close(device_fd);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int AsecStart(void *Handle)
|
||||
{
|
||||
struct asec_context *ctx = (struct asec_context *) Handle;
|
||||
char value[PROPERTY_VALUE_MAX];
|
||||
int rc = 0;
|
||||
|
||||
if (!ctx)
|
||||
return -EINVAL;
|
||||
|
||||
if (ctx->started)
|
||||
return -EBUSY;
|
||||
|
||||
LOG_ASEC("AsecStart(%s):\n", ctx->name);
|
||||
|
||||
NotifyAsecState(ASEC_BUSY, ctx->dstPath);
|
||||
|
||||
if ((rc = AsecLoadModules()) < 0) {
|
||||
LOG_ERROR("AsecStart: Failed to load kernel modules\n");
|
||||
#ifdef MODULE_FAILURE_IS_FATAL
|
||||
NotifyAsecState(ASEC_FAILED_INTERR, ctx->dstPath);
|
||||
return rc;
|
||||
#endif
|
||||
}
|
||||
|
||||
if ((rc = AsecLoadGenerateKey(ctx))) {
|
||||
LOG_ERROR("AsecStart: Failed to load / generate key\n");
|
||||
NotifyAsecState(ASEC_FAILED_INTERR, ctx->dstPath);
|
||||
return rc;
|
||||
}
|
||||
|
||||
if ((rc = AsecOpenCreateCache(ctx)) < 0) {
|
||||
LOG_ERROR("AsecStart: Failed to open / create cache\n");
|
||||
NotifyAsecState(ASEC_FAILED_INTERR, ctx->dstPath);
|
||||
return rc;
|
||||
}
|
||||
|
||||
if ((rc = AsecCreateLoop(ctx)) < 0) {
|
||||
LOG_ERROR("AsecStart: Failed to create loop\n");
|
||||
NotifyAsecState(ASEC_FAILED_INTERR, ctx->dstPath);
|
||||
goto fail_closecache;
|
||||
}
|
||||
|
||||
if ((rc = AsecCreateDeviceMapping(ctx)) < 0) {
|
||||
LOG_ERROR("AsecStart: Failed to create devmapping (%d)\n", rc);
|
||||
NotifyAsecState(ASEC_FAILED_INTERR, ctx->dstPath);
|
||||
goto fail_destroyloop;
|
||||
}
|
||||
|
||||
if (ctx->needs_format) {
|
||||
if ((rc = AsecFormatFilesystem(ctx))) {
|
||||
LOG_ERROR("AsecStart: Failed to format cache (%d)\n", rc);
|
||||
NotifyAsecState(ASEC_FAILED_INTERR, ctx->dstPath);
|
||||
goto fail_destroydm;
|
||||
}
|
||||
ctx->needs_format = 0;
|
||||
} else {
|
||||
if ((rc = AsecCheckFilesystem(ctx))) {
|
||||
LOG_ERROR("AsecStart: Failed to check filesystem (%d)\n", rc);
|
||||
NotifyAsecState(ASEC_FAILED_INTERR, ctx->dstPath);
|
||||
goto fail_destroydm;
|
||||
}
|
||||
}
|
||||
|
||||
if ((rc = AsecMountCache(ctx)) < 0) {
|
||||
LOG_ERROR("AsecStart: Failed to mount cache (%d)\n", rc);
|
||||
NotifyAsecState(ASEC_FAILED_INTERR, ctx->dstPath);
|
||||
goto fail_destroydm;
|
||||
}
|
||||
|
||||
NotifyAsecState(ASEC_AVAILABLE, ctx->dstPath);
|
||||
ctx->started = true;
|
||||
|
||||
return rc;
|
||||
|
||||
fail_destroydm:
|
||||
AsecDestroyDeviceMapping(ctx);
|
||||
fail_destroyloop:
|
||||
AsecDestroyLoop(ctx);
|
||||
fail_closecache:
|
||||
AsecCloseCache(ctx);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int AsecStop(void *Handle)
|
||||
{
|
||||
struct asec_context *ctx = (struct asec_context *) Handle;
|
||||
int rc = 0;
|
||||
|
||||
if (!ctx->started)
|
||||
return -EINVAL;
|
||||
|
||||
LOG_ASEC("AsecStop(%s):\n", ctx->name);
|
||||
|
||||
NotifyAsecState(ASEC_BUSY, ctx->dstPath);
|
||||
|
||||
if ((rc = AsecUnmountCache(ctx)) < 0) {
|
||||
LOG_ERROR("AsecStop: Failed to unmount cache (%d)\n", rc);
|
||||
NotifyAsecState(ASEC_FAILED_INTERR, ctx->dstPath);
|
||||
return rc;
|
||||
}
|
||||
|
||||
if ((rc = AsecDestroyDeviceMapping(ctx)) < 0) {
|
||||
LOG_ERROR("AsecStop: Failed to destroy devmapping (%d)\n", rc);
|
||||
NotifyAsecState(ASEC_FAILED_INTERR, ctx->dstPath);
|
||||
return rc;
|
||||
}
|
||||
|
||||
if ((rc = AsecDestroyLoop(ctx)) < 0) {
|
||||
LOG_ERROR("AsecStop: Failed to destroy loop device (%d)\n", rc);
|
||||
NotifyAsecState(ASEC_FAILED_INTERR, ctx->dstPath);
|
||||
return rc;
|
||||
}
|
||||
|
||||
AsecCloseCache(ctx);
|
||||
|
||||
if ((rc = AsecUnloadModules()) < 0) {
|
||||
if (rc == -EAGAIN) {
|
||||
LOG_ASEC("AsecStop: Kernel modules still in use\n");
|
||||
} else {
|
||||
LOG_ERROR("AsecStop: Failed to unload kernel modules (%d)\n", rc);
|
||||
#ifdef MODULE_FAILURE_IS_FATAL
|
||||
NotifyAsecState(ASEC_FAILED_INTERR, ctx->dstPath);
|
||||
return rc;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
ctx->started = false;
|
||||
NotifyAsecState(ASEC_DISABLED, ctx->dstPath);
|
||||
return rc;
|
||||
}
|
|
@ -1,66 +0,0 @@
|
|||
#ifndef _ASEC_H
|
||||
#define _ASEC_H
|
||||
|
||||
#define ASEC_STORES_MAX 4
|
||||
#define MAX_LOOP 8
|
||||
|
||||
typedef enum AsecState {
|
||||
// Feature disabled
|
||||
ASEC_DISABLED,
|
||||
|
||||
// Feature enabled and operational
|
||||
ASEC_AVAILABLE,
|
||||
|
||||
// Busy
|
||||
ASEC_BUSY,
|
||||
|
||||
// Internal Error
|
||||
ASEC_FAILED_INTERR,
|
||||
|
||||
// No media available
|
||||
ASEC_FAILED_NOMEDIA,
|
||||
|
||||
// Media is corrupt
|
||||
ASEC_FAILED_BADMEDIA,
|
||||
|
||||
// Key mismatch
|
||||
ASEC_FAILED_BADKEY,
|
||||
} AsecState;
|
||||
|
||||
/*
|
||||
* ASEC commands
|
||||
*/
|
||||
#define ASEC_CMD_SEND_STATUS "asec_send_status"
|
||||
#define ASEC_CMD_ENABLE "asec_enable"
|
||||
#define ASEC_CMD_DISABLE "asec_disable"
|
||||
|
||||
/*
|
||||
* ASEC events
|
||||
*/
|
||||
|
||||
// These events correspond to the states in the AsecState enum.
|
||||
// A path to the ASEC mount point follows the colon
|
||||
#define ASEC_EVENT_DISABLED "asec_disabled:"
|
||||
#define ASEC_EVENT_AVAILABLE "asec_available:"
|
||||
#define ASEC_EVENT_BUSY "asec_busy:"
|
||||
#define ASEC_EVENT_FAILED_INTERR "asec_failed_interror:"
|
||||
#define ASEC_EVENT_FAILED_NOMEDIA "asec_failed_nomedia"
|
||||
#define ASEC_EVENT_FAILED_BADMEDIA "asec_failed_badmedia:"
|
||||
#define ASEC_EVENT_FAILED_BADKEY "asec_failed_badkey:"
|
||||
|
||||
/*
|
||||
* System Properties
|
||||
*/
|
||||
|
||||
#define ASEC_ENABLED "asec.enabled"
|
||||
|
||||
#define ASEC_STATUS "ro.asec.status"
|
||||
#define ASEC_STATUS_DISABLED "disabled"
|
||||
#define ASEC_STATUS_AVAILABLE "available"
|
||||
#define ASEC_STATUS_BUSY "busy"
|
||||
#define ASEC_STATUS_FAILED_INTERR "internal_error"
|
||||
#define ASEC_STATUS_FAILED_NOMEDIA "no_media"
|
||||
#define ASEC_STATUS_FAILED_BADMEDIA "bad_media"
|
||||
#define ASEC_STATUS_FAILED_BADKEY "bad_key"
|
||||
|
||||
#endif
|
|
@ -1,22 +0,0 @@
|
|||
LOCAL_PATH:= $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_SRC_FILES:= \
|
||||
AutoMount.c \
|
||||
ProcessKiller.c \
|
||||
Server.c \
|
||||
mountd.c \
|
||||
ASEC.c \
|
||||
logwrapper.c
|
||||
|
||||
LOCAL_MODULE:= mountd
|
||||
|
||||
LOCAL_C_INCLUDES := $(KERNEL_HEADERS)
|
||||
|
||||
LOCAL_CFLAGS := -DCREATE_MOUNT_POINTS=0
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := libcutils
|
||||
|
||||
# disabled - we are using vold now instead
|
||||
# include $(BUILD_EXECUTABLE)
|
1062
mountd/AutoMount.c
1062
mountd/AutoMount.c
File diff suppressed because it is too large
Load Diff
190
mountd/NOTICE
190
mountd/NOTICE
|
@ -1,190 +0,0 @@
|
|||
|
||||
Copyright (c) 2005-2008, The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
|
@ -1,222 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
** mountd process killer
|
||||
*/
|
||||
|
||||
#include "mountd.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <dirent.h>
|
||||
#include <ctype.h>
|
||||
#include <pwd.h>
|
||||
#include <stdlib.h>
|
||||
#include <poll.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
|
||||
static boolean ReadSymLink(const char* path, char* link)
|
||||
{
|
||||
struct stat s;
|
||||
int length;
|
||||
|
||||
if (lstat(path, &s) < 0)
|
||||
return false;
|
||||
if ((s.st_mode & S_IFMT) != S_IFLNK)
|
||||
return false;
|
||||
|
||||
// we have a symlink
|
||||
length = readlink(path, link, PATH_MAX - 1);
|
||||
if (length <= 0)
|
||||
return false;
|
||||
link[length] = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
static boolean PathMatchesMountPoint(const char* path, const char* mountPoint)
|
||||
{
|
||||
int length = strlen(mountPoint);
|
||||
if (length > 1 && strncmp(path, mountPoint, length) == 0)
|
||||
{
|
||||
// we need to do extra checking if mountPoint does not end in a '/'
|
||||
if (mountPoint[length - 1] == '/')
|
||||
return true;
|
||||
// if mountPoint does not have a trailing slash, we need to make sure
|
||||
// there is one in the path to avoid partial matches.
|
||||
return (path[length] == 0 || path[length] == '/');
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void GetProcessName(int pid, char buffer[PATH_MAX])
|
||||
{
|
||||
int fd;
|
||||
sprintf(buffer, "/proc/%d/cmdline", pid);
|
||||
fd = open(buffer, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
strcpy(buffer, "???");
|
||||
} else {
|
||||
int length = read(fd, buffer, PATH_MAX - 1);
|
||||
buffer[length] = 0;
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
|
||||
static boolean CheckFileDescriptorSymLinks(int pid, const char* mountPoint)
|
||||
{
|
||||
DIR* dir;
|
||||
struct dirent* de;
|
||||
boolean fileOpen = false;
|
||||
char path[PATH_MAX];
|
||||
char link[PATH_MAX];
|
||||
int parent_length;
|
||||
|
||||
// compute path to process's directory of open files
|
||||
sprintf(path, "/proc/%d/fd", pid);
|
||||
dir = opendir(path);
|
||||
if (!dir)
|
||||
return false;
|
||||
|
||||
// remember length of the path
|
||||
parent_length = strlen(path);
|
||||
// append a trailing '/'
|
||||
path[parent_length++] = '/';
|
||||
|
||||
while ((de = readdir(dir)) != 0 && !fileOpen) {
|
||||
if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, ".."))
|
||||
continue;
|
||||
|
||||
// append the file name, after truncating to parent directory
|
||||
path[parent_length] = 0;
|
||||
strcat(path, de->d_name);
|
||||
|
||||
if (ReadSymLink(path, link) && PathMatchesMountPoint(link, mountPoint))
|
||||
{
|
||||
char name[PATH_MAX];
|
||||
GetProcessName(pid, name);
|
||||
LOG_ERROR("process %s (%d) has open file %s\n", name, pid, link);
|
||||
fileOpen = true;
|
||||
}
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
return fileOpen;
|
||||
}
|
||||
|
||||
static boolean CheckFileMaps(int pid, const char* mountPoint)
|
||||
{
|
||||
FILE* file;
|
||||
char buffer[PATH_MAX + 100];
|
||||
boolean mapOpen = false;
|
||||
|
||||
sprintf(buffer, "/proc/%d/maps", pid);
|
||||
file = fopen(buffer, "r");
|
||||
if (!file)
|
||||
return false;
|
||||
|
||||
while (!mapOpen && fgets(buffer, sizeof(buffer), file))
|
||||
{
|
||||
// skip to the path
|
||||
const char* path = strchr(buffer, '/');
|
||||
if (path && PathMatchesMountPoint(path, mountPoint))
|
||||
{
|
||||
char name[PATH_MAX];
|
||||
GetProcessName(pid, name);
|
||||
LOG_ERROR("process %s (%d) has open file map for %s\n", name, pid, path);
|
||||
mapOpen = true;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
return mapOpen;
|
||||
}
|
||||
|
||||
static boolean CheckSymLink(int pid, const char* mountPoint, const char* name, const char* message)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
char link[PATH_MAX];
|
||||
|
||||
sprintf(path, "/proc/%d/%s", pid, name);
|
||||
if (ReadSymLink(path, link) && PathMatchesMountPoint(link, mountPoint))
|
||||
{
|
||||
char name[PATH_MAX];
|
||||
GetProcessName(pid, name);
|
||||
LOG_ERROR("process %s (%d) has %s in %s\n", name, pid, message, mountPoint);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
static int get_pid(const char* s)
|
||||
{
|
||||
int result = 0;
|
||||
while (*s) {
|
||||
if (!isdigit(*s)) return -1;
|
||||
result = 10 * result + (*s++ - '0');
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// hunt down and kill processes that have files open on the given mount point
|
||||
void KillProcessesWithOpenFiles(const char* mountPoint, boolean sigkill, int *excluded, int num_excluded)
|
||||
{
|
||||
DIR* dir;
|
||||
struct dirent* de;
|
||||
|
||||
LOG_ERROR("KillProcessesWithOpenFiles %s\n", mountPoint);
|
||||
dir = opendir("/proc");
|
||||
if (!dir) return;
|
||||
|
||||
while ((de = readdir(dir)) != 0)
|
||||
{
|
||||
boolean killed = false;
|
||||
// does the name look like a process ID?
|
||||
int pid = get_pid(de->d_name);
|
||||
if (pid == -1) continue;
|
||||
|
||||
if (CheckFileDescriptorSymLinks(pid, mountPoint) // check for open files
|
||||
|| CheckFileMaps(pid, mountPoint) // check for mmap()
|
||||
|| CheckSymLink(pid, mountPoint, "cwd", "working directory") // check working directory
|
||||
|| CheckSymLink(pid, mountPoint, "root", "chroot") // check for chroot()
|
||||
|| CheckSymLink(pid, mountPoint, "exe", "executable path") // check executable path
|
||||
)
|
||||
{
|
||||
int i;
|
||||
boolean hit = false;
|
||||
|
||||
for (i = 0; i < num_excluded; i++) {
|
||||
if (pid == excluded[i]) {
|
||||
LOG_ERROR("I just need a little more TIME captain!\n");
|
||||
hit = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hit) {
|
||||
LOG_ERROR("Killing process %d\n", pid);
|
||||
kill(pid, (sigkill ? SIGKILL : SIGTERM));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
}
|
313
mountd/Server.c
313
mountd/Server.c
|
@ -1,313 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
** mountd server support
|
||||
*/
|
||||
|
||||
#include "mountd.h"
|
||||
#include "ASEC.h"
|
||||
|
||||
#include <cutils/properties.h>
|
||||
#include <cutils/sockets.h>
|
||||
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <private/android_filesystem_config.h>
|
||||
|
||||
|
||||
// current client file descriptor
|
||||
static int sFD = -1;
|
||||
|
||||
// to synchronize writing to client
|
||||
static pthread_mutex_t sWriteMutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
// path for media that failed to mount before the runtime is connected
|
||||
static char* sDeferredUnmountableMediaPath = NULL;
|
||||
|
||||
// last asec msg before the runtime was connected
|
||||
static char* sAsecDeferredMessage = NULL;
|
||||
static char* sAsecDeferredArgument = NULL;
|
||||
|
||||
static int Write(const char* message)
|
||||
{
|
||||
int result = -1;
|
||||
|
||||
pthread_mutex_lock(&sWriteMutex);
|
||||
|
||||
LOG_SERVER("Write: %s\n", message);
|
||||
if (sFD >= 0)
|
||||
result = write(sFD, message, strlen(message) + 1);
|
||||
|
||||
pthread_mutex_unlock(&sWriteMutex);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int Write2(const char* message, const char* data)
|
||||
{
|
||||
int result = -1;
|
||||
|
||||
char* buffer = (char *)alloca(strlen(message) + strlen(data) + 1);
|
||||
if (!buffer)
|
||||
{
|
||||
LOG_ERROR("alloca failed in Write2\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
strcpy(buffer, message);
|
||||
strcat(buffer, data);
|
||||
return Write(buffer);
|
||||
}
|
||||
|
||||
static void SendStatus()
|
||||
{
|
||||
Write(IsMassStorageConnected() ? MOUNTD_UMS_CONNECTED : MOUNTD_UMS_DISCONNECTED);
|
||||
Write(IsMassStorageEnabled() ? MOUNTD_UMS_ENABLED : MOUNTD_UMS_DISABLED);
|
||||
}
|
||||
|
||||
static void DoCommand(const char* command)
|
||||
{
|
||||
LOG_SERVER("DoCommand %s\n", command);
|
||||
|
||||
if (strcmp(command, MOUNTD_ENABLE_UMS) == 0)
|
||||
{
|
||||
EnableMassStorage(true);
|
||||
Write(MOUNTD_UMS_ENABLED);
|
||||
}
|
||||
else if (strcmp(command, MOUNTD_DISABLE_UMS) == 0)
|
||||
{
|
||||
EnableMassStorage(false);
|
||||
Write(MOUNTD_UMS_DISABLED);
|
||||
}
|
||||
else if (strcmp(command, MOUNTD_SEND_STATUS) == 0)
|
||||
{
|
||||
SendStatus();
|
||||
}
|
||||
else if (strncmp(command, MOUNTD_MOUNT_MEDIA, strlen(MOUNTD_MOUNT_MEDIA)) == 0)
|
||||
{
|
||||
const char* path = command + strlen(MOUNTD_MOUNT_MEDIA);
|
||||
MountMedia(path);
|
||||
}
|
||||
else if (strncmp(command, MOUNTD_EJECT_MEDIA, strlen(MOUNTD_EJECT_MEDIA)) == 0)
|
||||
{
|
||||
const char* path = command + strlen(MOUNTD_EJECT_MEDIA);
|
||||
UnmountMedia(path);
|
||||
}
|
||||
else if (strncmp(command, ASEC_CMD_ENABLE, strlen(ASEC_CMD_ENABLE)) == 0) {
|
||||
LOG_ASEC("Got ASEC_CMD_ENABLE\n");
|
||||
// XXX: SAN: Impliment
|
||||
}
|
||||
else if (strncmp(command, ASEC_CMD_DISABLE, strlen(ASEC_CMD_DISABLE)) == 0) {
|
||||
LOG_ASEC("Got ASEC_CMD_DISABLE\n");
|
||||
// XXX: SAN: Impliment
|
||||
}
|
||||
else if (strncmp(command, ASEC_CMD_SEND_STATUS, strlen(ASEC_CMD_SEND_STATUS)) == 0) {
|
||||
LOG_ASEC("Got ASEC_CMD_SEND_STATUS\n");
|
||||
// XXX: SAN: Impliment
|
||||
}
|
||||
else
|
||||
LOGE("unknown command %s\n", command);
|
||||
}
|
||||
|
||||
int RunServer()
|
||||
{
|
||||
int socket = android_get_control_socket(MOUNTD_SOCKET);
|
||||
if (socket < 0) {
|
||||
LOGE("Obtaining file descriptor for socket '%s' failed: %s",
|
||||
MOUNTD_SOCKET, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (listen(socket, 4) < 0) {
|
||||
LOGE("Unable to listen on file descriptor '%d' for socket '%s': %s",
|
||||
socket, MOUNTD_SOCKET, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
struct sockaddr addr;
|
||||
socklen_t alen;
|
||||
struct ucred cred;
|
||||
socklen_t size;
|
||||
|
||||
alen = sizeof(addr);
|
||||
sFD = accept(socket, &addr, &alen);
|
||||
if (sFD < 0)
|
||||
continue;
|
||||
|
||||
if (sDeferredUnmountableMediaPath) {
|
||||
NotifyMediaState(sDeferredUnmountableMediaPath, MEDIA_UNMOUNTABLE, false);
|
||||
free(sDeferredUnmountableMediaPath);
|
||||
sDeferredUnmountableMediaPath = NULL;
|
||||
}
|
||||
|
||||
if (sAsecDeferredMessage) {
|
||||
|
||||
if (Write2(sAsecDeferredMessage, sAsecDeferredArgument) < 0)
|
||||
LOG_ERROR("Failed to deliver deferred ASEC msg to framework\n");
|
||||
free(sAsecDeferredMessage);
|
||||
free(sAsecDeferredArgument);
|
||||
sAsecDeferredMessage = sAsecDeferredArgument = NULL;
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
char buffer[101];
|
||||
int result = read(sFD, buffer, sizeof(buffer) - 1);
|
||||
if (result > 0)
|
||||
{
|
||||
int start = 0;
|
||||
int i;
|
||||
// command should be zero terminated, but just in case
|
||||
buffer[result] = 0;
|
||||
for (i = 0; i < result; i++)
|
||||
{
|
||||
if (buffer[i] == 0)
|
||||
{
|
||||
DoCommand(buffer + start);
|
||||
start = i + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
close(sFD);
|
||||
sFD = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// should never get here
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SendMassStorageConnected(boolean connected)
|
||||
{
|
||||
Write(connected ? MOUNTD_UMS_CONNECTED : MOUNTD_UMS_DISCONNECTED);
|
||||
}
|
||||
|
||||
void SendUnmountRequest(const char* path)
|
||||
{
|
||||
Write2(MOUNTD_REQUEST_EJECT, path);
|
||||
}
|
||||
|
||||
void NotifyAsecState(AsecState state, const char *argument)
|
||||
{
|
||||
const char *event = NULL;
|
||||
const char *status = NULL;
|
||||
boolean deferr = true;;
|
||||
|
||||
switch (state) {
|
||||
case ASEC_DISABLED:
|
||||
event = ASEC_EVENT_DISABLED;
|
||||
status = ASEC_STATUS_DISABLED;
|
||||
break;
|
||||
case ASEC_AVAILABLE:
|
||||
event = ASEC_EVENT_AVAILABLE;
|
||||
status = ASEC_STATUS_AVAILABLE;
|
||||
break;
|
||||
case ASEC_BUSY:
|
||||
event = ASEC_EVENT_BUSY;
|
||||
status = ASEC_STATUS_BUSY;
|
||||
deferr = false;
|
||||
break;
|
||||
case ASEC_FAILED_INTERR:
|
||||
event = ASEC_EVENT_FAILED_INTERR;
|
||||
status = ASEC_STATUS_FAILED_INTERR;
|
||||
break;
|
||||
case ASEC_FAILED_NOMEDIA:
|
||||
event = ASEC_EVENT_FAILED_NOMEDIA;
|
||||
status = ASEC_STATUS_FAILED_NOMEDIA;
|
||||
break;
|
||||
case ASEC_FAILED_BADMEDIA:
|
||||
event = ASEC_EVENT_FAILED_BADMEDIA;
|
||||
status = ASEC_STATUS_FAILED_BADMEDIA;
|
||||
break;
|
||||
case ASEC_FAILED_BADKEY:
|
||||
event = ASEC_EVENT_FAILED_BADKEY;
|
||||
status = ASEC_STATUS_FAILED_BADKEY;
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("unknown AsecState %d in NotifyAsecState\n", state);
|
||||
return;
|
||||
}
|
||||
|
||||
property_set(ASEC_STATUS, status);
|
||||
|
||||
int result = Write2(event, argument);
|
||||
if ((result < 0) && deferr) {
|
||||
if (sAsecDeferredMessage)
|
||||
free(sAsecDeferredMessage);
|
||||
sAsecDeferredMessage = strdup(event);
|
||||
if (sAsecDeferredArgument)
|
||||
free(sAsecDeferredArgument);
|
||||
sAsecDeferredArgument = strdup(argument);
|
||||
LOG_ASEC("Deferring event '%s' arg '%s' until framework connects\n", event, argument);
|
||||
}
|
||||
}
|
||||
|
||||
void NotifyMediaState(const char* path, MediaState state, boolean readOnly)
|
||||
{
|
||||
const char* event = NULL;
|
||||
const char* propertyValue = NULL;
|
||||
|
||||
switch (state) {
|
||||
case MEDIA_REMOVED:
|
||||
event = MOUNTD_MEDIA_REMOVED;
|
||||
propertyValue = EXTERNAL_STORAGE_REMOVED;
|
||||
break;
|
||||
case MEDIA_UNMOUNTED:
|
||||
event = MOUNTD_MEDIA_UNMOUNTED;
|
||||
propertyValue = EXTERNAL_STORAGE_UNMOUNTED;
|
||||
break;
|
||||
case MEDIA_MOUNTED:
|
||||
event = (readOnly ? MOUNTD_MEDIA_MOUNTED_READ_ONLY : MOUNTD_MEDIA_MOUNTED);
|
||||
propertyValue = (readOnly ? EXTERNAL_STORAGE_MOUNTED_READ_ONLY : EXTERNAL_STORAGE_MOUNTED);
|
||||
break;
|
||||
case MEDIA_SHARED:
|
||||
event = MOUNTD_MEDIA_SHARED;
|
||||
propertyValue = EXTERNAL_STORAGE_SHARED;
|
||||
break;
|
||||
case MEDIA_BAD_REMOVAL:
|
||||
event = MOUNTD_MEDIA_BAD_REMOVAL;
|
||||
propertyValue = EXTERNAL_STORAGE_BAD_REMOVAL;
|
||||
break;
|
||||
case MEDIA_UNMOUNTABLE:
|
||||
event = MOUNTD_MEDIA_UNMOUNTABLE;
|
||||
propertyValue = EXTERNAL_STORAGE_UNMOUNTABLE;
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("unknown MediaState %d in NotifyMediaState\n", state);
|
||||
return;
|
||||
}
|
||||
|
||||
property_set(EXTERNAL_STORAGE_STATE, propertyValue);
|
||||
int result = Write2(event, path);
|
||||
if (result < 0 && state == MEDIA_UNMOUNTABLE) {
|
||||
|
||||
// if we cannot communicate with the runtime, defer this message until the runtime is available
|
||||
sDeferredUnmountableMediaPath = strdup(path);
|
||||
}
|
||||
}
|
|
@ -1,154 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "private/android_filesystem_config.h"
|
||||
#include "cutils/log.h"
|
||||
|
||||
int parent(const char *tag, int parent_read) {
|
||||
int status;
|
||||
char buffer[4096];
|
||||
|
||||
int a = 0; // start index of unprocessed data
|
||||
int b = 0; // end index of unprocessed data
|
||||
int sz;
|
||||
while ((sz = read(parent_read, &buffer[b], sizeof(buffer) - 1 - b)) > 0) {
|
||||
|
||||
sz += b;
|
||||
// Log one line at a time
|
||||
for (b = 0; b < sz; b++) {
|
||||
if (buffer[b] == '\r') {
|
||||
buffer[b] = '\0';
|
||||
} else if (buffer[b] == '\n') {
|
||||
buffer[b] = '\0';
|
||||
LOG(LOG_INFO, tag, &buffer[a]);
|
||||
a = b + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (a == 0 && b == sizeof(buffer) - 1) {
|
||||
// buffer is full, flush
|
||||
buffer[b] = '\0';
|
||||
LOG(LOG_INFO, tag, &buffer[a]);
|
||||
b = 0;
|
||||
} else if (a != b) {
|
||||
// Keep left-overs
|
||||
b -= a;
|
||||
memmove(buffer, &buffer[a], b);
|
||||
a = 0;
|
||||
} else {
|
||||
a = 0;
|
||||
b = 0;
|
||||
}
|
||||
|
||||
}
|
||||
// Flush remaining data
|
||||
if (a != b) {
|
||||
buffer[b] = '\0';
|
||||
LOG(LOG_INFO, tag, &buffer[a]);
|
||||
}
|
||||
status = 0xAAAA;
|
||||
if (wait(&status) != -1) { // Wait for child
|
||||
if (WIFEXITED(status)) {
|
||||
LOG(LOG_INFO, "logwrapper", "%s terminated by exit(%d)", tag,
|
||||
WEXITSTATUS(status));
|
||||
return WEXITSTATUS(status);
|
||||
} else if (WIFSIGNALED(status))
|
||||
LOG(LOG_INFO, "logwrapper", "%s terminated by signal %d", tag,
|
||||
WTERMSIG(status));
|
||||
else if (WIFSTOPPED(status))
|
||||
LOG(LOG_INFO, "logwrapper", "%s stopped by signal %d", tag,
|
||||
WSTOPSIG(status));
|
||||
} else
|
||||
LOG(LOG_INFO, "logwrapper", "%s wait() failed: %s (%d)", tag,
|
||||
strerror(errno), errno);
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
void child(int argc, char* argv[]) {
|
||||
// create null terminated argv_child array
|
||||
char* argv_child[argc + 1];
|
||||
memcpy(argv_child, argv, argc * sizeof(char *));
|
||||
argv_child[argc] = NULL;
|
||||
|
||||
// XXX: PROTECT FROM VIKING KILLER
|
||||
if (execvp(argv_child[0], argv_child)) {
|
||||
LOG(LOG_ERROR, "logwrapper",
|
||||
"executing %s failed: %s\n", argv_child[0], strerror(errno));
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
int logwrap(int argc, char* argv[])
|
||||
{
|
||||
pid_t pid;
|
||||
|
||||
int parent_ptty;
|
||||
int child_ptty;
|
||||
char *child_devname = NULL;
|
||||
|
||||
/* Use ptty instead of socketpair so that STDOUT is not buffered */
|
||||
parent_ptty = open("/dev/ptmx", O_RDWR);
|
||||
if (parent_ptty < 0) {
|
||||
LOG(LOG_ERROR, "logwrapper", "Cannot create parent ptty\n");
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (grantpt(parent_ptty) || unlockpt(parent_ptty) ||
|
||||
((child_devname = (char*)ptsname(parent_ptty)) == 0)) {
|
||||
LOG(LOG_ERROR, "logwrapper", "Problem with /dev/ptmx\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
LOG(LOG_ERROR, "logwrapper", "Failed to fork\n");
|
||||
return -errno;
|
||||
} else if (pid == 0) {
|
||||
child_ptty = open(child_devname, O_RDWR);
|
||||
if (child_ptty < 0) {
|
||||
LOG(LOG_ERROR, "logwrapper", "Problem with child ptty\n");
|
||||
return -errno;
|
||||
}
|
||||
|
||||
// redirect stdout and stderr
|
||||
close(parent_ptty);
|
||||
dup2(child_ptty, 1);
|
||||
dup2(child_ptty, 2);
|
||||
close(child_ptty);
|
||||
|
||||
child(argc, argv);
|
||||
} else {
|
||||
// switch user and group to "log"
|
||||
// this may fail if we are not root,
|
||||
// but in that case switching user/group is unnecessary
|
||||
|
||||
// setgid(AID_LOG);
|
||||
// setuid(AID_LOG);
|
||||
|
||||
return parent(argv[0], parent_ptty);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
174
mountd/mountd.c
174
mountd/mountd.c
|
@ -1,174 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
** mountd main program
|
||||
*/
|
||||
|
||||
#include "mountd.h"
|
||||
|
||||
#include <cutils/config_utils.h>
|
||||
#include <cutils/cpu_info.h>
|
||||
#include <cutils/properties.h>
|
||||
|
||||
#include <sys/mount.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <linux/capability.h>
|
||||
#include <linux/prctl.h>
|
||||
|
||||
#include <private/android_filesystem_config.h>
|
||||
|
||||
#ifdef MOUNTD_LOG
|
||||
FILE* logFile;
|
||||
#endif
|
||||
|
||||
struct asec_cfg {
|
||||
const char *name;
|
||||
const char *backing_file;
|
||||
const char *size;
|
||||
const char *mount_point;
|
||||
const char *crypt;
|
||||
};
|
||||
|
||||
static int ProcessAsecData(cnode *node, struct asec_cfg *stores, int idx)
|
||||
{
|
||||
cnode *child = node->first_child;
|
||||
const char *name = NULL;
|
||||
const char *file = NULL;
|
||||
const char *size = NULL;
|
||||
const char *mp = NULL;
|
||||
const char *crypt = NULL;
|
||||
|
||||
LOG_ASEC("ProcessAsecData(%s, %p, %d)\n", node->name, stores, idx);
|
||||
|
||||
while (child) {
|
||||
if (!strcmp(child->name, "name"))
|
||||
name = child->value;
|
||||
else if (!strcmp(child->name, "backing_file"))
|
||||
file = child->value;
|
||||
else if (!strcmp(child->name, "size"))
|
||||
size = child->value;
|
||||
else if (!strcmp(child->name, "mount_point"))
|
||||
mp = child->value;
|
||||
else if (!strcmp(child->name, "crypt"))
|
||||
crypt = child->value;
|
||||
child = child->next;
|
||||
}
|
||||
|
||||
if (!name || !file || !size || !mp || !crypt) {
|
||||
LOG_ERROR("Missing required token from config. Skipping ASEC volume\n");
|
||||
return -1;
|
||||
} else if (idx == ASEC_STORES_MAX) {
|
||||
LOG_ERROR("Maximum # of ASEC stores already defined\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
stores[idx].name = name;
|
||||
stores[idx].backing_file = file;
|
||||
stores[idx].size = size;
|
||||
stores[idx].mount_point = mp;
|
||||
stores[idx].crypt = crypt;
|
||||
return ++idx;
|
||||
}
|
||||
|
||||
static void ReadConfigFile(const char* path)
|
||||
{
|
||||
cnode* root = config_node("", "");
|
||||
cnode* node;
|
||||
|
||||
config_load_file(root, path);
|
||||
node = root->first_child;
|
||||
|
||||
while (node)
|
||||
{
|
||||
if (strcmp(node->name, "mount") == 0)
|
||||
{
|
||||
const char* block_device = NULL;
|
||||
const char* mount_point = NULL;
|
||||
const char* driver_store_path = NULL;
|
||||
boolean enable_ums = false;
|
||||
cnode* child = node->first_child;
|
||||
struct asec_cfg asec_stores[ASEC_STORES_MAX];
|
||||
int asec_idx = 0;
|
||||
|
||||
memset(asec_stores, 0, sizeof(asec_stores));
|
||||
|
||||
while (child)
|
||||
{
|
||||
const char* name = child->name;
|
||||
const char* value = child->value;
|
||||
|
||||
if (!strncmp(name, "asec_", 5)) {
|
||||
int rc = ProcessAsecData(child, asec_stores, asec_idx);
|
||||
if (rc < 0) {
|
||||
LOG_ERROR("Error processing ASEC cfg data\n");
|
||||
} else
|
||||
asec_idx = rc;
|
||||
} else if (strcmp(name, "block_device") == 0)
|
||||
block_device = value;
|
||||
else if (strcmp(name, "mount_point") == 0)
|
||||
mount_point = value;
|
||||
else if (strcmp(name, "driver_store_path") == 0)
|
||||
driver_store_path = value;
|
||||
else if (strcmp(name, "enable_ums") == 0 &&
|
||||
strcmp(value, "true") == 0)
|
||||
enable_ums = true;
|
||||
|
||||
child = child->next;
|
||||
}
|
||||
|
||||
// mount point and removable fields are optional
|
||||
if (block_device && mount_point)
|
||||
{
|
||||
void *mp = AddMountPoint(block_device, mount_point, driver_store_path, enable_ums);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < asec_idx; i++) {
|
||||
AddAsecToMountPoint(mp, asec_stores[i].name, asec_stores[i].backing_file,
|
||||
asec_stores[i].size, asec_stores[i].mount_point,
|
||||
asec_stores[i].crypt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
node = node->next;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
const char* configPath = "/system/etc/mountd.conf";
|
||||
int i;
|
||||
|
||||
for (i = 1; i < argc; i++)
|
||||
{
|
||||
const char* arg = argv[i];
|
||||
|
||||
if (strcmp(arg, "-f") == 0)
|
||||
{
|
||||
if (i < argc - 1)
|
||||
configPath = argv[++i];
|
||||
}
|
||||
}
|
||||
|
||||
ReadConfigFile(configPath);
|
||||
StartAutoMounter();
|
||||
return RunServer();
|
||||
}
|
190
mountd/mountd.h
190
mountd/mountd.h
|
@ -1,190 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef MOUNTD_H__
|
||||
#define MOUNTD_H__
|
||||
|
||||
#define LOG_TAG "mountd"
|
||||
#include "cutils/log.h"
|
||||
|
||||
#include "ASEC.h"
|
||||
|
||||
typedef int boolean;
|
||||
enum {
|
||||
false = 0,
|
||||
true = 1
|
||||
};
|
||||
|
||||
#define WEXITSTATUS(status) (((status) & 0xff00) >> 8)
|
||||
|
||||
// Set this for logging error messages
|
||||
#define ENABLE_LOG_ERROR
|
||||
|
||||
// set this to log automounter events
|
||||
#define ENABLE_LOG_MOUNT
|
||||
|
||||
// set this to log server events
|
||||
//#define ENABLE_LOG_SERVER
|
||||
|
||||
// set this to log ASEC events
|
||||
#define ENABLE_LOG_ASEC
|
||||
|
||||
#ifdef ENABLE_LOG_ERROR
|
||||
#define LOG_ERROR(fmt, args...) \
|
||||
{ LOGE(fmt , ## args); }
|
||||
#else
|
||||
#define LOG_ERROR(fmt, args...) \
|
||||
do { } while (0)
|
||||
#endif /* ENABLE_LOG_ERROR */
|
||||
|
||||
#ifdef ENABLE_LOG_MOUNT
|
||||
#define LOG_MOUNT(fmt, args...) \
|
||||
{ LOGD(fmt , ## args); }
|
||||
#else
|
||||
#define LOG_MOUNT(fmt, args...) \
|
||||
do { } while (0)
|
||||
#endif /* ENABLE_LOG_MOUNT */
|
||||
|
||||
#ifdef ENABLE_LOG_SERVER
|
||||
#define LOG_SERVER(fmt, args...) \
|
||||
{ LOGD(fmt , ## args); }
|
||||
#else
|
||||
#define LOG_SERVER(fmt, args...) \
|
||||
do { } while (0)
|
||||
#endif /* ENABLE_LOG_SERVER */
|
||||
|
||||
#ifdef ENABLE_LOG_ASEC
|
||||
#define LOG_ASEC(fmt, args...) \
|
||||
{ LOGD(fmt , ## args); }
|
||||
#else
|
||||
#define LOG_ASEC(fmt, args...) \
|
||||
do { } while (0)
|
||||
#endif /* ENABLE_LOG_ASEC */
|
||||
|
||||
|
||||
typedef enum MediaState {
|
||||
// no media in SD card slot
|
||||
MEDIA_REMOVED,
|
||||
|
||||
// media in SD card slot, but not mounted
|
||||
MEDIA_UNMOUNTED,
|
||||
|
||||
// media in SD card slot and mounted at its mount point
|
||||
MEDIA_MOUNTED,
|
||||
|
||||
// media in SD card slot, unmounted, and shared as a mass storage device
|
||||
MEDIA_SHARED,
|
||||
|
||||
// media was removed from SD card slot, but mount point was not unmounted
|
||||
// this state is cleared after the mount point is unmounted
|
||||
MEDIA_BAD_REMOVAL,
|
||||
|
||||
// media in SD card slot could not be mounted (corrupt file system?)
|
||||
MEDIA_UNMOUNTABLE,
|
||||
} MediaState;
|
||||
|
||||
// socket name for connecting to mountd
|
||||
#define MOUNTD_SOCKET "mountd"
|
||||
|
||||
// mountd commands
|
||||
// these must match the corresponding strings in //device/java/android/android/os/UsbListener.java
|
||||
#define MOUNTD_ENABLE_UMS "enable_ums"
|
||||
#define MOUNTD_DISABLE_UMS "disable_ums"
|
||||
#define MOUNTD_SEND_STATUS "send_status"
|
||||
|
||||
// these commands should contain a mount point following the colon
|
||||
#define MOUNTD_MOUNT_MEDIA "mount_media:"
|
||||
#define MOUNTD_EJECT_MEDIA "eject_media:"
|
||||
|
||||
// mountd events
|
||||
// these must match the corresponding strings in //device/java/android/android/os/UsbListener.java
|
||||
#define MOUNTD_UMS_ENABLED "ums_enabled"
|
||||
#define MOUNTD_UMS_DISABLED "ums_disabled"
|
||||
#define MOUNTD_UMS_CONNECTED "ums_connected"
|
||||
#define MOUNTD_UMS_DISCONNECTED "ums_disconnected"
|
||||
|
||||
// these events correspond to the states in the MediaState enum.
|
||||
// a path to the mount point follows the colon.
|
||||
#define MOUNTD_MEDIA_REMOVED "media_removed:"
|
||||
#define MOUNTD_MEDIA_UNMOUNTED "media_unmounted:"
|
||||
#define MOUNTD_MEDIA_MOUNTED "media_mounted:"
|
||||
#define MOUNTD_MEDIA_MOUNTED_READ_ONLY "media_mounted_ro:"
|
||||
#define MOUNTD_MEDIA_SHARED "media_shared:"
|
||||
#define MOUNTD_MEDIA_BAD_REMOVAL "media_bad_removal:"
|
||||
#define MOUNTD_MEDIA_UNMOUNTABLE "media_unmountable:"
|
||||
|
||||
// this event sent to request unmount for media mount point
|
||||
#define MOUNTD_REQUEST_EJECT "request_eject:"
|
||||
|
||||
// system properties
|
||||
// these must match the corresponding strings in //device/java/android/android/os/Environment.java
|
||||
#define EXTERNAL_STORAGE_STATE "EXTERNAL_STORAGE_STATE"
|
||||
#define EXTERNAL_STORAGE_REMOVED "removed"
|
||||
#define EXTERNAL_STORAGE_UNMOUNTED "unmounted"
|
||||
#define EXTERNAL_STORAGE_MOUNTED "mounted"
|
||||
#define EXTERNAL_STORAGE_MOUNTED_READ_ONLY "mounted_ro"
|
||||
#define EXTERNAL_STORAGE_SHARED "shared"
|
||||
#define EXTERNAL_STORAGE_BAD_REMOVAL "bad_removal"
|
||||
#define EXTERNAL_STORAGE_UNMOUNTABLE "unmountable"
|
||||
|
||||
// AutoMount.c
|
||||
|
||||
boolean IsMassStorageEnabled();
|
||||
boolean IsMassStorageConnected();
|
||||
|
||||
void MountMedia(const char* mountPoint);
|
||||
void UnmountMedia(const char* mountPoint);
|
||||
void EnableMassStorage(boolean enable);
|
||||
|
||||
// call this before StartAutoMounter() to add a mount point to monitor
|
||||
void *AddMountPoint(const char* device, const char* mountPoint, const char* driverStorePath,
|
||||
boolean enableUms);
|
||||
|
||||
int AddAsecToMountPoint(void *Mp, const char *name, const char *backing_file,
|
||||
const char *size, const char *mount_point, const char *crypt);
|
||||
|
||||
// start automounter thread
|
||||
void StartAutoMounter();
|
||||
|
||||
// check /proc/mounts for mounted file systems, and notify mount or unmount for any that are in our automount list
|
||||
void NotifyExistingMounts();
|
||||
|
||||
|
||||
// ASEC.c
|
||||
|
||||
void *AsecInit(const char *Name, const char *SrcPath, const char *BackingFile,
|
||||
const char *Size, const char *DstPath, const char *Crypt);
|
||||
int AsecStart(void *Handle);
|
||||
int AsecStop(void *Handle);
|
||||
void AsecDeinit(void *Handle);
|
||||
boolean AsecIsStarted(void *Handle);
|
||||
const char *AsecMountPoint(void *Handle);
|
||||
|
||||
// ProcessKiller.c
|
||||
|
||||
void KillProcessesWithOpenFiles(const char* mountPoint, boolean sigkill, pid_t *excluded, int num_excluded);
|
||||
|
||||
// logwrapper.c
|
||||
int logwrap(int argc, char* argv[]);
|
||||
|
||||
// Server.c
|
||||
|
||||
int RunServer();
|
||||
void SendMassStorageConnected(boolean connected);
|
||||
void SendUnmountRequest(const char* path);
|
||||
void NotifyMediaState(const char* path, MediaState state, boolean readOnly);
|
||||
void NotifyAsecState(AsecState state, const char *argument);
|
||||
#endif // MOUNTD_H__
|
|
@ -0,0 +1,64 @@
|
|||
BUILD_NEXUS := false
|
||||
ifeq ($(BUILD_NEXUS),true)
|
||||
|
||||
LOCAL_PATH:= $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_SRC_FILES:= \
|
||||
main.cpp \
|
||||
NetworkManager.cpp \
|
||||
CommandListener.cpp \
|
||||
Controller.cpp \
|
||||
WifiController.cpp \
|
||||
LoopController.cpp \
|
||||
NexusCommand.cpp \
|
||||
TiwlanWifiController.cpp \
|
||||
Supplicant.cpp \
|
||||
SupplicantEvent.cpp \
|
||||
SupplicantListener.cpp \
|
||||
VpnController.cpp \
|
||||
ScanResult.cpp \
|
||||
WifiScanner.cpp \
|
||||
WifiNetwork.cpp \
|
||||
OpenVpnController.cpp \
|
||||
InterfaceConfig.cpp \
|
||||
PropertyManager.cpp \
|
||||
SupplicantState.cpp \
|
||||
SupplicantEventFactory.cpp \
|
||||
SupplicantConnectedEvent.cpp \
|
||||
SupplicantAssociatingEvent.cpp \
|
||||
SupplicantAssociatedEvent.cpp \
|
||||
SupplicantStateChangeEvent.cpp \
|
||||
SupplicantScanResultsEvent.cpp \
|
||||
SupplicantConnectionTimeoutEvent.cpp \
|
||||
SupplicantDisconnectedEvent.cpp \
|
||||
SupplicantStatus.cpp \
|
||||
TiwlanEventListener.cpp \
|
||||
DhcpClient.cpp DhcpListener.cpp \
|
||||
|
||||
LOCAL_MODULE:= nexus
|
||||
|
||||
LOCAL_C_INCLUDES := $(KERNEL_HEADERS) -I../../../frameworks/base/include/
|
||||
|
||||
LOCAL_CFLAGS :=
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := libsysutils libwpa_client
|
||||
|
||||
include $(BUILD_EXECUTABLE)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_SRC_FILES:= \
|
||||
nexctl.c \
|
||||
|
||||
LOCAL_MODULE:= nexctl
|
||||
|
||||
LOCAL_C_INCLUDES := $(KERNEL_HEADERS)
|
||||
|
||||
LOCAL_CFLAGS :=
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := libcutils
|
||||
|
||||
include $(BUILD_EXECUTABLE)
|
||||
|
||||
endif # ifeq ($(BUILD_NEXUS),true)
|
|
@ -0,0 +1,231 @@
|
|||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define LOG_TAG "CommandListener"
|
||||
#include <cutils/log.h>
|
||||
|
||||
#include <sysutils/SocketClient.h>
|
||||
|
||||
#include "CommandListener.h"
|
||||
#include "Controller.h"
|
||||
#include "Property.h"
|
||||
#include "NetworkManager.h"
|
||||
#include "WifiController.h"
|
||||
#include "VpnController.h"
|
||||
#include "ErrorCode.h"
|
||||
|
||||
CommandListener::CommandListener() :
|
||||
FrameworkListener("nexus") {
|
||||
registerCmd(new WifiScanResultsCmd());
|
||||
registerCmd(new WifiListNetworksCmd());
|
||||
registerCmd(new WifiCreateNetworkCmd());
|
||||
registerCmd(new WifiRemoveNetworkCmd());
|
||||
|
||||
registerCmd(new GetCmd());
|
||||
registerCmd(new SetCmd());
|
||||
registerCmd(new ListCmd());
|
||||
}
|
||||
|
||||
/* -------------
|
||||
* Wifi Commands
|
||||
* ------------ */
|
||||
|
||||
CommandListener::WifiCreateNetworkCmd::WifiCreateNetworkCmd() :
|
||||
NexusCommand("wifi_create_network") {
|
||||
}
|
||||
|
||||
int CommandListener::WifiCreateNetworkCmd::runCommand(SocketClient *cli,
|
||||
int argc, char **argv) {
|
||||
NetworkManager *nm = NetworkManager::Instance();
|
||||
WifiController *wc = (WifiController *) nm->findController("WIFI");
|
||||
WifiNetwork *wn;
|
||||
|
||||
if (!(wn = wc->createNetwork()))
|
||||
cli->sendMsg(ErrorCode::OperationFailed, "Failed to create network", true);
|
||||
else {
|
||||
char tmp[128];
|
||||
sprintf(tmp, "Created network id %d.", wn->getNetworkId());
|
||||
cli->sendMsg(ErrorCode::CommandOkay, tmp, false);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
CommandListener::WifiRemoveNetworkCmd::WifiRemoveNetworkCmd() :
|
||||
NexusCommand("wifi_remove_network") {
|
||||
}
|
||||
|
||||
int CommandListener::WifiRemoveNetworkCmd::runCommand(SocketClient *cli,
|
||||
int argc, char **argv) {
|
||||
NetworkManager *nm = NetworkManager::Instance();
|
||||
WifiController *wc = (WifiController *) nm->findController("WIFI");
|
||||
|
||||
if (wc->removeNetwork(atoi(argv[1])))
|
||||
cli->sendMsg(ErrorCode::OperationFailed, "Failed to remove network", true);
|
||||
else {
|
||||
cli->sendMsg(ErrorCode::CommandOkay, "Network removed.", false);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
CommandListener::WifiScanResultsCmd::WifiScanResultsCmd() :
|
||||
NexusCommand("wifi_scan_results") {
|
||||
}
|
||||
|
||||
int CommandListener::WifiScanResultsCmd::runCommand(SocketClient *cli,
|
||||
int argc, char **argv) {
|
||||
NetworkManager *nm = NetworkManager::Instance();
|
||||
WifiController *wc = (WifiController *) nm->findController("WIFI");
|
||||
|
||||
ScanResultCollection *src = wc->createScanResults();
|
||||
ScanResultCollection::iterator it;
|
||||
char buffer[256];
|
||||
|
||||
for(it = src->begin(); it != src->end(); ++it) {
|
||||
sprintf(buffer, "%s:%u:%d:%s:%s",
|
||||
(*it)->getBssid(), (*it)->getFreq(), (*it)->getLevel(),
|
||||
(*it)->getFlags(), (*it)->getSsid());
|
||||
cli->sendMsg(ErrorCode::WifiScanResult, buffer, false);
|
||||
delete (*it);
|
||||
it = src->erase(it);
|
||||
}
|
||||
|
||||
delete src;
|
||||
cli->sendMsg(ErrorCode::CommandOkay, "Scan results complete.", false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
CommandListener::WifiListNetworksCmd::WifiListNetworksCmd() :
|
||||
NexusCommand("wifi_list_networks") {
|
||||
}
|
||||
|
||||
int CommandListener::WifiListNetworksCmd::runCommand(SocketClient *cli,
|
||||
int argc, char **argv) {
|
||||
NetworkManager *nm = NetworkManager::Instance();
|
||||
WifiController *wc = (WifiController *) nm->findController("WIFI");
|
||||
|
||||
WifiNetworkCollection *src = wc->createNetworkList();
|
||||
WifiNetworkCollection::iterator it;
|
||||
char buffer[256];
|
||||
|
||||
for(it = src->begin(); it != src->end(); ++it) {
|
||||
sprintf(buffer, "%d:%s", (*it)->getNetworkId(), (*it)->getSsid());
|
||||
cli->sendMsg(ErrorCode::WifiNetworkList, buffer, false);
|
||||
delete (*it);
|
||||
}
|
||||
|
||||
delete src;
|
||||
cli->sendMsg(ErrorCode::CommandOkay, "Network listing complete.", false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ------------
|
||||
* Vpn Commands
|
||||
* ------------ */
|
||||
|
||||
/* ----------------
|
||||
* Generic Commands
|
||||
* ---------------- */
|
||||
CommandListener::GetCmd::GetCmd() :
|
||||
NexusCommand("get") {
|
||||
}
|
||||
|
||||
int CommandListener::GetCmd::runCommand(SocketClient *cli, int argc, char **argv) {
|
||||
char val[Property::ValueMaxSize];
|
||||
|
||||
if (!NetworkManager::Instance()->getPropMngr()->get(argv[1],
|
||||
val,
|
||||
sizeof(val))) {
|
||||
goto out_inval;
|
||||
}
|
||||
|
||||
char *tmp;
|
||||
asprintf(&tmp, "%s %s", argv[1], val);
|
||||
cli->sendMsg(ErrorCode::PropertyRead, tmp, false);
|
||||
free(tmp);
|
||||
|
||||
cli->sendMsg(ErrorCode::CommandOkay, "Property read.", false);
|
||||
return 0;
|
||||
out_inval:
|
||||
errno = EINVAL;
|
||||
cli->sendMsg(ErrorCode::CommandParameterError, "Failed to read property.", true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
CommandListener::SetCmd::SetCmd() :
|
||||
NexusCommand("set") {
|
||||
}
|
||||
|
||||
int CommandListener::SetCmd::runCommand(SocketClient *cli, int argc,
|
||||
char **argv) {
|
||||
if (NetworkManager::Instance()->getPropMngr()->set(argv[1], argv[2]))
|
||||
goto out_inval;
|
||||
|
||||
cli->sendMsg(ErrorCode::CommandOkay, "Property set.", false);
|
||||
return 0;
|
||||
|
||||
out_inval:
|
||||
errno = EINVAL;
|
||||
cli->sendMsg(ErrorCode::CommandParameterError, "Failed to set property.", true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
CommandListener::ListCmd::ListCmd() :
|
||||
NexusCommand("list") {
|
||||
}
|
||||
|
||||
int CommandListener::ListCmd::runCommand(SocketClient *cli, int argc, char **argv) {
|
||||
android::List<char *> *pc;
|
||||
|
||||
if (!(pc = NetworkManager::Instance()->getPropMngr()->createPropertyList())) {
|
||||
errno = ENODATA;
|
||||
cli->sendMsg(ErrorCode::CommandParameterError, "Failed to list properties.", true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
android::List<char *>::iterator it;
|
||||
|
||||
for (it = pc->begin(); it != pc->end(); ++it) {
|
||||
char p_v[Property::ValueMaxSize];
|
||||
|
||||
if (!NetworkManager::Instance()->getPropMngr()->get((*it),
|
||||
p_v,
|
||||
sizeof(p_v))) {
|
||||
LOGW("Failed to get %s (%s)", (*it), strerror(errno));
|
||||
}
|
||||
|
||||
char *buf;
|
||||
if (asprintf(&buf, "%s %s", (*it), p_v) < 0) {
|
||||
LOGE("Failed to allocate memory");
|
||||
free((*it));
|
||||
continue;
|
||||
}
|
||||
cli->sendMsg(ErrorCode::PropertyList, buf, false);
|
||||
free(buf);
|
||||
|
||||
free((*it));
|
||||
}
|
||||
|
||||
delete pc;
|
||||
|
||||
cli->sendMsg(ErrorCode::CommandOkay, "Properties list complete.", false);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _COMMANDLISTENER_H__
|
||||
#define _COMMANDLISTENER_H__
|
||||
|
||||
#include <sysutils/FrameworkListener.h>
|
||||
#include "NexusCommand.h"
|
||||
|
||||
class CommandListener : public FrameworkListener {
|
||||
public:
|
||||
CommandListener();
|
||||
virtual ~CommandListener() {}
|
||||
|
||||
private:
|
||||
|
||||
class WifiScanCmd : public NexusCommand {
|
||||
public:
|
||||
WifiScanCmd();
|
||||
virtual ~WifiScanCmd() {}
|
||||
int runCommand(SocketClient *c, int argc, char ** argv);
|
||||
};
|
||||
|
||||
class WifiScanResultsCmd : public NexusCommand {
|
||||
public:
|
||||
WifiScanResultsCmd();
|
||||
virtual ~WifiScanResultsCmd() {}
|
||||
int runCommand(SocketClient *c, int argc, char ** argv);
|
||||
};
|
||||
|
||||
class WifiCreateNetworkCmd : public NexusCommand {
|
||||
public:
|
||||
WifiCreateNetworkCmd();
|
||||
virtual ~WifiCreateNetworkCmd() {}
|
||||
int runCommand(SocketClient *c, int argc, char ** argv);
|
||||
};
|
||||
|
||||
class WifiRemoveNetworkCmd : public NexusCommand {
|
||||
public:
|
||||
WifiRemoveNetworkCmd();
|
||||
virtual ~WifiRemoveNetworkCmd() {}
|
||||
int runCommand(SocketClient *c, int argc, char ** argv);
|
||||
};
|
||||
|
||||
class WifiListNetworksCmd : public NexusCommand {
|
||||
public:
|
||||
WifiListNetworksCmd();
|
||||
virtual ~WifiListNetworksCmd() {}
|
||||
int runCommand(SocketClient *c, int argc, char ** argv);
|
||||
};
|
||||
|
||||
class SetCmd : public NexusCommand {
|
||||
public:
|
||||
SetCmd();
|
||||
virtual ~SetCmd() {}
|
||||
int runCommand(SocketClient *c, int argc, char ** argv);
|
||||
};
|
||||
|
||||
class GetCmd : public NexusCommand {
|
||||
public:
|
||||
GetCmd();
|
||||
virtual ~GetCmd() {}
|
||||
int runCommand(SocketClient *c, int argc, char ** argv);
|
||||
};
|
||||
|
||||
class ListCmd : public NexusCommand {
|
||||
public:
|
||||
ListCmd();
|
||||
virtual ~ListCmd() {}
|
||||
int runCommand(SocketClient *c, int argc, char ** argv);
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,176 @@
|
|||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <malloc.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define LOG_TAG "Controller"
|
||||
|
||||
#include <cutils/log.h>
|
||||
|
||||
#include "Controller.h"
|
||||
|
||||
extern "C" int init_module(void *, unsigned int, const char *);
|
||||
extern "C" int delete_module(const char *, unsigned int);
|
||||
|
||||
Controller::Controller(const char *name, PropertyManager *propMngr,
|
||||
IControllerHandler *handlers) {
|
||||
mPropMngr = propMngr;
|
||||
mName = strdup(name);
|
||||
mHandlers = handlers;
|
||||
mBoundInterface = NULL;
|
||||
}
|
||||
|
||||
Controller::~Controller() {
|
||||
if (mBoundInterface)
|
||||
free(mBoundInterface);
|
||||
if (mName)
|
||||
free(mName);
|
||||
}
|
||||
|
||||
int Controller::start() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Controller::stop() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Controller::set(const char *name, const char *value) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
const char *Controller::get(const char *name, char *buffer, size_t maxsize) {
|
||||
errno = ENOENT;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int Controller::loadKernelModule(char *modpath, const char *args) {
|
||||
void *module;
|
||||
unsigned int size;
|
||||
|
||||
module = loadFile(modpath, &size);
|
||||
if (!module) {
|
||||
errno = -EIO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int rc = init_module(module, size, args);
|
||||
free (module);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int Controller::unloadKernelModule(const char *modtag) {
|
||||
int rc = -1;
|
||||
int retries = 10;
|
||||
|
||||
while (retries--) {
|
||||
rc = delete_module(modtag, O_NONBLOCK | O_EXCL);
|
||||
if (rc < 0 && errno == EAGAIN)
|
||||
usleep(1000*500);
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (rc != 0) {
|
||||
LOGW("Unable to unload kernel driver '%s' (%s)", modtag,
|
||||
strerror(errno));
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
bool Controller::isKernelModuleLoaded(const char *modtag) {
|
||||
FILE *fp = fopen("/proc/modules", "r");
|
||||
|
||||
if (!fp) {
|
||||
LOGE("Unable to open /proc/modules (%s)", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
char line[255];
|
||||
while(fgets(line, sizeof(line), fp)) {
|
||||
char *endTag = strchr(line, ' ');
|
||||
|
||||
if (!endTag) {
|
||||
LOGW("Unable to find tag for line '%s'", line);
|
||||
continue;
|
||||
}
|
||||
if (!strncmp(line, modtag, (endTag - line))) {
|
||||
fclose(fp);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
return false;
|
||||
}
|
||||
|
||||
void *Controller::loadFile(char *filename, unsigned int *_size)
|
||||
{
|
||||
int ret, fd;
|
||||
struct stat sb;
|
||||
ssize_t size;
|
||||
void *buffer = NULL;
|
||||
|
||||
/* open the file */
|
||||
fd = open(filename, O_RDONLY);
|
||||
if (fd < 0)
|
||||
return NULL;
|
||||
|
||||
/* find out how big it is */
|
||||
if (fstat(fd, &sb) < 0)
|
||||
goto bail;
|
||||
size = sb.st_size;
|
||||
|
||||
/* allocate memory for it to be read into */
|
||||
buffer = malloc(size);
|
||||
if (!buffer)
|
||||
goto bail;
|
||||
|
||||
/* slurp it into our buffer */
|
||||
ret = read(fd, buffer, size);
|
||||
if (ret != size)
|
||||
goto bail;
|
||||
|
||||
/* let the caller know how big it is */
|
||||
*_size = size;
|
||||
|
||||
bail:
|
||||
close(fd);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
int Controller::bindInterface(const char *ifname) {
|
||||
mBoundInterface = strdup(ifname);
|
||||
LOGD("Controller %s bound to %s", mName, ifname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Controller::unbindInterface(const char *ifname) {
|
||||
free(mBoundInterface);
|
||||
mBoundInterface = NULL;
|
||||
LOGD("Controller %s unbound from %s", mName, ifname);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _CONTROLLER_H
|
||||
#define _CONTROLLER_H
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <utils/List.h>
|
||||
|
||||
class PropertyManager;
|
||||
class IControllerHandler;
|
||||
|
||||
#include "PropertyManager.h"
|
||||
#include "IPropertyProvider.h"
|
||||
|
||||
class Controller : public IPropertyProvider {
|
||||
/*
|
||||
* Name of this controller - WIFI/VPN/USBNET/BTNET/BTDUN/LOOP/etc
|
||||
*/
|
||||
char *mName;
|
||||
|
||||
/*
|
||||
* Name of the system ethernet interface which this controller is
|
||||
* bound to.
|
||||
*/
|
||||
char *mBoundInterface;
|
||||
|
||||
protected:
|
||||
PropertyManager *mPropMngr;
|
||||
IControllerHandler *mHandlers;
|
||||
|
||||
public:
|
||||
Controller(const char *name, PropertyManager *propMngr,
|
||||
IControllerHandler *handlers);
|
||||
virtual ~Controller();
|
||||
|
||||
virtual int start();
|
||||
virtual int stop();
|
||||
|
||||
const char *getName() { return mName; }
|
||||
const char *getBoundInterface() { return mBoundInterface; }
|
||||
|
||||
/* IPropertyProvider methods */
|
||||
virtual int set(const char *name, const char *value);
|
||||
virtual const char *get(const char *name, char *buffer, size_t maxsize);
|
||||
|
||||
protected:
|
||||
int loadKernelModule(char *modpath, const char *args);
|
||||
bool isKernelModuleLoaded(const char *modtag);
|
||||
int unloadKernelModule(const char *modtag);
|
||||
int bindInterface(const char *ifname);
|
||||
int unbindInterface(const char *ifname);
|
||||
|
||||
private:
|
||||
void *loadFile(char *filename, unsigned int *_size);
|
||||
};
|
||||
|
||||
typedef android::List<Controller *> ControllerCollection;
|
||||
#endif
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#define LOG_TAG "DhcpClient"
|
||||
#include <cutils/log.h>
|
||||
#include <cutils/properties.h>
|
||||
|
||||
#include <sysutils/ServiceManager.h>
|
||||
|
||||
#include "DhcpClient.h"
|
||||
#include "DhcpState.h"
|
||||
#include "DhcpListener.h"
|
||||
#include "IDhcpEventHandlers.h"
|
||||
|
||||
extern "C" {
|
||||
int ifc_disable(const char *ifname);
|
||||
int ifc_add_host_route(const char *ifname, uint32_t addr);
|
||||
int ifc_remove_host_routes(const char *ifname);
|
||||
int ifc_set_default_route(const char *ifname, uint32_t gateway);
|
||||
int ifc_get_default_route(const char *ifname);
|
||||
int ifc_remove_default_route(const char *ifname);
|
||||
int ifc_reset_connections(const char *ifname);
|
||||
int ifc_configure(const char *ifname, in_addr_t ipaddr, in_addr_t netmask, in_addr_t gateway, in_addr_t dns1, in_addr_t dns2);
|
||||
|
||||
int dhcp_do_request(const char *ifname,
|
||||
in_addr_t *ipaddr,
|
||||
in_addr_t *gateway,
|
||||
in_addr_t *mask,
|
||||
in_addr_t *dns1,
|
||||
in_addr_t *dns2,
|
||||
in_addr_t *server,
|
||||
uint32_t *lease);
|
||||
int dhcp_stop(const char *ifname);
|
||||
int dhcp_release_lease(const char *ifname);
|
||||
char *dhcp_get_errmsg();
|
||||
}
|
||||
|
||||
DhcpClient::DhcpClient(IDhcpEventHandlers *handlers) :
|
||||
mState(DhcpState::STOPPED), mHandlers(handlers) {
|
||||
mServiceManager = new ServiceManager();
|
||||
mListener = NULL;
|
||||
}
|
||||
|
||||
DhcpClient::~DhcpClient() {
|
||||
delete mServiceManager;
|
||||
if (mListener)
|
||||
delete mListener;
|
||||
}
|
||||
|
||||
int DhcpClient::start(const char *interface) {
|
||||
|
||||
char svc[PROPERTY_VALUE_MAX];
|
||||
snprintf(svc, sizeof(svc), "dhcpcd_ng:%s", interface);
|
||||
|
||||
if (mServiceManager->start(svc)) {
|
||||
LOGE("Failed to start dhcp service");
|
||||
return -1;
|
||||
}
|
||||
|
||||
mListener = new DhcpListener(mHandlers);
|
||||
if (mListener->startListener()) {
|
||||
LOGE("Failed to start listener");
|
||||
#if 0
|
||||
mServiceManager->stop("dhcpcd_ng");
|
||||
return -1;
|
||||
#endif
|
||||
delete mListener;
|
||||
mListener = NULL;
|
||||
}
|
||||
|
||||
mState = DhcpState::STARTED;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DhcpClient::stop() {
|
||||
if (mListener) {
|
||||
mListener->stopListener();
|
||||
delete mListener;
|
||||
mListener = NULL;
|
||||
}
|
||||
|
||||
if (mServiceManager->stop("dhcpcd_ng"))
|
||||
LOGW("Failed to stop DHCP service (%s)", strerror(errno));
|
||||
mState = DhcpState::STOPPED;
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _DhcpClient_H
|
||||
#define _DhcpClient_H
|
||||
|
||||
class IDhcpEventHandlers;
|
||||
class ServiceManager;
|
||||
class DhcpListener;
|
||||
|
||||
class DhcpClient {
|
||||
int mState;
|
||||
IDhcpEventHandlers *mHandlers;
|
||||
ServiceManager *mServiceManager;
|
||||
DhcpListener *mListener;
|
||||
|
||||
public:
|
||||
DhcpClient(IDhcpEventHandlers *handlers);
|
||||
virtual ~DhcpClient();
|
||||
|
||||
int getState() { return mState; }
|
||||
|
||||
int start(const char *interface);
|
||||
int stop();
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "DhcpListener"
|
||||
#include <cutils/log.h>
|
||||
|
||||
#include <DhcpListener.h>
|
||||
#include "IDhcpEventHandlers.h"
|
||||
|
||||
DhcpListener::DhcpListener(IDhcpEventHandlers *handlers) :
|
||||
SocketListener("dhcp_ng", false) {
|
||||
mHandlers = handlers;
|
||||
}
|
||||
|
||||
DhcpListener::~DhcpListener() {
|
||||
}
|
||||
|
||||
bool DhcpListener::onDataAvailable(SocketClient *cli) {
|
||||
LOGD("onDataAvailable()");
|
||||
return true;
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _DhcpListener_H
|
||||
#define _DhcpListener_H
|
||||
|
||||
#include <sysutils/SocketListener.h>
|
||||
|
||||
class IDhcpEventHandlers;
|
||||
|
||||
class DhcpListener : public SocketListener {
|
||||
IDhcpEventHandlers *mHandlers;
|
||||
|
||||
public:
|
||||
|
||||
DhcpListener(IDhcpEventHandlers *handlers);
|
||||
virtual ~DhcpListener();
|
||||
|
||||
private:
|
||||
bool onDataAvailable(SocketClient *cli);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _DhcpState_H
|
||||
#define _DhcpState_H
|
||||
|
||||
class DhcpState {
|
||||
public:
|
||||
static const int UNKNOWN = 0;
|
||||
static const int STOPPED = 1;
|
||||
static const int STARTED = 2;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _ERRORCODE_H
|
||||
#define _ERRORCODE_H
|
||||
|
||||
class ErrorCode {
|
||||
public:
|
||||
// 100 series - Requestion action was initiated; expect another reply
|
||||
// before proceeding with a new command.
|
||||
static const int ActionInitiated = 100;
|
||||
|
||||
static const int WifiScanResult = 125;
|
||||
static const int WifiNetworkList = 126;
|
||||
|
||||
static const int PropertyRead = 127;
|
||||
static const int PropertySet = 128;
|
||||
static const int PropertyList = 129;
|
||||
|
||||
// 200 series - Requested action has been successfully completed
|
||||
static const int CommandOkay = 200;
|
||||
|
||||
// 400 series - The command was accepted but the requested action
|
||||
// did not take place.
|
||||
static const int OperationFailed = 400;
|
||||
|
||||
// 500 series - The command was not accepted and the requested
|
||||
// action did not take place.
|
||||
static const int CommandSyntaxError = 500;
|
||||
static const int CommandParameterError = 501;
|
||||
|
||||
// 600 series - Unsolicited broadcasts
|
||||
static const int UnsolicitedInformational = 600;
|
||||
};
|
||||
#endif
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _ICONTROLLER_HANDLER_H
|
||||
#define _ICONTROLLER_HANDLER_H
|
||||
|
||||
class Controller;
|
||||
class InterfaceConfig;
|
||||
|
||||
class IControllerHandler {
|
||||
public:
|
||||
virtual void onInterfaceConnected(Controller *c, const InterfaceConfig *cfg) = 0;
|
||||
virtual void onInterfaceDisconnected(Controller *c, const char *name) = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _IDhcpEventHandlers_H
|
||||
#define _IDhcpEventHandlers_H
|
||||
|
||||
class IDhcpEventHandlers {
|
||||
public:
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _IPROPERTY_PROVIDER_H
|
||||
#define _IPROPERTY_PROVIDER_H
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <utils/List.h>
|
||||
|
||||
class IPropertyProvider {
|
||||
public:
|
||||
virtual int set(const char *name, const char *value) = 0;
|
||||
virtual const char *get(const char *name, char *buffer, size_t max) = 0;
|
||||
};
|
||||
|
||||
typedef android::List<IPropertyProvider *> IPropertyProviderCollection;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _ISUPPLICANT_EVENT_HANDLER_H
|
||||
#define _ISUPPLICANT_EVENT_HANDLER_H
|
||||
|
||||
class SupplicantAssociatingEvent;
|
||||
class SupplicantAssociatedEvent;
|
||||
class SupplicantConnectedEvent;
|
||||
class SupplicantScanResultsEvent;
|
||||
class SupplicantStateChangeEvent;
|
||||
class SupplicantConnectionTimeoutEvent;
|
||||
class SupplicantDisconnectedEvent;
|
||||
|
||||
class ISupplicantEventHandler {
|
||||
public:
|
||||
virtual void onAssociatingEvent(SupplicantAssociatingEvent *evt) = 0;
|
||||
virtual void onAssociatedEvent(SupplicantAssociatedEvent *evt) = 0;
|
||||
virtual void onConnectedEvent(SupplicantConnectedEvent *evt) = 0;
|
||||
virtual void onScanResultsEvent(SupplicantScanResultsEvent *evt) = 0;
|
||||
virtual void onStateChangeEvent(SupplicantStateChangeEvent *evt) = 0;
|
||||
virtual void onConnectionTimeoutEvent(SupplicantConnectionTimeoutEvent *evt) = 0;
|
||||
virtual void onDisconnectedEvent(SupplicantDisconnectedEvent *evt) = 0;
|
||||
#if 0
|
||||
virtual void onTerminatingEvent(SupplicantEvent *evt) = 0;
|
||||
virtual void onPasswordChangedEvent(SupplicantEvent *evt) = 0;
|
||||
virtual void onEapNotificationEvent(SupplicantEvent *evt) = 0;
|
||||
virtual void onEapStartedEvent(SupplicantEvent *evt) = 0;
|
||||
virtual void onEapMethodEvent(SupplicantEvent *evt) = 0;
|
||||
virtual void onEapSuccessEvent(SupplicantEvent *evt) = 0;
|
||||
virtual void onEapFailureEvent(SupplicantEvent *evt) = 0;
|
||||
virtual void onLinkSpeedEvent(SupplicantEvent *evt) = 0;
|
||||
virtual void onDriverStateEvent(SupplicantEvent *evt) = 0;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,169 @@
|
|||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define LOG_TAG "InterfaceConfig"
|
||||
#include <cutils/log.h>
|
||||
|
||||
#include "InterfaceConfig.h"
|
||||
#include "NetworkManager.h"
|
||||
|
||||
const char *InterfaceConfig::PropertyNames[] = { "dhcp", "ip",
|
||||
"netmask",
|
||||
"gateway", "dns1", "dns2",
|
||||
"dns3", '\0' };
|
||||
|
||||
InterfaceConfig::InterfaceConfig(const char *prop_prefix) {
|
||||
mPropPrefix = strdup(prop_prefix);
|
||||
mUseDhcp = true;
|
||||
registerProperties();
|
||||
}
|
||||
|
||||
InterfaceConfig::~InterfaceConfig() {
|
||||
unregisterProperties();
|
||||
free(mPropPrefix);
|
||||
}
|
||||
|
||||
InterfaceConfig::InterfaceConfig(const char *prop_prefix,
|
||||
const char *ip, const char *nm,
|
||||
const char *gw, const char *dns1, const char *dns2,
|
||||
const char *dns3) {
|
||||
mPropPrefix = strdup(prop_prefix);
|
||||
mUseDhcp = false;
|
||||
|
||||
if (!inet_aton(ip, &mIp))
|
||||
LOGW("Unable to parse ip (%s)", ip);
|
||||
if (!inet_aton(nm, &mNetmask))
|
||||
LOGW("Unable to parse netmask (%s)", nm);
|
||||
if (!inet_aton(gw, &mGateway))
|
||||
LOGW("Unable to parse gateway (%s)", gw);
|
||||
if (!inet_aton(dns1, &mDns1))
|
||||
LOGW("Unable to parse dns1 (%s)", dns1);
|
||||
if (!inet_aton(dns2, &mDns2))
|
||||
LOGW("Unable to parse dns2 (%s)", dns2);
|
||||
if (!inet_aton(dns3, &mDns3))
|
||||
LOGW("Unable to parse dns3 (%s)", dns3);
|
||||
registerProperties();
|
||||
}
|
||||
|
||||
InterfaceConfig::InterfaceConfig(const char *prop_prefix,
|
||||
const struct in_addr *ip,
|
||||
const struct in_addr *nm, const struct in_addr *gw,
|
||||
const struct in_addr *dns1, const struct in_addr *dns2,
|
||||
const struct in_addr *dns3) {
|
||||
mPropPrefix = strdup(prop_prefix);
|
||||
mUseDhcp = false;
|
||||
|
||||
memcpy(&mIp, ip, sizeof(struct in_addr));
|
||||
memcpy(&mNetmask, nm, sizeof(struct in_addr));
|
||||
memcpy(&mGateway, gw, sizeof(struct in_addr));
|
||||
memcpy(&mDns1, dns1, sizeof(struct in_addr));
|
||||
memcpy(&mDns2, dns2, sizeof(struct in_addr));
|
||||
memcpy(&mDns3, dns3, sizeof(struct in_addr));
|
||||
registerProperties();
|
||||
}
|
||||
|
||||
int InterfaceConfig::registerProperties() {
|
||||
for (const char **p = InterfaceConfig::PropertyNames; *p != '\0'; p++) {
|
||||
char *tmp;
|
||||
asprintf(&tmp, "%s.if.%s", mPropPrefix, *p);
|
||||
|
||||
if (NetworkManager::Instance()->getPropMngr()->registerProperty(tmp,
|
||||
this)) {
|
||||
free(tmp);
|
||||
return -1;
|
||||
}
|
||||
free(tmp);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int InterfaceConfig::unregisterProperties() {
|
||||
for (const char **p = InterfaceConfig::PropertyNames; *p != '\0'; p++) {
|
||||
char *tmp;
|
||||
asprintf(&tmp, "%s.if.%s", mPropPrefix, *p);
|
||||
|
||||
if (NetworkManager::Instance()->getPropMngr()->unregisterProperty(tmp))
|
||||
LOGW("Unable to remove property '%s' (%s)", tmp, strerror(errno));
|
||||
free(tmp);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int InterfaceConfig::set(const char *name, const char *value) {
|
||||
const char *n;
|
||||
|
||||
for (n = &name[strlen(name)]; *n != '.'; n--);
|
||||
n++;
|
||||
|
||||
if (!strcasecmp(n, "name")) {
|
||||
errno = EROFS;
|
||||
return -1;
|
||||
} else if (!strcasecmp(n, "ip") && !inet_aton(value, &mIp))
|
||||
goto out_inval;
|
||||
else if (!strcasecmp(n, "dhcp"))
|
||||
mUseDhcp = (atoi(value) == 0 ? false : true);
|
||||
else if (!strcasecmp(n, "netmask") && !inet_aton(value, &mNetmask))
|
||||
goto out_inval;
|
||||
else if (!strcasecmp(n, "gateway") && !inet_aton(value, &mGateway))
|
||||
goto out_inval;
|
||||
else if (!strcasecmp(n, "dns1") && !inet_aton(value, &mDns1))
|
||||
goto out_inval;
|
||||
else if (!strcasecmp(n, "dns2") && !inet_aton(value, &mDns2))
|
||||
goto out_inval;
|
||||
else if (!strcasecmp(n, "dns3") && !inet_aton(value, &mDns3))
|
||||
goto out_inval;
|
||||
else {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out_inval:
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
const char *InterfaceConfig::get(const char *name, char *buffer, size_t max) {
|
||||
const char *n;
|
||||
|
||||
for (n = &name[strlen(name)]; *n != '.'; n--);
|
||||
n++;
|
||||
|
||||
if (!strcasecmp(n, "ip"))
|
||||
strncpy(buffer, inet_ntoa(mIp), max);
|
||||
else if (!strcasecmp(n, "dhcp"))
|
||||
snprintf(buffer, max, "%d", mUseDhcp);
|
||||
else if (!strcasecmp(n, "netmask"))
|
||||
strncpy(buffer, inet_ntoa(mNetmask), max);
|
||||
else if (!strcasecmp(n, "gateway"))
|
||||
strncpy(buffer, inet_ntoa(mGateway), max);
|
||||
else if (!strcasecmp(n, "dns1"))
|
||||
strncpy(buffer, inet_ntoa(mDns1), max);
|
||||
else if (!strcasecmp(n, "dns2"))
|
||||
strncpy(buffer, inet_ntoa(mDns2), max);
|
||||
else if (!strcasecmp(n, "dns3"))
|
||||
strncpy(buffer, inet_ntoa(mDns3), max);
|
||||
else {
|
||||
strncpy(buffer, "(internal error)", max);
|
||||
errno = ENOENT;
|
||||
return NULL;
|
||||
}
|
||||
return buffer;
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _INTERFACE_CONFIG_H
|
||||
#define _INTERFACE_CONFIG_H
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "IPropertyProvider.h"
|
||||
|
||||
class PropertyManager;
|
||||
|
||||
class InterfaceConfig : public IPropertyProvider {
|
||||
public:
|
||||
static const char *PropertyNames[];
|
||||
|
||||
private:
|
||||
char *mPropPrefix;
|
||||
bool mUseDhcp;
|
||||
struct in_addr mIp;
|
||||
struct in_addr mNetmask;
|
||||
struct in_addr mGateway;
|
||||
struct in_addr mDns1;
|
||||
struct in_addr mDns2;
|
||||
struct in_addr mDns3;
|
||||
|
||||
public:
|
||||
InterfaceConfig(const char *prop_prefix);
|
||||
InterfaceConfig(const char *prop_prefix,
|
||||
const char *ip, const char *nm,
|
||||
const char *gw, const char *dns1, const char *dns2,
|
||||
const char *dns3);
|
||||
|
||||
InterfaceConfig(const char *prop_prefix,
|
||||
const struct in_addr *ip,
|
||||
const struct in_addr *nm, const struct in_addr *gw,
|
||||
const struct in_addr *dns1, const struct in_addr *dns2,
|
||||
const struct in_addr *dns3);
|
||||
|
||||
virtual ~InterfaceConfig();
|
||||
|
||||
int set(const char *name, const char *value);
|
||||
const char *get(const char *name, char *buffer, size_t maxsize);
|
||||
|
||||
bool getUseDhcp() const { return mUseDhcp; }
|
||||
const struct in_addr &getIp() const { return mIp; }
|
||||
const struct in_addr &getNetmask() const { return mNetmask; }
|
||||
const struct in_addr &getGateway() const { return mGateway; }
|
||||
const struct in_addr &getDns1() const { return mDns1; }
|
||||
const struct in_addr &getDns2() const { return mDns2; }
|
||||
const struct in_addr &getDns3() const { return mDns3; }
|
||||
|
||||
private:
|
||||
int registerProperties();
|
||||
int unregisterProperties();
|
||||
};
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include "LoopController.h"
|
||||
#include "PropertyManager.h"
|
||||
|
||||
LoopController::LoopController(PropertyManager *propmngr,
|
||||
IControllerHandler *handlers) :
|
||||
Controller("LOOP", propmngr, handlers) {
|
||||
}
|
||||
|
||||
int LoopController::set(const char *name, const char *value) {
|
||||
return Controller::set(name, value);
|
||||
}
|
||||
|
||||
const char *LoopController::get(const char *name, char *buffer, size_t maxsize) {
|
||||
return Controller::get(name, buffer, maxsize);
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _LOOP_CONTROLLER_H
|
||||
#define _LOOP_CONTROLLER_H
|
||||
|
||||
#include "Controller.h"
|
||||
|
||||
class ControllerHandler;
|
||||
|
||||
class LoopController : public Controller {
|
||||
public:
|
||||
LoopController(PropertyManager *propmngr, IControllerHandler *h);
|
||||
virtual ~LoopController() {}
|
||||
|
||||
int set(const char *name, const char *value);
|
||||
const char *get(const char *name, char *buffer, size_t maxsize);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define LOG_TAG "Nexus"
|
||||
|
||||
#include <cutils/log.h>
|
||||
|
||||
#include "NetworkManager.h"
|
||||
#include "InterfaceConfig.h"
|
||||
#include "DhcpClient.h"
|
||||
|
||||
NetworkManager *NetworkManager::sInstance = NULL;
|
||||
|
||||
NetworkManager *NetworkManager::Instance() {
|
||||
if (!sInstance)
|
||||
sInstance = new NetworkManager(new PropertyManager());
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
NetworkManager::NetworkManager(PropertyManager *propMngr) {
|
||||
mBroadcaster = NULL;
|
||||
mControllers = new ControllerCollection();
|
||||
mPropMngr = propMngr;
|
||||
mDhcp = new DhcpClient(this);
|
||||
}
|
||||
|
||||
NetworkManager::~NetworkManager() {
|
||||
}
|
||||
|
||||
int NetworkManager::run() {
|
||||
if (startControllers()) {
|
||||
LOGW("Unable to start all controllers (%s)", strerror(errno));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int NetworkManager::attachController(Controller *c) {
|
||||
mControllers->push_back(c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int NetworkManager::startControllers() {
|
||||
int rc = 0;
|
||||
ControllerCollection::iterator i;
|
||||
|
||||
for (i = mControllers->begin(); i != mControllers->end(); ++i) {
|
||||
int irc = (*i)->start();
|
||||
LOGD("Controller '%s' start rc = %d", (*i)->getName(), irc);
|
||||
if (irc && !rc)
|
||||
rc = irc;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
int NetworkManager::stopControllers() {
|
||||
int rc = 0;
|
||||
ControllerCollection::iterator i;
|
||||
|
||||
for (i = mControllers->begin(); i != mControllers->end(); ++i) {
|
||||
int irc = (*i)->stop();
|
||||
LOGD("Controller '%s' stop rc = %d", (*i)->getName(), irc);
|
||||
if (irc && !rc)
|
||||
rc = irc;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
Controller *NetworkManager::findController(const char *name) {
|
||||
ControllerCollection::iterator i;
|
||||
for (i = mControllers->begin(); i != mControllers->end(); ++i) {
|
||||
if (!strcmp((*i)->getName(), name))
|
||||
return *i;
|
||||
}
|
||||
LOGW("Controller '%s' not found", name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void NetworkManager::onInterfaceConnected(Controller *c, const InterfaceConfig *cfg) {
|
||||
LOGD("Controller %s interface %s connected", c->getName(), c->getBoundInterface());
|
||||
|
||||
// Look up the interface
|
||||
|
||||
if (0) { // already started?
|
||||
}
|
||||
|
||||
if (cfg) {
|
||||
if (cfg->getUseDhcp() && mDhcp->start(c->getBoundInterface())) {
|
||||
LOGE("DHCP start failed");
|
||||
} else if (!cfg->getUseDhcp()) {
|
||||
// Static configuration
|
||||
}
|
||||
} else {
|
||||
LOGD("No InterfaceConfig for %s:%s - assuming self-managed",
|
||||
c->getName(), c->getBoundInterface());
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkManager::onInterfaceDisconnected(Controller *c, const char *name) {
|
||||
LOGD("Controller %s interface %s disconnected", c->getName(), name);
|
||||
|
||||
// If we have a DHCP request out on this interface then stop it
|
||||
if (1) {
|
||||
mDhcp->stop();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _NETWORKMANAGER_H
|
||||
#define _NETWORKMANAGER_H
|
||||
|
||||
#include <sysutils/SocketListener.h>
|
||||
|
||||
#include "Controller.h"
|
||||
#include "PropertyManager.h"
|
||||
#include "IControllerHandler.h"
|
||||
#include "IDhcpEventHandlers.h"
|
||||
|
||||
class InterfaceConfig;
|
||||
class DhcpClient;
|
||||
|
||||
class NetworkManager : public IControllerHandler, public IDhcpEventHandlers {
|
||||
private:
|
||||
static NetworkManager *sInstance;
|
||||
|
||||
private:
|
||||
ControllerCollection *mControllers;
|
||||
SocketListener *mBroadcaster;
|
||||
PropertyManager *mPropMngr;
|
||||
DhcpClient *mDhcp;
|
||||
|
||||
public:
|
||||
virtual ~NetworkManager();
|
||||
|
||||
int run();
|
||||
|
||||
int attachController(Controller *controller);
|
||||
|
||||
Controller *findController(const char *name);
|
||||
|
||||
void setBroadcaster(SocketListener *sl) { mBroadcaster = sl; }
|
||||
SocketListener *getBroadcaster() { return mBroadcaster; }
|
||||
PropertyManager *getPropMngr() { return mPropMngr; }
|
||||
|
||||
static NetworkManager *Instance();
|
||||
|
||||
private:
|
||||
int startControllers();
|
||||
int stopControllers();
|
||||
|
||||
NetworkManager(PropertyManager *propMngr);
|
||||
|
||||
void onInterfaceConnected(Controller *c, const InterfaceConfig *cfg);
|
||||
void onInterfaceDisconnected(Controller *c, const char *name);
|
||||
};
|
||||
#endif
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "NexusCommand.h"
|
||||
|
||||
NexusCommand::NexusCommand(const char *cmd) :
|
||||
FrameworkCommand(cmd) {
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _NEXUS_COMMAND_H
|
||||
#define _NEXUS_COMMAND_H
|
||||
|
||||
#include <sysutils/FrameworkCommand.h>
|
||||
|
||||
class NexusCommand : public FrameworkCommand {
|
||||
public:
|
||||
NexusCommand(const char *cmd);
|
||||
virtual ~NexusCommand() {}
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#define LOG_TAG "OpenVpnController"
|
||||
#include <cutils/log.h>
|
||||
#include <cutils/properties.h>
|
||||
|
||||
#include <sysutils/ServiceManager.h>
|
||||
|
||||
#include "OpenVpnController.h"
|
||||
#include "PropertyManager.h"
|
||||
|
||||
#define DAEMON_PROP_NAME "vpn.openvpn.status"
|
||||
#define DAEMON_CONFIG_FILE "/data/misc/openvpn/openvpn.conf"
|
||||
|
||||
OpenVpnController::OpenVpnController(PropertyManager *propmngr,
|
||||
IControllerHandler *handlers) :
|
||||
VpnController(propmngr, handlers) {
|
||||
mServiceManager = new ServiceManager();
|
||||
}
|
||||
|
||||
OpenVpnController::~OpenVpnController() {
|
||||
delete mServiceManager;
|
||||
}
|
||||
|
||||
int OpenVpnController::start() {
|
||||
return VpnController::start();
|
||||
}
|
||||
|
||||
int OpenVpnController::stop() {
|
||||
return VpnController::stop();
|
||||
}
|
||||
|
||||
int OpenVpnController::enable() {
|
||||
char svc[PROPERTY_VALUE_MAX];
|
||||
char tmp[64];
|
||||
|
||||
if (!mPropMngr->get("vpn.gateway", tmp, sizeof(tmp))) {
|
||||
LOGE("Error reading property 'vpn.gateway' (%s)", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
snprintf(svc, sizeof(svc), "openvpn:--remote %s 1194", tmp);
|
||||
|
||||
if (mServiceManager->start(svc))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int OpenVpnController::disable() {
|
||||
if (mServiceManager->stop("openvpn"))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _OPEN_VPN_CONTROLLER_H
|
||||
#define _OPEN_VPN_CONTROLLER_H
|
||||
|
||||
#include "PropertyManager.h"
|
||||
#include "VpnController.h"
|
||||
|
||||
class ServiceManager;
|
||||
class IControllerHandler;
|
||||
|
||||
class OpenVpnController : public VpnController {
|
||||
private:
|
||||
ServiceManager *mServiceManager;
|
||||
|
||||
public:
|
||||
OpenVpnController(PropertyManager *propmngr, IControllerHandler *handlers);
|
||||
virtual ~OpenVpnController();
|
||||
|
||||
int start();
|
||||
int stop();
|
||||
|
||||
private:
|
||||
int enable();
|
||||
int disable();
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
class Property {
|
||||
public:
|
||||
static const int NameMaxSize = 128;
|
||||
static const int ValueMaxSize = 255;
|
||||
};
|
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "PropertyManager"
|
||||
|
||||
#include <cutils/log.h>
|
||||
|
||||
#include "PropertyManager.h"
|
||||
|
||||
PropertyManager::PropertyManager() {
|
||||
mPropertyPairs = new PropertyPairCollection();
|
||||
pthread_mutex_init(&mLock, NULL);
|
||||
}
|
||||
|
||||
PropertyManager::~PropertyManager() {
|
||||
delete mPropertyPairs;
|
||||
}
|
||||
|
||||
int PropertyManager::registerProperty(const char *name, IPropertyProvider *pp) {
|
||||
PropertyPairCollection::iterator it;
|
||||
|
||||
// LOGD("registerProperty(%s)", name);
|
||||
pthread_mutex_lock(&mLock);
|
||||
for (it = mPropertyPairs->begin(); it != mPropertyPairs->end(); ++it) {
|
||||
if (!strcmp(name, (*it)->getName())) {
|
||||
errno = EADDRINUSE;
|
||||
LOGE("Failed to register property %s (%s)",
|
||||
name, strerror(errno));
|
||||
pthread_mutex_unlock(&mLock);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
mPropertyPairs->push_back(new PropertyPair(name, pp));
|
||||
pthread_mutex_unlock(&mLock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int PropertyManager::unregisterProperty(const char *name) {
|
||||
PropertyPairCollection::iterator it;
|
||||
|
||||
// LOGD("unregisterProperty(%s)", name);
|
||||
pthread_mutex_lock(&mLock);
|
||||
for (it = mPropertyPairs->begin(); it != mPropertyPairs->end(); ++it) {
|
||||
if (!strcmp(name, (*it)->getName())) {
|
||||
delete ((*it));
|
||||
mPropertyPairs->erase(it);
|
||||
pthread_mutex_unlock(&mLock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&mLock);
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* IPropertyManager methods
|
||||
*/
|
||||
|
||||
int PropertyManager::set(const char *name, const char *value) {
|
||||
PropertyPairCollection::iterator it;
|
||||
|
||||
pthread_mutex_lock(&mLock);
|
||||
for (it = mPropertyPairs->begin(); it != mPropertyPairs->end(); ++it) {
|
||||
if (!strcmp(name, (*it)->getName())) {
|
||||
pthread_mutex_unlock(&mLock);
|
||||
return (*it)->getProvider()->set(name, value);
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&mLock);
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
const char *PropertyManager::get(const char *name, char *buffer, size_t max) {
|
||||
PropertyPairCollection::iterator it;
|
||||
|
||||
memset(buffer, 0, max);
|
||||
pthread_mutex_lock(&mLock);
|
||||
for (it = mPropertyPairs->begin(); it != mPropertyPairs->end(); ++it) {
|
||||
if (!strcmp(name, (*it)->getName())) {
|
||||
pthread_mutex_unlock(&mLock);
|
||||
return (*it)->getProvider()->get(name, buffer, max);
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&mLock);
|
||||
errno = ENOENT;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
android::List<char *> *PropertyManager::createPropertyList() {
|
||||
android::List<char *> *c = new android::List<char *>();
|
||||
|
||||
PropertyPairCollection::iterator it;
|
||||
|
||||
pthread_mutex_lock(&mLock);
|
||||
for (it = mPropertyPairs->begin(); it != mPropertyPairs->end(); ++it)
|
||||
c->push_back(strdup((*it)->getName()));
|
||||
pthread_mutex_unlock(&mLock);
|
||||
return c;
|
||||
}
|
||||
|
||||
PropertyPair::PropertyPair(const char *name, IPropertyProvider *pp) {
|
||||
mName = strdup(name);
|
||||
mPp = pp;
|
||||
}
|
||||
|
||||
PropertyPair::~PropertyPair() {
|
||||
free(mName);
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue