diff options
-rw-r--r-- | adb/Android.mk | 8 | ||||
-rw-r--r-- | adb/SERVICES.TXT | 11 | ||||
-rw-r--r-- | adb/adb.c | 10 | ||||
-rw-r--r-- | adb/commandline.c | 136 | ||||
-rw-r--r-- | adb/kdbg.c | 474 | ||||
-rw-r--r-- | adb/services.c | 5 | ||||
-rw-r--r-- | include/arch/linux-arm/AndroidConfig.h | 5 | ||||
-rw-r--r-- | init/devices.c | 1 | ||||
-rw-r--r-- | init/init.c | 157 | ||||
-rw-r--r-- | init/init.h | 7 | ||||
-rw-r--r-- | init/keywords.h | 1 | ||||
-rw-r--r-- | init/parser.c | 45 | ||||
-rw-r--r-- | mountd/ASEC.c | 18 | ||||
-rw-r--r-- | mountd/Android.mk | 3 | ||||
-rw-r--r-- | mountd/AutoMount.c | 62 | ||||
-rw-r--r-- | mountd/dm-ioctl.h | 304 | ||||
-rw-r--r-- | mountd/logwrapper.c | 154 | ||||
-rw-r--r-- | mountd/mountd.h | 2 |
18 files changed, 389 insertions, 1014 deletions
diff --git a/adb/Android.mk b/adb/Android.mk index c06485f..2296610 100644 --- a/adb/Android.mk +++ b/adb/Android.mk @@ -77,14 +77,6 @@ ifeq ($(HOST_OS),windows) $(LOCAL_INSTALLED_MODULE): $(HOST_OUT_EXECUTABLES)/AdbWinApi.dll endif -ifeq ($(HOST_OS),linux) -include $(CLEAR_VARS) -LOCAL_SRC_FILES := \ - kdbg.c -LOCAL_MODULE := kdbg -include $(BUILD_HOST_EXECUTABLE) -endif - endif # adbd device daemon diff --git a/adb/SERVICES.TXT b/adb/SERVICES.TXT index d059e18..b0124a4 100644 --- a/adb/SERVICES.TXT +++ b/adb/SERVICES.TXT @@ -91,7 +91,7 @@ host:<request> <host-prefix>:get-state Returns the state of a given device as a string. -<host-prefix>:forward:<local>:<remote> +<host-prefix>:forward:<local>;<remote> Asks the ADB server to forward local connections from <local> to the <remote> address on a given device. @@ -135,15 +135,6 @@ shell: this to implement "adb shell", but will also cook the input before sending it to the device (see interactive_shell() in commandline.c) -bootdebug: - Ask debugging information to the bootloader. The adbd daemon will - respond with FAIL to this request. - -bootloader:<command> - Send a request to the bootloader. This can also work if the device - is currently in the bootloader state. The adbd daemon will respond - with FAIL to such requests. - remount: Ask adbd to remount the device's filesystem in read-write mode, instead of read-only. This is usually necessary before performing @@ -985,16 +985,6 @@ int handle_host_request(char *service, transport_type ttype, char* serial, int r return 0; } - if(!strncmp(service,"get-product",strlen("get-product"))) { - char *out = "unknown"; - transport = acquire_one_transport(CS_ANY, ttype, serial, NULL); - if (transport && transport->product) { - out = transport->product; - } - snprintf(buf, sizeof buf, "OKAY%04x%s",(unsigned)strlen(out),out); - writex(reply_fd, buf, strlen(buf)); - return 0; - } if(!strncmp(service,"get-serialno",strlen("get-serialno"))) { char *out = "unknown"; transport = acquire_one_transport(CS_ANY, ttype, serial, NULL); diff --git a/adb/commandline.c b/adb/commandline.c index cbf079c..be596ce 100644 --- a/adb/commandline.c +++ b/adb/commandline.c @@ -144,7 +144,6 @@ void help() " adb start-server - ensure that there is a server running\n" " adb kill-server - kill the server if it is running\n" " adb get-state - prints: offline | bootloader | device\n" - " adb get-product - prints: <product-id>\n" " adb get-serialno - prints: <serial-number>\n" " adb status-window - continuously print device status for a specified device\n" " adb remount - remounts the /system partition on the device read-write\n" @@ -377,82 +376,6 @@ int interactive_shell(void) } - -int adb_download_buffer(const char *service, const void* data, int sz, - unsigned progress) -{ - char buf[4096]; - unsigned total; - int fd; - const unsigned char *ptr; - - snprintf(buf, sizeof buf, "%s:%d", service, sz); - fd = adb_connect(buf); - if(fd < 0) { - fprintf(stderr,"error: %s\n", adb_error()); - return -1; - } - - adb_socket_setbufsize(fd, CHUNK_SIZE); - - total = sz; - ptr = data; - - if(progress) { - char *x = strrchr(service, ':'); - if(x) service = x + 1; - } - - while(sz > 0) { - unsigned xfer = (sz > CHUNK_SIZE) ? CHUNK_SIZE : sz; - if(writex(fd, ptr, xfer)) { - adb_status(fd); - fprintf(stderr,"* failed to write data '%s' *\n", adb_error()); - return -1; - } - sz -= xfer; - ptr += xfer; - if(progress) { - int percent = 100 - (int)(100.0 * ((float)sz / (float)total)); - printf("sending: '%s' %4d%% \r", service, percent); - fflush(stdout); - } - } - if(progress) { - printf("\n"); - } - - if(readx(fd, buf, 4)){ - fprintf(stderr,"* error reading response *\n"); - adb_close(fd); - return -1; - } - if(memcmp(buf, "OKAY", 4)) { - buf[4] = 0; - fprintf(stderr,"* error response '%s' *\n", buf); - adb_close(fd); - return -1; - } - - adb_close(fd); - return 0; -} - - -int adb_download(const char *service, const char *fn, unsigned progress) -{ - void *data; - unsigned sz; - - data = load_file(fn, &sz); - if(data == 0) { - fprintf(stderr,"* cannot read '%s' *\n", service); - return -1; - } - - return adb_download_buffer(service, data, sz, progress); -} - static void format_host_command(char* buffer, size_t buflen, const char* command, transport_type ttype, const char* serial) { if (serial) { @@ -678,13 +601,6 @@ static int logcat(transport_type transport, char* serial, int argc, char **argv) return 0; } -int adb_download_data(const char *what, const void* data, int sz, unsigned progress) -{ - char service[4096]; - snprintf(service, sizeof service, "bootloader:flash:%s", what); - return adb_download_buffer(service, data, sz, 1); -} - #define SENTINEL_FILE "config" OS_PATH_SEPARATOR_STR "envsetup.make" static int top_works(const char *top) { @@ -977,32 +893,6 @@ top: } } - if(!strcmp(argv[0], "debug")) { - int fd = adb_connect("bootdebug:"); - if(fd >= 0) { - read_and_dump(fd); - adb_close(fd); - return 0; - } - fprintf(stderr,"error: %s\n", adb_error()); - return 1; - } - - if(!strcmp(argv[0], "bl")) { - int fd; - if(argc != 2) return usage(); - snprintf(buf, sizeof buf, "bootloader:%s", argv[1]); - fd = adb_connect(buf); - if(fd >= 0) { - read_and_dump(fd); - adb_close(fd); - return 0; - } else { - fprintf(stderr,"* command failed: %s *\n", adb_error()); - } - return 1; - } - if(!strcmp(argv[0], "kill-server")) { int fd; fd = _adb_connect("host:kill"); @@ -1024,27 +914,6 @@ top: return 1; } - /* adb_download() commands */ - - if(!strcmp(argv[0], "send")) { - if(argc != 3) return usage(); - snprintf(buf, sizeof buf, "bootloader:send:%s", argv[1]); - if(adb_download(buf, argv[2], 1)) { - return 1; - } else { - return 0; - } - } - - if(!strcmp(argv[0], "recover")) { - if(argc != 2) return usage(); - if(adb_download("recover", argv[1], 1)) { - return 1; - } else { - return 0; - } - } - if(!strcmp(argv[0], "bugreport")) { if (argc != 1) { return 1; @@ -1057,9 +926,7 @@ top: if(!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) { char* service = argv[0]; - if (!strncmp(service, "wait-for-bootloader", strlen("wait-for-bootloader"))) { - fprintf(stderr,"WAIT FOR BOOTLOADER\n"); - } else if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) { + if (!strncmp(service, "wait-for-device", strlen("wait-for-device"))) { if (ttype == kTransportUsb) { service = "wait-for-usb"; } else if (ttype == kTransportLocal) { @@ -1157,7 +1024,6 @@ top: /* passthrough commands */ if(!strcmp(argv[0],"get-state") || - !strcmp(argv[0],"get-product") || !strcmp(argv[0],"get-serialno")) { char *tmp; diff --git a/adb/kdbg.c b/adb/kdbg.c deleted file mode 100644 index 60de53c..0000000 --- a/adb/kdbg.c +++ /dev/null @@ -1,474 +0,0 @@ -/* - * 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 _GNU_SOURCE -#include <stdio.h> - -#include <stdlib.h> -#include <unistd.h> -#include <string.h> - -#include <sys/ioctl.h> -#include <sys/types.h> -#include <dirent.h> -#include <fcntl.h> -#include <errno.h> -#include <pthread.h> -#include <ctype.h> - -#include <linux/usbdevice_fs.h> -#include <linux/version.h> -#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 20) -#include <linux/usb/ch9.h> -#else -#include <linux/usb_ch9.h> -#endif -#include <asm/byteorder.h> - -#include <cutils/fdevent.h> -#include "adb.h" - - -#define TRACE_USB 0 - -#if TRACE_USB -#define DBG1(x...) fprintf(stderr, x) -#define DBG(x...) fprintf(stderr, x) -#else -#define DBG(x...) -#define DBG1(x...) -#endif - -struct usb_handle -{ - struct usb_handle *next; - char fname[32]; - int desc; - unsigned char ep_in; - unsigned char ep_out; - unsigned int interface; -}; - -static struct usb_handle *g_first_usb_device; -static struct usb_handle *g_last_usb_device; - -static void new_device(char *dev_name, unsigned char ep_in, unsigned char ep_out, unsigned int interface) -{ - struct usb_handle* usb; - - DBG("New device being added %s \n", dev_name); - - usb = (struct usb_handle *)calloc(1, sizeof(struct usb_handle)); - strcpy(usb->fname, dev_name); - usb->ep_in = ep_in; - usb->ep_out = ep_out; - usb->interface = interface; - usb->next = NULL; - if(g_last_usb_device) - g_last_usb_device->next = usb; - else - g_first_usb_device = usb; - g_last_usb_device = usb; -} - - -static inline int badname(const char *name) -{ - if(!isdigit(name[0])) return 1; - if(!isdigit(name[1])) return 1; - if(!isdigit(name[2])) return 1; - if(name[3] != 0) return 1; - return 0; -} - -static int find_usb_devices(const char *base, unsigned vendor, unsigned product1, unsigned product2, - unsigned ifclass, unsigned ifsubclass, - unsigned ifprotocol, unsigned numendpoints) -{ - char busname[32], devname[32]; - unsigned char local_ep_in, local_ep_out; - DIR *busdir , *devdir ; - struct dirent *de; - int fd ; - int ret_val = -1; - int found_device = 0; - - busdir = opendir(base); - if(busdir == 0) return 0; - - while((de = readdir(busdir)) != 0) { - if(badname(de->d_name)) continue; - - snprintf(busname, sizeof busname, "%s/%s", base, de->d_name); - devdir = opendir(busname); - if(devdir == 0) continue; - - DBG("[ scanning %s ]\n", busname); - while((de = readdir(devdir))) { - if(badname(de->d_name)) continue; - snprintf(devname, sizeof devname, "%s/%s", busname, de->d_name); - - DBG("[ scanning %s ]\n", devname); - fd = open(devname, O_RDWR); - if(fd < 0) { - continue; - } else { - unsigned char devdesc[256]; - unsigned char* bufptr = devdesc; - struct usb_device_descriptor* device; - struct usb_config_descriptor* config; - struct usb_interface_descriptor* interface; - struct usb_endpoint_descriptor *ep1, *ep2; - unsigned vid, pid; - int i, interfaces; - - size_t desclength = read(fd, devdesc, sizeof(devdesc)); - - // should have device and configuration descriptors, and atleast two endpoints - if (desclength < USB_DT_DEVICE_SIZE + USB_DT_CONFIG_SIZE) { - DBG("desclength %d is too small\n", desclength); - close(fd); - continue; - } - - device = (struct usb_device_descriptor*)bufptr; - bufptr += USB_DT_DEVICE_SIZE; - if(device->bLength == USB_DT_DEVICE_SIZE && device->bDescriptorType == USB_DT_DEVICE) { - vid = __le16_to_cpu(device->idVendor); - pid = __le16_to_cpu(device->idProduct); - pid = devdesc[10] | (devdesc[11] << 8); - DBG("[ %s is V:%04x P:%04x ]\n", devname, vid, pid); - if((vendor == vid) && (product1 == pid || product2 == pid)){ - - // should have config descriptor next - config = (struct usb_config_descriptor *)bufptr; - bufptr += USB_DT_CONFIG_SIZE; - if (config->bLength != USB_DT_CONFIG_SIZE || config->bDescriptorType != USB_DT_CONFIG) { - DBG("usb_config_descriptor not found\n"); - close(fd); - continue; - } - - // loop through all the interfaces and look for the ADB interface - interfaces = config->bNumInterfaces; - for (i = 0; i < interfaces; i++) { - if (bufptr + USB_DT_ENDPOINT_SIZE > devdesc + desclength) - break; - - interface = (struct usb_interface_descriptor *)bufptr; - bufptr += USB_DT_INTERFACE_SIZE; - if (interface->bLength != USB_DT_INTERFACE_SIZE || - interface->bDescriptorType != USB_DT_INTERFACE) { - DBG("usb_interface_descriptor not found\n"); - break; - } - - DBG("bInterfaceClass: %d, bInterfaceSubClass: %d,\ - bInterfaceProtocol: %d, bNumEndpoints: %d\n", - interface->bInterfaceClass, interface->bInterfaceSubClass, - interface->bInterfaceProtocol, interface->bNumEndpoints); - // Sooner bootloader has zero for bInterfaceClass, while adb has USB_CLASS_CDC_DATA - if (interface->bInterfaceClass == ifclass && - interface->bInterfaceSubClass == ifsubclass && - interface->bInterfaceProtocol == ifprotocol && - interface->bNumEndpoints == numendpoints) { - - DBG("looking for bulk endpoints\n"); - // looks like ADB... - ep1 = (struct usb_endpoint_descriptor *)bufptr; - bufptr += USB_DT_ENDPOINT_SIZE; - ep2 = (struct usb_endpoint_descriptor *)bufptr; - bufptr += USB_DT_ENDPOINT_SIZE; - - if (bufptr > devdesc + desclength || - ep1->bLength != USB_DT_ENDPOINT_SIZE || - ep1->bDescriptorType != USB_DT_ENDPOINT || - ep2->bLength != USB_DT_ENDPOINT_SIZE || - ep2->bDescriptorType != USB_DT_ENDPOINT) { - DBG("endpoints not found\n"); - break; - } - - // both endpoints should be bulk - if (ep1->bmAttributes != USB_ENDPOINT_XFER_BULK || - ep2->bmAttributes != USB_ENDPOINT_XFER_BULK) { - DBG("bulk endpoints not found\n"); - continue; - } - - // we have a match. now we just need to figure out which is in and which is out. - if (ep1->bEndpointAddress & USB_ENDPOINT_DIR_MASK) { - local_ep_in = ep1->bEndpointAddress; - local_ep_out = ep2->bEndpointAddress; - } else { - local_ep_in = ep2->bEndpointAddress; - local_ep_out = ep1->bEndpointAddress; - } - - new_device(devname, local_ep_in, local_ep_out, i); - found_device = 1; - close(fd); - } else { - // skip to next interface - bufptr += (interface->bNumEndpoints * USB_DT_ENDPOINT_SIZE); - } - } // end of for - } //end of productid if - } - close(fd); - } // end of if - } // end of devdir while - closedir(devdir); - } //end of busdir while - closedir(busdir); - - return found_device; -} - - -static void find_devices(unsigned vendor, unsigned product1, unsigned product2) -{ - // don't scan /proc/bus/usb if we find something in /dev/bus/usb, to avoid duplication of devices. - if (!find_usb_devices("/dev/bus/usb", vendor, product1, product2, USB_CLASS_VENDOR_SPEC, 1, 0, 2)) { - find_usb_devices("/proc/bus/usb", vendor, product1, product2, USB_CLASS_VENDOR_SPEC, 1, 0, 2); - } -} - -void usb_open_device(struct usb_handle *h) -{ - int n = 0; - - h->desc = open(h->fname, O_RDWR); - //DBG("[ usb open %s fd = %d]\n", h->fname, h->desc); - n = ioctl(h->desc, USBDEVFS_CLAIMINTERFACE, &h->interface); - if(n != 0) goto fail; -// t->usb_is_open = 1; - return; - - -fail: - DBG("[ usb open %s error=%d, err_str = %s]\n", - h->fname, errno, strerror(errno)); - if(h->desc >= 0) { - close(h->desc); - h->desc = -1; - } -// t->usb_is_open = 0; -} - -int usb_write(struct usb_handle *h, const void *_data, int len) -{ - unsigned char *data = (unsigned char*) _data; - struct usbdevfs_bulktransfer bulk; - int n; - - while(len >= 0) { - int xfer = (len > 4096) ? 4096 : len; - - bulk.ep = h->ep_out; - bulk.len = xfer; - bulk.data = data; - bulk.timeout = 500 + xfer * 8; - - bulk.timeout *= 10; - - n = ioctl(h->desc, USBDEVFS_BULK, &bulk); - if(n != xfer) { - DBG("ERROR: n = %d, errno = %d (%s)\n", - n, errno, strerror(errno)); - return -1; - } - if(len == 0) - break; - - len -= xfer; - data += xfer; - if(len == 0) - break; - } - - return 0; -} - -int usb_read(struct usb_handle *h, void *_data, int len) -{ - unsigned char *data_start = (unsigned char*) _data; - unsigned char *data = (unsigned char*) _data; - struct usbdevfs_bulktransfer bulk; - int n; - - while(len > 0) { - int xfer = (len > 4096) ? 4096 : len; - - bulk.ep = h->ep_in; - bulk.len = xfer; - bulk.data = data; - - // adjust timeout based on the data we're transferring, - // otherwise the timeout interrupts us partway through - // and we get out of sync... - bulk.timeout = 500 + xfer * 8; - - bulk.timeout = 500 + xfer / 128; - -// bulk.timeout *= 10; - DBG1("[ usb read %d fd = %d], fname=%s\n", xfer, h->desc, h->fname); - n = ioctl(h->desc, USBDEVFS_BULK, &bulk); - DBG1("[ usb read %d ] = %d, fname=%s\n", xfer, n, h->fname); - if(n < 0) { - if((errno == ETIMEDOUT) && (h->desc != -1)) { - DBG("[ timeout ]\n"); - if(n > 0){ - data += n; - len -= n; - } - continue; - } - DBG1("ERROR: n = %d, errno = %d (%s)\n", - n, errno, strerror(errno)); - return -1; - } - - len -= n; - data += n; - if(n != xfer) - break; - } - - return data - data_start; -} - -void usb_kick(struct usb_handle *h) -{ - close(h->desc); - h->desc = -1; -} - -int usb_close(struct usb_handle *h) -{ - close(h->desc); - h->desc = -1; - return 0; -} - -void list_devices() -{ - int i = 0; - struct usb_handle *h = g_first_usb_device; - while(h) { - printf("%d: %s\n", i, h->fname); - i++; - h = h->next; - } -} - -int main(int argc, char **argv) -{ - char buffer[4096/*-64*/]; - int len; - int c; - char *arg; - int device_index = 0; - struct usb_handle *h; - int i; - - find_devices(VENDOR_ID_GOOGLE, PRODUCT_ID_SOONER, PRODUCT_ID_SOONER_COMP); - while(1) { - c = getopt(argc, argv, "d:l"); - if (c == EOF) - break; - switch(c) { - case 'd': - device_index = strtol(optarg, NULL, 0); - break; - case 'l': - list_devices(); - return 0; - case '?': - fprintf(stderr, "%s: invalid option -%c\n", - argv[0], optopt); - return 1; - } - } - - argc -= optind - 1; - argv += optind - 1; - - h = g_first_usb_device; - i = device_index; - while(i-- > 0 && h) { - h = h->next; - } - if(h == NULL) { - fprintf(stderr, "no device %d\n", device_index); - return 1; - } - - usb_open_device(h); - if(g_first_usb_device->desc < 0) { - fprintf(stderr, "could not open device (%s), %s\n", h->fname, strerror(errno)); - return 1; - } - len = 0; - if(argc == 1) { - char *line = NULL; - size_t line_size = 0; - while((len = getline(&line, &line_size, stdin)) >= 0) { - //if(len > 0 && line[len - 1] == '\n') - // len--; - usb_write(h, line, len); - while(1) { - len = usb_read(h, buffer, sizeof(buffer)); - if(len < 0) - break; - write(STDOUT_FILENO, buffer, len); - if(len < (int)sizeof(buffer)) - break; - } - } - return 0; - } - while(argc > 1) { - argc--; - argv++; - arg = *argv; - while(arg) { - if(*arg) - buffer[len++] = *arg++; - else { - arg = NULL; - if(argc > 1) - buffer[len++] = ' '; - else - break; - } - if(len == sizeof(buffer)) { - usb_write(h, buffer, len); - len = 0; - } - } - } - usb_write(h, buffer, len); - while(1) { - len = usb_read(h, buffer, sizeof(buffer)); - if(len < 0) - break; - write(STDOUT_FILENO, buffer, len); - if(len < (int)sizeof(buffer)) - break; - } - return 0; -} diff --git a/adb/services.c b/adb/services.c index 23730d8..e686949 100644 --- a/adb/services.c +++ b/adb/services.c @@ -345,10 +345,7 @@ asocket* host_service_to_socket(const char* name, const char *serial) name += strlen("wait-for-"); - if (!strncmp(name, "bootloader", strlen("bootloader"))) { - sinfo->transport = kTransportUsb; - sinfo->state = CS_BOOTLOADER; - } else if (!strncmp(name, "local", strlen("local"))) { + if (!strncmp(name, "local", strlen("local"))) { sinfo->transport = kTransportLocal; sinfo->state = CS_DEVICE; } else if (!strncmp(name, "usb", strlen("usb"))) { diff --git a/include/arch/linux-arm/AndroidConfig.h b/include/arch/linux-arm/AndroidConfig.h index b2dabf2..f322127 100644 --- a/include/arch/linux-arm/AndroidConfig.h +++ b/include/arch/linux-arm/AndroidConfig.h @@ -248,6 +248,11 @@ #define ARCH_ARM /* + * Define if the size of enums is as short as possible, + */ +/* #define HAVE_SHORT_ENUMS */ + +/* * sprintf() format string for shared library naming. */ #define OS_SHARED_LIB_FORMAT_STR "lib%s.so" diff --git a/init/devices.c b/init/devices.c index f86eab9..44e263d 100644 --- a/init/devices.c +++ b/init/devices.c @@ -122,6 +122,7 @@ static struct perms_ devperms[] = { { "/dev/msm_pcm_out", 0660, AID_SYSTEM, AID_AUDIO, 1 }, { "/dev/msm_pcm_in", 0660, AID_SYSTEM, AID_AUDIO, 1 }, { "/dev/msm_pcm_ctl", 0660, AID_SYSTEM, AID_AUDIO, 1 }, + { "/dev/msm_snd", 0660, AID_SYSTEM, AID_AUDIO, 1 }, { "/dev/msm_mp3", 0660, AID_SYSTEM, AID_AUDIO, 1 }, { "/dev/smd0", 0640, AID_RADIO, AID_RADIO, 0 }, { "/dev/qmi", 0640, AID_RADIO, AID_RADIO, 0 }, diff --git a/init/init.c b/init/init.c index 3616840..b8b4f40 100644 --- a/init/init.c +++ b/init/init.c @@ -37,6 +37,7 @@ #include <cutils/sockets.h> #include <termios.h> #include <linux/kd.h> +#include <linux/keychord.h> #include <sys/system_properties.h> @@ -60,6 +61,9 @@ static char bootloader[32]; static char hardware[32]; static unsigned revision = 0; static char qemu[32]; +static struct input_keychord *keychords = 0; +static int keychords_count = 0; +static int keychords_length = 0; static void drain_action_queue(void); @@ -233,7 +237,7 @@ void service_start(struct service *svc) setpgid(0, getpid()); - /* as requested, set our gid, supplemental gids, and uid */ + /* as requested, set our gid, supplemental gids, and uid */ if (svc->gid) { setgid(svc->gid); } @@ -658,17 +662,101 @@ void open_devnull_stdio(void) exit(1); } +void add_service_keycodes(struct service *svc) +{ + struct input_keychord *keychord; + int i, size; + + if (svc->keycodes) { + /* add a new keychord to the list */ + size = sizeof(*keychord) + svc->nkeycodes * sizeof(keychord->keycodes[0]); + keychords = realloc(keychords, keychords_length + size); + if (!keychords) { + ERROR("could not allocate keychords\n"); + keychords_length = 0; + keychords_count = 0; + return; + } + + keychord = (struct input_keychord *)((char *)keychords + keychords_length); + keychord->version = KEYCHORD_VERSION; + keychord->id = keychords_count + 1; + keychord->count = svc->nkeycodes; + svc->keychord_id = keychord->id; + + for (i = 0; i < svc->nkeycodes; i++) { + keychord->keycodes[i] = svc->keycodes[i]; + } + keychords_count++; + keychords_length += size; + } +} + +int open_keychord() +{ + int fd, ret; + + service_for_each(add_service_keycodes); + + /* nothing to do if no services require keychords */ + if (!keychords) + return -1; + + fd = open("/dev/keychord", O_RDWR); + if (fd < 0) { + ERROR("could not open /dev/keychord\n"); + return fd; + } + fcntl(fd, F_SETFD, FD_CLOEXEC); + + ret = write(fd, keychords, keychords_length); + if (ret != keychords_length) { + ERROR("could not configure /dev/keychord %d (%d)\n", ret, errno); + close(fd); + fd = -1; + } + + free(keychords); + keychords = 0; + + return fd; +} + +void handle_keychord(int fd) +{ + struct service *svc; + int ret; + __u16 id; + + ret = read(fd, &id, sizeof(id)); + if (ret != sizeof(id)) { + ERROR("could not read keychord id\n"); + return; + } + + svc = service_find_by_keychord(id); + if (svc) { + INFO("starting service %s from keychord\n", svc->name); + service_start(svc); + } else { + ERROR("service for keychord %d not found\n", id); + } +} + int main(int argc, char **argv) { int device_fd = -1; int property_set_fd = -1; int signal_recv_fd = -1; + int keychord_fd = -1; + int fd_count; int s[2]; int fd; struct sigaction act; char tmp[PROP_VALUE_MAX]; struct pollfd ufds[4]; char *tmpdev; + char* debuggable; act.sa_handler = sigchld_handler; act.sa_flags = SA_NOCLDSTOP; @@ -721,6 +809,12 @@ int main(int argc, char **argv) device_fd = device_init(); property_init(); + + // only listen for keychords if ro.debuggable is true + debuggable = property_get("ro.debuggable"); + if (debuggable && !strcmp(debuggable, "1")) { + keychord_fd = open_keychord(); + } if (console[0]) { snprintf(tmp, sizeof(tmp), "/dev/%s", console); @@ -733,27 +827,27 @@ int main(int argc, char **argv) close(fd); if( load_565rle_image(INIT_IMAGE_FILE) ) { - fd = open("/dev/tty0", O_WRONLY); - if (fd >= 0) { - const char *msg; + fd = open("/dev/tty0", O_WRONLY); + if (fd >= 0) { + const char *msg; msg = "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" // console is 40 cols x 30 lines - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - " A N D R O I D "; - write(fd, msg, strlen(msg)); - close(fd); - } + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" // console is 40 cols x 30 lines + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + " A N D R O I D "; + write(fd, msg, strlen(msg)); + close(fd); + } } if (qemu[0]) @@ -823,6 +917,16 @@ int main(int argc, char **argv) ufds[1].events = POLLIN; ufds[2].fd = signal_recv_fd; ufds[2].events = POLLIN; + fd_count = 3; + + if (keychord_fd > 0) { + ufds[3].fd = keychord_fd; + ufds[3].events = POLLIN; + fd_count++; + } else { + ufds[3].events = 0; + ufds[3].revents = 0; + } #if BOOTCHART bootchart_count = bootchart_init(); @@ -836,11 +940,10 @@ int main(int argc, char **argv) #endif for(;;) { - int nr, timeout = -1; + int nr, i, timeout = -1; - ufds[0].revents = 0; - ufds[1].revents = 0; - ufds[2].revents = 0; + for (i = 0; i < fd_count; i++) + ufds[i].revents = 0; drain_action_queue(); restart_processes(); @@ -861,7 +964,7 @@ int main(int argc, char **argv) } } #endif - nr = poll(ufds, 3, timeout); + nr = poll(ufds, fd_count, timeout); if (nr <= 0) continue; @@ -878,6 +981,8 @@ int main(int argc, char **argv) if (ufds[1].revents == POLLIN) handle_property_set_fd(property_set_fd); + if (ufds[3].revents == POLLIN) + handle_keychord(keychord_fd); } return 0; diff --git a/init/init.h b/init/init.h index 4ff0c69..b686869 100644 --- a/init/init.h +++ b/init/init.h @@ -139,12 +139,19 @@ struct service { 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 parse_config_file(const char *fn); struct service *service_find_by_name(const char *name); struct service *service_find_by_pid(pid_t pid); +struct service *service_find_by_keychord(int keychord_id); +void service_for_each(void (*func)(struct service *svc)); void service_for_each_class(const char *classname, void (*func)(struct service *svc)); void service_for_each_flags(unsigned matchflags, diff --git a/init/keywords.h b/init/keywords.h index 058996e..6f47379 100644 --- a/init/keywords.h +++ b/init/keywords.h @@ -45,6 +45,7 @@ enum { KEYWORD(ifup, COMMAND, 1, do_ifup) KEYWORD(insmod, COMMAND, 1, do_insmod) KEYWORD(import, COMMAND, 1, do_import) + KEYWORD(keycodes, OPTION, 0, 0) KEYWORD(mkdir, COMMAND, 1, do_mkdir) KEYWORD(mount, COMMAND, 3, do_mount) KEYWORD(on, SECTION, 0, 0) diff --git a/init/parser.c b/init/parser.c index a51691b..6a22d24 100644 --- a/init/parser.c +++ b/init/parser.c @@ -158,6 +158,9 @@ int lookup_keyword(const char *s) if (!strcmp(s, "nsmod")) return K_insmod; if (!strcmp(s, "mport")) return K_import; break; + case 'k': + if (!strcmp(s, "eycodes")) return K_keycodes; + break; case 'l': if (!strcmp(s, "oglevel")) return K_loglevel; break; @@ -183,7 +186,7 @@ int lookup_keyword(const char *s) if (!strcmp(s, "tart")) return K_start; if (!strcmp(s, "top")) return K_stop; if (!strcmp(s, "ymlink")) return K_symlink; - if (!strcmp(s, "ysclktz")) return K_sysclktz; + if (!strcmp(s, "ysclktz")) return K_sysclktz; break; case 't': if (!strcmp(s, "rigger")) return K_trigger; @@ -440,6 +443,29 @@ struct service *service_find_by_pid(pid_t pid) return 0; } +struct service *service_find_by_keychord(int keychord_id) +{ + struct listnode *node; + struct service *svc; + list_for_each(node, &service_list) { + svc = node_to_item(node, struct service, slist); + if (svc->keychord_id == keychord_id) { + return svc; + } + } + return 0; +} + +void service_for_each(void (*func)(struct service *svc)) +{ + struct listnode *node; + struct service *svc; + list_for_each(node, &service_list) { + svc = node_to_item(node, struct service, slist); + func(svc); + } +} + void service_for_each_class(const char *classname, void (*func)(struct service *svc)) { @@ -586,7 +612,7 @@ static void parse_line_service(struct parse_state *state, int nargs, char **args { struct service *svc = state->context; struct command *cmd; - int kw, kw_nargs; + int i, kw, kw_nargs; if (nargs == 0) { return; @@ -624,6 +650,21 @@ static void parse_line_service(struct parse_state *state, int nargs, char **args svc->nr_supp_gids = n - 2; } break; + case K_keycodes: + if (nargs < 2) { + parse_error(state, "keycodes option requires atleast one keycode\n"); + } else { + svc->keycodes = malloc((nargs - 1) * sizeof(svc->keycodes[0])); + if (!svc->keycodes) { + parse_error(state, "could not allocate keycodes\n"); + } else { + svc->nkeycodes = nargs - 1; + for (i = 1; i < nargs; i++) { + svc->keycodes[i - 1] = atoi(args[i]); + } + } + } + break; case K_oneshot: svc->flags |= SVC_ONESHOT; break; diff --git a/mountd/ASEC.c b/mountd/ASEC.c index 3d8e50e..a6aab9c 100644 --- a/mountd/ASEC.c +++ b/mountd/ASEC.c @@ -35,13 +35,15 @@ #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" -#include "dm-ioctl.h" + +//#define MODULE_FAILURE_IS_FATAL extern int init_module(void *, unsigned long, const char *); extern int delete_module(const char *, unsigned int); @@ -104,14 +106,12 @@ void *AsecInit(const char *Name, const char *SrcPath, const char *BackingFile, { 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 (!AsecIsEnabled()) { - LOG_ERROR("AsecInit(): Disabled\n"); - return NULL; - } - if (!Name || !SrcPath || !BackingFile || !Size || !DstPath || !Crypt) { LOG_ERROR("AsecInit(): Invalid arguments\n"); return NULL; @@ -159,7 +159,7 @@ static int AsecLoadModules() sprintf(moduleFile, "%s/%s.ko", MODULE_PATH, moduleName); module = load_file(moduleFile, &size); if (!module) { - LOG_ERROR("Failed to load module %s\n", moduleFile); + LOG_ERROR("Failed to load module %s (%d)\n", moduleFile, errno); return -1; } @@ -659,8 +659,10 @@ int AsecStart(void *Handle) 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))) { @@ -759,8 +761,10 @@ int AsecStop(void *Handle) 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 } } diff --git a/mountd/Android.mk b/mountd/Android.mk index bc128ac..2fb7640 100644 --- a/mountd/Android.mk +++ b/mountd/Android.mk @@ -7,7 +7,8 @@ LOCAL_SRC_FILES:= \ ProcessKiller.c \ Server.c \ mountd.c \ - ASEC.c + ASEC.c \ + logwrapper.c LOCAL_MODULE:= mountd diff --git a/mountd/AutoMount.c b/mountd/AutoMount.c index 0aac871..0853b41 100644 --- a/mountd/AutoMount.c +++ b/mountd/AutoMount.c @@ -109,7 +109,7 @@ boolean gMassStorageConnected = false; static pthread_t sAutoMountThread = 0; static pid_t gExcludedPids[2] = {-1, -1}; -static const char FSCK_MSDOS_PATH[] = "/system/bin/fsck_msdos"; +static const char FSCK_MSDOS_PATH[] = "/system/bin/dosfsck"; // number of mount points that have timeouts pending static int sRetriesPending = 0; @@ -209,40 +209,32 @@ static int CheckFilesystem(const char *device) int result = access(FSCK_MSDOS_PATH, X_OK); if (result != 0) { - LOG_MOUNT("CheckFilesystem(%s): fsck_msdos not found (skipping checks)\n", device); + LOG_MOUNT("CheckFilesystem(%s): %s not found (skipping checks)\n", FSCK_MSDOS_PATH, device); return 0; } - sprintf(cmdline, "%s -p %s", FSCK_MSDOS_PATH, device); - LOG_MOUNT("Checking filesystem (%s)\n", cmdline); - - // XXX: Notify framework we're disk checking - - // XXX: PROTECT FROM VIKING KILLER - if ((rc = system(cmdline)) < 0) { - LOG_ERROR("Error executing disk check command (%d)\n", errno); - return -errno; - } - - rc = WEXITSTATUS(rc); + char *args[7]; + args[0] = FSCK_MSDOS_PATH; + args[1] = "-v"; + args[2] = "-V"; + args[3] = "-w"; + args[4] = "-p"; + args[5] = device; + args[6] = NULL; + + LOG_MOUNT("Checking filesystem on %s\n", device); + rc = logwrap(6, args); + // XXX: We need to be able to distinguish between a FS with an error + // and a block device which does not have a FAT fs at all on it if (rc == 0) { LOG_MOUNT("Filesystem check completed OK\n"); return 0; } else if (rc == 1) { - LOG_MOUNT("Filesystem check failed (invalid usage)\n"); + LOG_MOUNT("Filesystem check failed (general failure)\n"); return -EINVAL; } else if (rc == 2) { - LOG_MOUNT("Filesystem check failed (unresolved issues)\n"); - return -EIO; - } else if (rc == 4) { - LOG_MOUNT("Filesystem check failed (root changed)\n"); - return -EIO; - } else if (rc == 8) { - LOG_MOUNT("Filesystem check failed (general failure)\n"); - return -EIO; - } else if (rc == 12) { - LOG_MOUNT("Filesystem check failed (exit signaled)\n"); + LOG_MOUNT("Filesystem check failed (invalid usage)\n"); return -EIO; } else { LOG_MOUNT("Filesystem check failed (unknown exit code %d)\n", rc); @@ -252,7 +244,7 @@ static int CheckFilesystem(const char *device) static int DoMountDevice(const char* device, const char* mountPoint) { - LOG_MOUNT("mounting %s at %s\n", device, mountPoint); + LOG_MOUNT("Attempting mount of %s on %s\n", device, mountPoint); #if CREATE_MOUNT_POINTS // make sure mount point exists @@ -292,8 +284,10 @@ static int DoMountDevice(const char* device, const char* mountPoint) } int result = access(device, R_OK); - if (result != 0) - return result; + if (result) { + LOG_ERROR("Unable to access '%s' (%d)\n", device, errno); + return -errno; + } if ((result = CheckFilesystem(device))) { LOG_ERROR("Not mounting filesystem due to check failure (%d)\n", result); @@ -304,7 +298,6 @@ static int DoMountDevice(const char* device, const char* mountPoint) // - SD cards with bad filesystem return result; } - // Extra safety measures: flags |= MS_NODEV | MS_NOEXEC | MS_NOSUID | MS_DIRSYNC; @@ -319,9 +312,9 @@ static int DoMountDevice(const char* device, const char* mountPoint) result = mount(device, mountPoint, "vfat", flags, "utf8,uid=1000,gid=1000,fmask=711,dmask=700"); } - LOG_MOUNT("mount returned %d errno: %d\n", result, errno); if (result == 0) { + LOG_MOUNT("Partition %s mounted on %s\n", device, mountPoint); NotifyMediaState(mountPoint, MEDIA_MOUNTED, (flags & MS_RDONLY) != 0); MountPoint* mp = sMountPointList; @@ -342,13 +335,13 @@ static int DoMountDevice(const char* device, const char* mountPoint) mp = mp -> next; } } else if (errno == EBUSY) { - // ignore EBUSY, since it usually means the device is already mounted + LOG_MOUNT("Mount failed (already mounted)\n"); result = 0; } else { #if CREATE_MOUNT_POINTS rmdir(mountPoint); #endif - LOG_MOUNT("mount failed, errno: %d\n", errno); + LOG_MOUNT("Unable to mount %s on %s\n", device, mountPoint); } return result; @@ -404,8 +397,11 @@ static int MountPartition(const char* device, const char* mountPoint) // attempt to mount subpartitions of the device for (i = 1; i < 10; i++) { + int rc; snprintf(buf, sizeof(buf), "%sp%d", device, i); - if (DoMountDevice(buf, mountPoint) == 0) + rc = DoMountDevice(buf, mountPoint); + LOG_MOUNT("DoMountDevice(%s, %s) = %d\n", buf, mountPoint, rc); + if (rc == 0) return 0; } diff --git a/mountd/dm-ioctl.h b/mountd/dm-ioctl.h deleted file mode 100644 index ee5c350..0000000 --- a/mountd/dm-ioctl.h +++ /dev/null @@ -1,304 +0,0 @@ -/* - * Copyright (C) 2001 - 2003 Sistina Software (UK) Limited. - * Copyright (C) 2004 - 2005 Red Hat, Inc. All rights reserved. - * - * This file is released under the LGPL. - */ - -#ifndef _LINUX_DM_IOCTL_V4_H -#define _LINUX_DM_IOCTL_V4_H - -#ifdef linux -# include <linux/types.h> -#endif - -#define DM_DIR "mapper" /* Slashes not supported */ -#define DM_MAX_TYPE_NAME 16 -#define DM_NAME_LEN 128 -#define DM_UUID_LEN 129 - -/* - * A traditional ioctl interface for the device mapper. - * - * Each device can have two tables associated with it, an - * 'active' table which is the one currently used by io passing - * through the device, and an 'inactive' one which is a table - * that is being prepared as a replacement for the 'active' one. - * - * DM_VERSION: - * Just get the version information for the ioctl interface. - * - * DM_REMOVE_ALL: - * Remove all dm devices, destroy all tables. Only really used - * for debug. - * - * DM_LIST_DEVICES: - * Get a list of all the dm device names. - * - * DM_DEV_CREATE: - * Create a new device, neither the 'active' or 'inactive' table - * slots will be filled. The device will be in suspended state - * after creation, however any io to the device will get errored - * since it will be out-of-bounds. - * - * DM_DEV_REMOVE: - * Remove a device, destroy any tables. - * - * DM_DEV_RENAME: - * Rename a device. - * - * DM_SUSPEND: - * This performs both suspend and resume, depending which flag is - * passed in. - * Suspend: This command will not return until all pending io to - * the device has completed. Further io will be deferred until - * the device is resumed. - * Resume: It is no longer an error to issue this command on an - * unsuspended device. If a table is present in the 'inactive' - * slot, it will be moved to the active slot, then the old table - * from the active slot will be _destroyed_. Finally the device - * is resumed. - * - * DM_DEV_STATUS: - * Retrieves the status for the table in the 'active' slot. - * - * DM_DEV_WAIT: - * Wait for a significant event to occur to the device. This - * could either be caused by an event triggered by one of the - * targets of the table in the 'active' slot, or a table change. - * - * DM_TABLE_LOAD: - * Load a table into the 'inactive' slot for the device. The - * device does _not_ need to be suspended prior to this command. - * - * DM_TABLE_CLEAR: - * Destroy any table in the 'inactive' slot (ie. abort). - * - * DM_TABLE_DEPS: - * Return a set of device dependencies for the 'active' table. - * - * DM_TABLE_STATUS: - * Return the targets status for the 'active' table. - * - * DM_TARGET_MSG: - * Pass a message string to the target at a specific offset of a device. - * - * DM_DEV_SET_GEOMETRY: - * Set the geometry of a device by passing in a string in this format: - * - * "cylinders heads sectors_per_track start_sector" - * - * Beware that CHS geometry is nearly obsolete and only provided - * for compatibility with dm devices that can be booted by a PC - * BIOS. See struct hd_geometry for range limits. Also note that - * the geometry is erased if the device size changes. - */ - -/* - * All ioctl arguments consist of a single chunk of memory, with - * this structure at the start. If a uuid is specified any - * lookup (eg. for a DM_INFO) will be done on that, *not* the - * name. - */ -struct dm_ioctl { - /* - * The version number is made up of three parts: - * major - no backward or forward compatibility, - * minor - only backwards compatible, - * patch - both backwards and forwards compatible. - * - * All clients of the ioctl interface should fill in the - * version number of the interface that they were - * compiled with. - * - * All recognised ioctl commands (ie. those that don't - * return -ENOTTY) fill out this field, even if the - * command failed. - */ - uint32_t version[3]; /* in/out */ - uint32_t data_size; /* total size of data passed in - * including this struct */ - - uint32_t data_start; /* offset to start of data - * relative to start of this struct */ - - uint32_t target_count; /* in/out */ - int32_t open_count; /* out */ - uint32_t flags; /* in/out */ - uint32_t event_nr; /* in/out */ - uint32_t padding; - - uint64_t dev; /* in/out */ - - char name[DM_NAME_LEN]; /* device name */ - char uuid[DM_UUID_LEN]; /* unique identifier for - * the block device */ - char data[7]; /* padding or data */ -}; - -/* - * Used to specify tables. These structures appear after the - * dm_ioctl. - */ -struct dm_target_spec { - uint64_t sector_start; - uint64_t length; - int32_t status; /* used when reading from kernel only */ - - /* - * Location of the next dm_target_spec. - * - When specifying targets on a DM_TABLE_LOAD command, this value is - * the number of bytes from the start of the "current" dm_target_spec - * to the start of the "next" dm_target_spec. - * - When retrieving targets on a DM_TABLE_STATUS command, this value - * is the number of bytes from the start of the first dm_target_spec - * (that follows the dm_ioctl struct) to the start of the "next" - * dm_target_spec. - */ - uint32_t next; - - char target_type[DM_MAX_TYPE_NAME]; - - /* - * Parameter string starts immediately after this object. - * Be careful to add padding after string to ensure correct - * alignment of subsequent dm_target_spec. - */ -}; - -/* - * Used to retrieve the target dependencies. - */ -struct dm_target_deps { - uint32_t count; /* Array size */ - uint32_t padding; /* unused */ - uint64_t dev[0]; /* out */ -}; - -/* - * Used to get a list of all dm devices. - */ -struct dm_name_list { - uint64_t dev; - uint32_t next; /* offset to the next record from - the _start_ of this */ - char name[0]; -}; - -/* - * Used to retrieve the target versions - */ -struct dm_target_versions { - uint32_t next; - uint32_t version[3]; - - char name[0]; -}; - -/* - * Used to pass message to a target - */ -struct dm_target_msg { - uint64_t sector; /* Device sector */ - - char message[0]; -}; - -/* - * If you change this make sure you make the corresponding change - * to dm-ioctl.c:lookup_ioctl() - */ -enum { - /* Top level cmds */ - DM_VERSION_CMD = 0, - DM_REMOVE_ALL_CMD, - DM_LIST_DEVICES_CMD, - - /* device level cmds */ - DM_DEV_CREATE_CMD, - DM_DEV_REMOVE_CMD, - DM_DEV_RENAME_CMD, - DM_DEV_SUSPEND_CMD, - DM_DEV_STATUS_CMD, - DM_DEV_WAIT_CMD, - - /* Table level cmds */ - DM_TABLE_LOAD_CMD, - DM_TABLE_CLEAR_CMD, - DM_TABLE_DEPS_CMD, - DM_TABLE_STATUS_CMD, - - /* Added later */ - DM_LIST_VERSIONS_CMD, - DM_TARGET_MSG_CMD, - DM_DEV_SET_GEOMETRY_CMD -}; - -#define DM_IOCTL 0xfd - -#define DM_VERSION _IOWR(DM_IOCTL, DM_VERSION_CMD, struct dm_ioctl) -#define DM_REMOVE_ALL _IOWR(DM_IOCTL, DM_REMOVE_ALL_CMD, struct dm_ioctl) -#define DM_LIST_DEVICES _IOWR(DM_IOCTL, DM_LIST_DEVICES_CMD, struct dm_ioctl) - -#define DM_DEV_CREATE _IOWR(DM_IOCTL, DM_DEV_CREATE_CMD, struct dm_ioctl) -#define DM_DEV_REMOVE _IOWR(DM_IOCTL, DM_DEV_REMOVE_CMD, struct dm_ioctl) -#define DM_DEV_RENAME _IOWR(DM_IOCTL, DM_DEV_RENAME_CMD, struct dm_ioctl) -#define DM_DEV_SUSPEND _IOWR(DM_IOCTL, DM_DEV_SUSPEND_CMD, struct dm_ioctl) -#define DM_DEV_STATUS _IOWR(DM_IOCTL, DM_DEV_STATUS_CMD, struct dm_ioctl) -#define DM_DEV_WAIT _IOWR(DM_IOCTL, DM_DEV_WAIT_CMD, struct dm_ioctl) - -#define DM_TABLE_LOAD _IOWR(DM_IOCTL, DM_TABLE_LOAD_CMD, struct dm_ioctl) -#define DM_TABLE_CLEAR _IOWR(DM_IOCTL, DM_TABLE_CLEAR_CMD, struct dm_ioctl) -#define DM_TABLE_DEPS _IOWR(DM_IOCTL, DM_TABLE_DEPS_CMD, struct dm_ioctl) -#define DM_TABLE_STATUS _IOWR(DM_IOCTL, DM_TABLE_STATUS_CMD, struct dm_ioctl) - -#define DM_LIST_VERSIONS _IOWR(DM_IOCTL, DM_LIST_VERSIONS_CMD, struct dm_ioctl) - -#define DM_TARGET_MSG _IOWR(DM_IOCTL, DM_TARGET_MSG_CMD, struct dm_ioctl) -#define DM_DEV_SET_GEOMETRY _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl) - -#define DM_VERSION_MAJOR 4 -#define DM_VERSION_MINOR 13 -#define DM_VERSION_PATCHLEVEL 0 -#define DM_VERSION_EXTRA "-ioctl (2007-10-18)" - -/* Status bits */ -#define DM_READONLY_FLAG (1 << 0) /* In/Out */ -#define DM_SUSPEND_FLAG (1 << 1) /* In/Out */ -#define DM_PERSISTENT_DEV_FLAG (1 << 3) /* In */ - -/* - * Flag passed into ioctl STATUS command to get table information - * rather than current status. - */ -#define DM_STATUS_TABLE_FLAG (1 << 4) /* In */ - -/* - * Flags that indicate whether a table is present in either of - * the two table slots that a device has. - */ -#define DM_ACTIVE_PRESENT_FLAG (1 << 5) /* Out */ -#define DM_INACTIVE_PRESENT_FLAG (1 << 6) /* Out */ - -/* - * Indicates that the buffer passed in wasn't big enough for the - * results. - */ -#define DM_BUFFER_FULL_FLAG (1 << 8) /* Out */ - -/* - * This flag is now ignored. - */ -#define DM_SKIP_BDGET_FLAG (1 << 9) /* In */ - -/* - * Set this to avoid attempting to freeze any filesystem when suspending. - */ -#define DM_SKIP_LOCKFS_FLAG (1 << 10) /* In */ - -/* - * Set this to suspend without flushing queued ios. - */ -#define DM_NOFLUSH_FLAG (1 << 11) /* In */ - -#endif /* _LINUX_DM_IOCTL_H */ diff --git a/mountd/logwrapper.c b/mountd/logwrapper.c new file mode 100644 index 0000000..69606ab --- /dev/null +++ b/mountd/logwrapper.c @@ -0,0 +1,154 @@ +/* + * 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; +} diff --git a/mountd/mountd.h b/mountd/mountd.h index 9b62484..c4bc91d 100644 --- a/mountd/mountd.h +++ b/mountd/mountd.h @@ -177,6 +177,8 @@ const char *AsecMountPoint(void *Handle); void KillProcessesWithOpenFiles(const char* mountPoint, boolean sigkill, pid_t *excluded, int num_excluded); +// logwrapper.c +int logwrap(int argc, char* argv[]); // Server.c |