diff options
129 files changed, 4844 insertions, 6476 deletions
diff --git a/CleanSpec.mk b/CleanSpec.mk new file mode 100644 index 0000000..b84e1b6 --- /dev/null +++ b/CleanSpec.mk @@ -0,0 +1,49 @@ +# 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. +# + +# If you don't need to do a full clean build but would like to touch +# a file or delete some intermediate files, add a clean step to the end +# of the list. These steps will only be run once, if they haven't been +# run before. +# +# E.g.: +# $(call add-clean-step, touch -c external/sqlite/sqlite3.h) +# $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates) +# +# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with +# files that are missing or have been moved. +# +# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory. +# Use $(OUT_DIR) to refer to the "out" directory. +# +# If you need to re-do something that's already mentioned, just copy +# the command and add it to the bottom of the list. E.g., if a change +# that you made last week required touching a file and a change you +# made today requires touching the same file, just copy the old +# touch step and add it to the end of the list. +# +# ************************************************ +# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST +# ************************************************ + +# For example: +#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates) +#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates) +#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f) +#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*) + +# ************************************************ +# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST +# ************************************************ diff --git a/adb/Android.mk b/adb/Android.mk index 740135e..7faca9b 100644 --- a/adb/Android.mk +++ b/adb/Android.mk @@ -35,13 +35,18 @@ ifeq ($(HOST_OS),windows) USB_SRCS := usb_windows.c EXTRA_SRCS := get_my_path_windows.c EXTRA_STATIC_LIBS := AdbWinApi - LOCAL_C_INCLUDES += /usr/include/w32api/ddk development/host/windows/usb/api/ ifneq ($(strip $(USE_CYGWIN)),) + # Pure cygwin case LOCAL_LDLIBS += -lpthread - else + LOCAL_C_INCLUDES += /usr/include/w32api/ddk + endif + ifneq ($(strip $(USE_MINGW)),) + # MinGW under Linux case LOCAL_LDLIBS += -lws2_32 USE_SYSDEPS_WIN32 := 1 + LOCAL_C_INCLUDES += /usr/i586-mingw32msvc/include/ddk endif + LOCAL_C_INCLUDES += development/host/windows/usb/api/ endif LOCAL_SRC_FILES := \ @@ -901,9 +901,10 @@ int adb_main(int is_daemon, int server_port) ** 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 + ** AID_MOUNT to allow unmounting the SD card before rebooting */ gid_t groups[] = { AID_ADB, AID_LOG, AID_INPUT, AID_INET, AID_GRAPHICS, - AID_NET_BT, AID_NET_BT_ADMIN, AID_SDCARD_RW }; + AID_NET_BT, AID_NET_BT_ADMIN, AID_SDCARD_RW, AID_MOUNT }; setgroups(sizeof(groups)/sizeof(groups[0]), groups); /* then switch user and group to "shell" */ diff --git a/adb/commandline.c b/adb/commandline.c index 02e4658..dcba83b 100644 --- a/adb/commandline.c +++ b/adb/commandline.c @@ -92,7 +92,7 @@ void help() " returns an error if more than one emulator is running.\n" " -s <serial number> - directs command to the USB device or emulator with\n" " the given serial number. Overrides ANDROID_SERIAL\n" - " envivornment variable.\n" + " environment variable.\n" " -p <product name or path> - simple product name like 'sooner', or\n" " a relative/absolute path to a product\n" " out directory like 'out/target/product/sooner'.\n" @@ -126,9 +126,10 @@ void help() " dev:<character device name>\n" " jdwp:<process pid> (remote only)\n" " adb jdwp - list PIDs of processes hosting a JDWP transport\n" - " adb install [-l] [-r] <file> - push this package file to the device and install it\n" + " adb install [-l] [-r] [-s] <file> - push this package file to the device and install it\n" " ('-l' means forward-lock the app)\n" " ('-r' means reinstall the app, keeping its data)\n" + " ('-s' means install on SD card instead of internal storage)\n" " adb uninstall [-k] <package> - remove this app package from the device\n" " ('-k' means keep the data and cache directories)\n" " adb bugreport - return all information from the device\n" @@ -1226,17 +1227,25 @@ int install_app(transport_type transport, char* serial, int argc, char** argv) { struct stat st; int err; - const char *const WHERE = "/data/local/tmp/%s"; + const char *const DATA_DEST = "/data/local/tmp/%s"; + const char *const SD_DEST = "/sdcard/tmp/%s"; + const char* where = DATA_DEST; char to[PATH_MAX]; char* filename = argv[argc - 1]; const char* p; + int i; + + for (i = 0; i < argc; i++) { + if (!strcmp(argv[i], "-s")) + where = SD_DEST; + } p = adb_dirstop(filename); if (p) { p++; - snprintf(to, sizeof to, WHERE, p); + snprintf(to, sizeof to, where, p); } else { - snprintf(to, sizeof to, WHERE, filename); + snprintf(to, sizeof to, where, filename); } if (p[0] == '\0') { } diff --git a/adb/services.c b/adb/services.c index b5df554..487c7d3 100644 --- a/adb/services.c +++ b/adb/services.c @@ -176,9 +176,23 @@ void restart_usb_service(int fd, void *cookie) void reboot_service(int fd, void *arg) { char buf[100]; - int ret; + int pid, ret; sync(); + + /* Attempt to unmount the SD card first. + * No need to bother checking for errors. + */ + pid = fork(); + if (pid == 0) { + /* ask vdc to unmount it */ + execl("/system/bin/vdc", "/system/bin/vdc", "volume", "unmount", + getenv("EXTERNAL_STORAGE"), "force", NULL); + } else if (pid > 0) { + /* wait until vdc succeeds or fails */ + waitpid(pid, &ret, 0); + } + ret = __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART2, (char *)arg); if (ret < 0) { diff --git a/debuggerd/Android.mk b/debuggerd/Android.mk index 1dc8426..ccc001b 100644 --- a/debuggerd/Android.mk +++ b/debuggerd/Android.mk @@ -9,18 +9,41 @@ LOCAL_SRC_FILES:= debuggerd.c getevent.c unwind-arm.c pr-support.c utility.c sym LOCAL_CFLAGS := -Wall LOCAL_MODULE := debuggerd +ifeq ($(ARCH_ARM_HAVE_VFP),true) +LOCAL_CFLAGS += -DWITH_VFP +endif # ARCH_ARM_HAVE_VFP +ifeq ($(ARCH_ARM_HAVE_VFP_D32),true) +LOCAL_CFLAGS += -DWITH_VFP_D32 +endif # ARCH_ARM_HAVE_VFP_D32 + LOCAL_STATIC_LIBRARIES := libcutils libc include $(BUILD_EXECUTABLE) include $(CLEAR_VARS) -LOCAL_SRC_FILES := crasher.c +LOCAL_SRC_FILES := crasher.c LOCAL_SRC_FILES += crashglue.S -LOCAL_MODULE := crasher +LOCAL_MODULE := crasher LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) LOCAL_MODULE_TAGS := eng #LOCAL_FORCE_STATIC_EXECUTABLE := true LOCAL_SHARED_LIBRARIES := libcutils libc include $(BUILD_EXECUTABLE) +ifeq ($(ARCH_ARM_HAVE_VFP),true) +include $(CLEAR_VARS) + +LOCAL_CFLAGS += -DWITH_VFP +ifeq ($(ARCH_ARM_HAVE_VFP_D32),true) +LOCAL_CFLAGS += -DWITH_VFP_D32 +endif # ARCH_ARM_HAVE_VFP_D32 + +LOCAL_SRC_FILES := vfp-crasher.c vfp.S +LOCAL_MODULE := vfp-crasher +LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) +LOCAL_MODULE_TAGS := eng +LOCAL_SHARED_LIBRARIES := libcutils libc +include $(BUILD_EXECUTABLE) +endif # ARCH_ARM_HAVE_VFP == true + endif # TARGET_ARCH == arm diff --git a/debuggerd/crashglue.S b/debuggerd/crashglue.S index 888951b..0c1fd9b 100644 --- a/debuggerd/crashglue.S +++ b/debuggerd/crashglue.S @@ -1,5 +1,7 @@ .globl crash1 +.type crash1, %function .globl crashnostack +.type crashnostack, %function crash1: ldr r0, =0xa5a50000 @@ -25,4 +27,4 @@ crashnostack: mov sp, #0 mov r0, #0 ldr r0, [r0] - b .
\ No newline at end of file + b . diff --git a/debuggerd/debuggerd.c b/debuggerd/debuggerd.c index 02bab2c..3b2972a 100644 --- a/debuggerd/debuggerd.c +++ b/debuggerd/debuggerd.c @@ -42,6 +42,14 @@ #include "utility.h" +#ifdef WITH_VFP +#ifdef WITH_VFP_D32 +#define NUM_VFP_REGS 32 +#else +#define NUM_VFP_REGS 16 +#endif +#endif + /* Main entry point to get the backtrace from the crashing process */ extern int unwind_backtrace_with_ptrace(int tfd, pid_t pid, mapinfo *map, unsigned int sp_list[], @@ -121,7 +129,7 @@ void dump_build_info(int tfd) void dump_stack_and_code(int tfd, int pid, mapinfo *map, int unwind_depth, unsigned int sp_list[], - int frame0_pc_sane, bool at_fault) + bool at_fault) { unsigned int sp, pc, p, end, data; struct pt_regs r; @@ -133,19 +141,11 @@ void dump_stack_and_code(int tfd, int pid, mapinfo *map, sp = r.ARM_sp; pc = r.ARM_pc; - /* Died because calling the weeds - dump - * the code around the PC in the next frame instead. - */ - if (frame0_pc_sane == 0) { - pc = r.ARM_lr; - } - - _LOG(tfd, only_in_tombstone, - "\ncode around %s:\n", frame0_pc_sane ? "pc" : "lr"); + _LOG(tfd, only_in_tombstone, "\ncode around pc:\n"); end = p = pc & ~3; - p -= 16; - end += 16; + p -= 32; + end += 32; /* Dump the code around PC as: * addr contents @@ -164,12 +164,12 @@ void dump_stack_and_code(int tfd, int pid, mapinfo *map, _LOG(tfd, only_in_tombstone, "%s\n", code_buffer); } - if (frame0_pc_sane) { + if ((unsigned) r.ARM_lr != pc) { _LOG(tfd, only_in_tombstone, "\ncode around lr:\n"); end = p = r.ARM_lr & ~3; - p -= 16; - end += 16; + p -= 32; + end += 32; /* Dump the code around LR as: * addr contents @@ -286,6 +286,24 @@ void dump_registers(int tfd, int pid, bool at_fault) _LOG(tfd, only_in_tombstone, " ip %08x sp %08x lr %08x pc %08x cpsr %08x\n", r.ARM_ip, r.ARM_sp, r.ARM_lr, r.ARM_pc, r.ARM_cpsr); + +#ifdef WITH_VFP + struct user_vfp vfp_regs; + int i; + + if(ptrace(PTRACE_GETVFPREGS, pid, 0, &vfp_regs)) { + _LOG(tfd, only_in_tombstone, + "cannot get registers: %s\n", strerror(errno)); + return; + } + + for (i = 0; i < NUM_VFP_REGS; i += 2) { + _LOG(tfd, only_in_tombstone, + " d%-2d %016llx d%-2d %016llx\n", + i, vfp_regs.fpregs[i], i+1, vfp_regs.fpregs[i+1]); + } + _LOG(tfd, only_in_tombstone, " scr %08lx\n\n", vfp_regs.fpscr); +#endif } const char *get_signame(int sig) @@ -421,8 +439,7 @@ void dump_crash_report(int tfd, unsigned pid, unsigned tid, bool at_fault) dump_pc_and_lr(tfd, tid, milist, stack_depth, at_fault); } - dump_stack_and_code(tfd, tid, milist, stack_depth, sp_list, frame0_pc_sane, - at_fault); + dump_stack_and_code(tfd, tid, milist, stack_depth, sp_list, at_fault); while(milist) { mapinfo *next = milist->next; @@ -611,15 +628,16 @@ static void wait_for_user_action(unsigned tid, struct ucred* cr) (void)tid; /* First log a helpful message */ LOG( "********************************************************\n" - "* process %d crashed. debuggerd waiting for gdbserver \n" - "* \n" - "* adb shell gdbserver :port --attach %d & \n" - "* \n" - "* and press the HOME key. \n" + "* Process %d has been suspended while crashing. To\n" + "* attach gdbserver for a gdb connection on port 5039:\n" + "*\n" + "* adb shell gdbserver :5039 --attach %d &\n" + "*\n" + "* Press HOME key to let the process continue crashing.\n" "********************************************************\n", cr->pid, cr->pid); - /* wait for HOME key */ + /* wait for HOME key (TODO: something useful for devices w/o HOME key) */ if (init_getevent() == 0) { int ms = 1200 / 10; int dit = 1; @@ -703,7 +721,7 @@ static void handle_crashing_process(int fd) sprintf(buf,"/proc/%d/task/%d", cr.pid, tid); if(stat(buf, &s)) { - LOG("tid %d does not exist in pid %d. ignorning debug request\n", + LOG("tid %d does not exist in pid %d. ignoring debug request\n", tid, cr.pid); close(fd); return; diff --git a/debuggerd/vfp-crasher.c b/debuggerd/vfp-crasher.c new file mode 100644 index 0000000..7a19cdd --- /dev/null +++ b/debuggerd/vfp-crasher.c @@ -0,0 +1,7 @@ +int main() +{ + extern void crash(void); + + crash(); + return 0; +} diff --git a/debuggerd/vfp.S b/debuggerd/vfp.S new file mode 100644 index 0000000..9744f6f --- /dev/null +++ b/debuggerd/vfp.S @@ -0,0 +1,43 @@ + .text + .align 2 + .global crash + .type crash, %function +crash: + fconstd d0, #0 + fconstd d1, #1 + fconstd d2, #2 + fconstd d3, #3 + fconstd d4, #4 + fconstd d5, #5 + fconstd d6, #6 + fconstd d7, #7 + fconstd d8, #8 + fconstd d9, #9 + fconstd d10, #10 + fconstd d11, #11 + fconstd d12, #12 + fconstd d13, #13 + fconstd d14, #14 + fconstd d15, #15 +#ifdef WITH_VFP_D32 + fconstd d16, #16 + fconstd d17, #17 + fconstd d18, #18 + fconstd d19, #19 + fconstd d20, #20 + fconstd d21, #21 + fconstd d22, #22 + fconstd d23, #23 + fconstd d24, #24 + fconstd d25, #25 + fconstd d26, #26 + fconstd d27, #27 + fconstd d28, #28 + fconstd d29, #29 + fconstd d30, #30 + fconstd d31, #31 +#endif + mov r0, #0 + str r0, [r0] + bx lr + diff --git a/fastboot/Android.mk b/fastboot/Android.mk index 7a9d35f..34380ec 100644 --- a/fastboot/Android.mk +++ b/fastboot/Android.mk @@ -33,11 +33,18 @@ endif ifeq ($(HOST_OS),windows) LOCAL_SRC_FILES += usb_windows.c util_windows.c EXTRA_STATIC_LIBS := AdbWinApi - LOCAL_C_INCLUDES += /usr/include/w32api/ddk development/host/windows/usb/api - ifeq ($(strip $(USE_CYGWIN)),) + ifneq ($(strip $(USE_CYGWIN)),) + # Pure cygwin case + LOCAL_LDLIBS += -lpthread + LOCAL_C_INCLUDES += /usr/include/w32api/ddk + endif + ifneq ($(strip $(USE_MINGW)),) + # MinGW under Linux case LOCAL_LDLIBS += -lws2_32 USE_SYSDEPS_WIN32 := 1 + LOCAL_C_INCLUDES += /usr/i586-mingw32msvc/include/ddk endif + LOCAL_C_INCLUDES += development/host/windows/usb/api endif LOCAL_STATIC_LIBRARIES := $(EXTRA_STATIC_LIBS) libzipfile libunz diff --git a/fastboot/engine.c b/fastboot/engine.c index 4c7e197..6d62c6e 100644 --- a/fastboot/engine.c +++ b/fastboot/engine.c @@ -30,9 +30,17 @@ #include <stdlib.h> #include <stdarg.h> #include <string.h> +#include <sys/time.h> #include "fastboot.h" +double now() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return (double)tv.tv_sec + (double)tv.tv_usec / 1000000; +} + char *mkmsg(const char *fmt, ...) { char buf[256]; @@ -66,6 +74,8 @@ struct Action const char *msg; int (*func)(Action *a, int status, char *resp); + + double start; }; static Action *action_list = 0; @@ -76,7 +86,9 @@ static int cb_default(Action *a, int status, char *resp) if (status) { fprintf(stderr,"FAILED (%s)\n", resp); } else { - fprintf(stderr,"OKAY\n"); + double split = now(); + fprintf(stderr,"OKAY [%7.3fs]\n", (split - a->start)); + a->start = split; } return status; } @@ -101,6 +113,9 @@ static Action *queue_action(unsigned op, const char *fmt, ...) action_last = a; a->op = op; a->func = cb_default; + + a->start = -1; + return a; } @@ -166,7 +181,9 @@ static int cb_check(Action *a, int status, char *resp, int invert) if (invert) yes = !yes; if (yes) { - fprintf(stderr,"OKAY\n"); + double split = now(); + fprintf(stderr,"OKAY [%7.3fs]\n", (split - a->start)); + a->start = split; return 0; } @@ -263,9 +280,12 @@ void fb_execute_queue(usb_handle *usb) a = action_list; resp[FB_RESPONSE_SZ] = 0; + double start = -1; for (a = action_list; a; a = a->next) { + a->start = now(); + if (start < 0) start = a->start; if (a->msg) { - fprintf(stderr,"%s... ",a->msg); + fprintf(stderr,"%30s... ",a->msg); } if (a->op == OP_DOWNLOAD) { status = fb_download_data(usb, a->data, a->size); @@ -285,5 +305,7 @@ void fb_execute_queue(usb_handle *usb) die("bogus action"); } } + + fprintf(stderr,"finished. total time: %.3fs\n", (now() - start)); } diff --git a/fastboot/fastboot.c b/fastboot/fastboot.c index 1308f26..bed30b2 100644 --- a/fastboot/fastboot.c +++ b/fastboot/fastboot.c @@ -149,8 +149,9 @@ int match_fastboot(usb_ifc_info *info) if(!(vendor_id && (info->dev_vendor == vendor_id)) && (info->dev_vendor != 0x18d1) && // Google (info->dev_vendor != 0x0451) && - (info->dev_vendor != 0x22b8) && // Motorola (info->dev_vendor != 0x0502) && + (info->dev_vendor != 0x22b8) && // Motorola + (info->dev_vendor != 0x0955) && // Nvidia (info->dev_vendor != 0x413c) && // DELL (info->dev_vendor != 0x0bb4)) // HTC return -1; @@ -167,6 +168,9 @@ int list_devices_callback(usb_ifc_info *info) { if (match_fastboot(info) == 0) { char* serial = info->serial_number; + if (!info->writable) { + serial = "no permissions"; // like "adb devices" + } if (!serial[0]) { serial = "????????????"; } @@ -227,11 +231,12 @@ void usage(void) " -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" + " -n <page size> specify the nand page size. default: 2048\n" ); exit(1); } -void *load_bootable_image(const char *kernel, const char *ramdisk, +void *load_bootable_image(unsigned page_size, const char *kernel, const char *ramdisk, unsigned *sz, const char *cmdline) { void *kdata = 0, *rdata = 0; @@ -272,7 +277,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, base_addr, &bsize); + bdata = mkbootimg(kdata, ksize, rdata, rsize, 0, 0, page_size, base_addr, &bsize); if(bdata == 0) { fprintf(stderr,"failed to create boot.img\n"); return 0; @@ -544,6 +549,7 @@ int main(int argc, char **argv) int wants_reboot_bootloader = 0; void *data; unsigned sz; + unsigned page_size = 2048; skip(1); if (argc == 0) { @@ -556,6 +562,8 @@ int main(int argc, char **argv) return 0; } + serial = getenv("ANDROID_SERIAL"); + while (argc > 0) { if(!strcmp(*argv, "-w")) { wants_wipe = 1; @@ -564,6 +572,11 @@ int main(int argc, char **argv) require(2); base_addr = strtoul(argv[1], 0, 16); skip(2); + } else if(!strcmp(*argv, "-n")) { + require(2); + page_size = (unsigned)strtoul(argv[1], NULL, 0); + if (!page_size) die("invalid page size"); + skip(2); } else if(!strcmp(*argv, "-s")) { require(2); serial = argv[1]; @@ -623,7 +636,7 @@ int main(int argc, char **argv) rname = argv[0]; skip(1); } - data = load_bootable_image(kname, rname, &sz, cmdline); + data = load_bootable_image(page_size, kname, rname, &sz, cmdline); if (data == 0) return 1; fb_queue_download("boot.img", data, sz); fb_queue_command("boot", "booting"); @@ -653,7 +666,7 @@ int main(int argc, char **argv) } else { skip(3); } - data = load_bootable_image(kname, rname, &sz, cmdline); + data = load_bootable_image(page_size, kname, rname, &sz, cmdline); if (data == 0) die("cannot load bootable image"); fb_queue_flash(pname, data, sz); } else if(!strcmp(*argv, "flashall")) { diff --git a/fastboot/usb.h b/fastboot/usb.h index f3ec5bf..cc157d5 100644 --- a/fastboot/usb.h +++ b/fastboot/usb.h @@ -50,6 +50,8 @@ struct usb_ifc_info unsigned char has_bulk_in; unsigned char has_bulk_out; + unsigned char writable; + char serial_number[256]; }; diff --git a/fastboot/usb_linux.c b/fastboot/usb_linux.c index 3b40ba7..2ce53eb 100644 --- a/fastboot/usb_linux.c +++ b/fastboot/usb_linux.c @@ -89,7 +89,8 @@ static int check(void *_desc, int len, unsigned type, int size) return 0; } -static int filter_usb_device(int fd, char *ptr, int len, ifc_match_func callback, +static int filter_usb_device(int fd, char *ptr, int len, int writable, + ifc_match_func callback, int *ept_in_id, int *ept_out_id, int *ifc_id) { struct usb_device_descriptor *dev; @@ -119,7 +120,8 @@ static int filter_usb_device(int fd, char *ptr, int len, ifc_match_func callback info.dev_class = dev->bDeviceClass; info.dev_subclass = dev->bDeviceSubClass; info.dev_protocol = dev->bDeviceProtocol; - + info.writable = writable; + // read device serial number (if there is one) info.serial_number[0] = 0; if (dev->iSerialNumber) { @@ -201,6 +203,7 @@ static usb_handle *find_usb_device(const char *base, ifc_match_func callback) DIR *busdir, *devdir; struct dirent *de; int fd; + int writable; busdir = opendir(base); if(busdir == 0) return 0; @@ -219,13 +222,20 @@ static usb_handle *find_usb_device(const char *base, ifc_match_func callback) sprintf(devname, "%s/%s", busname, de->d_name); // DBG("[ scanning %s ]\n", devname); + writable = 1; if((fd = open(devname, O_RDWR)) < 0) { - continue; + // Check if we have read-only access, so we can give a helpful + // diagnostic like "adb devices" does. + writable = 0; + if((fd = open(devname, O_RDONLY)) < 0) { + continue; + } } n = read(fd, desc, sizeof(desc)); - if(filter_usb_device(fd, desc, n, callback, &in, &out, &ifc) == 0){ + if(filter_usb_device(fd, desc, n, writable, callback, + &in, &out, &ifc) == 0) { usb = calloc(1, sizeof(usb_handle)); strcpy(usb->fname, devname); usb->ep_in = in; @@ -375,5 +385,3 @@ usb_handle *usb_open(ifc_match_func callback) { return find_usb_device("/dev/bus/usb", callback); } - - diff --git a/fastboot/usb_osx.c b/fastboot/usb_osx.c index d6a8260..0b0512d 100644 --- a/fastboot/usb_osx.c +++ b/fastboot/usb_osx.c @@ -351,6 +351,7 @@ static int try_device(io_service_t device, usb_handle *handle) { // device has no serial number handle->info.serial_number[0] = 0; } + handle->info.writable = 1; if (try_interfaces(dev, handle)) { goto error; @@ -416,8 +417,6 @@ static int init_usb(ifc_match_func callback, usb_handle **handle) { break; } - usb_ifc_info info; - if (try_device(device, &h) != 0) { IOObjectRelease(device); ret = -1; diff --git a/fastboot/usb_windows.c b/fastboot/usb_windows.c index 9c0a9cb..54008a4 100644 --- a/fastboot/usb_windows.c +++ b/fastboot/usb_windows.c @@ -301,6 +301,7 @@ int recognized_device(usb_handle* handle, ifc_match_func callback) { info.ifc_class = interf_desc.bInterfaceClass; info.ifc_subclass = interf_desc.bInterfaceSubClass; info.ifc_protocol = interf_desc.bInterfaceProtocol; + info.writable = 1; // read serial number (if there is one) unsigned long serial_number_len = sizeof(info.serial_number); diff --git a/include/arch/darwin-x86/AndroidConfig.h b/include/arch/darwin-x86/AndroidConfig.h index 363a8f7..3aa0cd1 100644 --- a/include/arch/darwin-x86/AndroidConfig.h +++ b/include/arch/darwin-x86/AndroidConfig.h @@ -256,6 +256,16 @@ #define HAVE_STRLCPY 1 /* + * Define if the open_memstream() function exists on the system. + */ +/* #define HAVE_OPEN_MEMSTREAM 1 */ + +/* + * Define if the BSD funopen() function exists on the system. + */ +#define HAVE_FUNOPEN 1 + +/* * Define if writev() exists */ #define HAVE_WRITEV 1 diff --git a/include/arch/freebsd-x86/AndroidConfig.h b/include/arch/freebsd-x86/AndroidConfig.h index b01a854..57d5024 100644 --- a/include/arch/freebsd-x86/AndroidConfig.h +++ b/include/arch/freebsd-x86/AndroidConfig.h @@ -295,6 +295,16 @@ #define HAVE_STRLCPY 1 /* + * Define if the open_memstream() function exists on the system. + */ +/* #define HAVE_OPEN_MEMSTREAM 1 */ + +/* + * Define if the BSD funopen() function exists on the system. + */ +#define HAVE_FUNOPEN 1 + +/* * Define if prctl() exists */ /* #define HAVE_PRCTL 1 */ diff --git a/include/arch/linux-arm/AndroidConfig.h b/include/arch/linux-arm/AndroidConfig.h index 26547a2..f51ddb1 100644 --- a/include/arch/linux-arm/AndroidConfig.h +++ b/include/arch/linux-arm/AndroidConfig.h @@ -298,6 +298,16 @@ #define HAVE_STRLCPY 1 /* + * Define if the open_memstream() function exists on the system. + */ +/* #define HAVE_OPEN_MEMSTREAM 1 */ + +/* + * Define if the BSD funopen() function exists on the system. + */ +#define HAVE_FUNOPEN 1 + +/* * Define if prctl() exists */ #define HAVE_PRCTL 1 diff --git a/include/arch/linux-sh/AndroidConfig.h b/include/arch/linux-sh/AndroidConfig.h index 67ac277..5e93990 100644 --- a/include/arch/linux-sh/AndroidConfig.h +++ b/include/arch/linux-sh/AndroidConfig.h @@ -303,6 +303,16 @@ #define HAVE_STRLCPY 1 /* + * Define if the open_memstream() function exists on the system. + */ +/* #define HAVE_OPEN_MEMSTREAM 1 */ + +/* + * Define if the BSD funopen() function exists on the system. + */ +#define HAVE_FUNOPEN 1 + +/* * Define if prctl() exists */ #define HAVE_PRCTL 1 diff --git a/include/arch/linux-x86/AndroidConfig.h b/include/arch/linux-x86/AndroidConfig.h index 31bdb5f..b0fe90a 100644 --- a/include/arch/linux-x86/AndroidConfig.h +++ b/include/arch/linux-x86/AndroidConfig.h @@ -279,6 +279,16 @@ /* #define HAVE_STRLCPY 1 */ /* + * Define if the open_memstream() function exists on the system. + */ +#define HAVE_OPEN_MEMSTREAM 1 + +/* + * Define if the BSD funopen() function exists on the system. + */ +/* #define HAVE_FUNOPEN 1 */ + +/* * Define if prctl() exists */ #define HAVE_PRCTL 1 diff --git a/include/arch/target_linux-x86/AndroidConfig.h b/include/arch/target_linux-x86/AndroidConfig.h index d89d054..4db3e72 100644 --- a/include/arch/target_linux-x86/AndroidConfig.h +++ b/include/arch/target_linux-x86/AndroidConfig.h @@ -289,6 +289,16 @@ #define HAVE_STRLCPY 1 /* + * Define if the open_memstream() function exists on the system. + */ +/* #define HAVE_OPEN_MEMSTREAM 1 */ + +/* + * Define if the BSD funopen() function exists on the system. + */ +#define HAVE_FUNOPEN 1 + +/* * Define if prctl() exists */ #define HAVE_PRCTL 1 diff --git a/include/arch/windows/AndroidConfig.h b/include/arch/windows/AndroidConfig.h index 0fc4955..806887b 100644 --- a/include/arch/windows/AndroidConfig.h +++ b/include/arch/windows/AndroidConfig.h @@ -272,6 +272,16 @@ /* #define HAVE_STRLCPY 1 */ /* + * Define if the open_memstream() function exists on the system. + */ +/* #define HAVE_OPEN_MEMSTREAM 1 */ + +/* + * Define if the BSD funopen() function exists on the system. + */ +/* #define HAVE_FUNOPEN 1 */ + +/* * Define if <winsock2.h> exists. * Only MinGW has it. */ @@ -286,7 +296,6 @@ */ #ifdef USE_MINGW #define S_IRGRP 0 -#define sleep _sleep #endif /* diff --git a/vold/volmgr_vfat.h b/include/cutils/iosched_policy.h index d9cf04d..07c5d1f 100644 --- a/vold/volmgr_vfat.h +++ b/include/cutils/iosched_policy.h @@ -1,6 +1,5 @@ - /* - * Copyright (C) 2008 The Android Open Source Project + * 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. @@ -15,15 +14,25 @@ * limitations under the License. */ -#ifndef _VOLMGR_VFAT_H -#define _VOLMGR_VFAT_H +#ifndef __CUTILS_IOSCHED_POLICY_H +#define __CUTILS_IOSCHED_POLICY_H -#include "volmgr.h" -#include "blkdev.h" +#ifdef __cplusplus +extern "C" { +#endif +typedef enum { + IoSchedClass_NONE, + IoSchedClass_RT, + IoSchedClass_BE, + IoSchedClass_IDLE, +} IoSchedClass; +extern int android_set_ioprio(int pid, IoSchedClass clazz, int ioprio); +extern int android_get_ioprio(int pid, IoSchedClass *clazz, int *ioprio); -int vfat_identify(blkdev_t *blkdev); -int vfat_check(blkdev_t *blkdev); -int vfat_mount(blkdev_t *blkdev, volume_t *vol, boolean safe_mode); +#ifdef __cplusplus +} #endif + +#endif /* __CUTILS_IOSCHED_POLICY_H */ diff --git a/include/cutils/log.h b/include/cutils/log.h index ec3cac8..dd47c35 100644 --- a/include/cutils/log.h +++ b/include/cutils/log.h @@ -196,6 +196,91 @@ extern "C" { #define IF_LOGE() IF_LOG(LOG_ERROR, LOG_TAG) #endif + +// --------------------------------------------------------------------- + +/* + * Simplified macro to send a verbose system log message using the current LOG_TAG. + */ +#ifndef SLOGV +#if LOG_NDEBUG +#define SLOGV(...) ((void)0) +#else +#define SLOGV(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) +#endif +#endif + +#define CONDITION(cond) (__builtin_expect((cond)!=0, 0)) + +#ifndef SLOGV_IF +#if LOG_NDEBUG +#define SLOGV_IF(cond, ...) ((void)0) +#else +#define SLOGV_IF(cond, ...) \ + ( (CONDITION(cond)) \ + ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)) \ + : (void)0 ) +#endif +#endif + +/* + * Simplified macro to send a debug system log message using the current LOG_TAG. + */ +#ifndef SLOGD +#define SLOGD(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) +#endif + +#ifndef SLOGD_IF +#define SLOGD_IF(cond, ...) \ + ( (CONDITION(cond)) \ + ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) \ + : (void)0 ) +#endif + +/* + * Simplified macro to send an info system log message using the current LOG_TAG. + */ +#ifndef SLOGI +#define SLOGI(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)) +#endif + +#ifndef SLOGI_IF +#define SLOGI_IF(cond, ...) \ + ( (CONDITION(cond)) \ + ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)) \ + : (void)0 ) +#endif + +/* + * Simplified macro to send a warning system log message using the current LOG_TAG. + */ +#ifndef SLOGW +#define SLOGW(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)) +#endif + +#ifndef SLOGW_IF +#define SLOGW_IF(cond, ...) \ + ( (CONDITION(cond)) \ + ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)) \ + : (void)0 ) +#endif + +/* + * Simplified macro to send an error system log message using the current LOG_TAG. + */ +#ifndef SLOGE +#define SLOGE(...) ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) +#endif + +#ifndef SLOGE_IF +#define SLOGE_IF(cond, ...) \ + ( (CONDITION(cond)) \ + ? ((void)__android_log_buf_print(LOG_ID_SYSTEM, ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) \ + : (void)0 ) +#endif + + + // --------------------------------------------------------------------- /* @@ -338,6 +423,21 @@ typedef enum { #define android_logToFile(tag, file) (0) #define android_logToFd(tag, fd) (0) +typedef enum { + LOG_ID_MAIN = 0, + LOG_ID_RADIO = 1, + LOG_ID_EVENTS = 2, + LOG_ID_SYSTEM = 3, + + LOG_ID_MAX +} log_id_t; + +/* + * Send a simple string to the log. + */ +int __android_log_buf_write(int bufID, int prio, const char *tag, const char *text); +int __android_log_buf_print(int bufID, int prio, const char *tag, const char *fmt, ...); + #ifdef __cplusplus } diff --git a/include/cutils/logger.h b/include/cutils/logger.h index 3a08019..b60f7ad 100644 --- a/include/cutils/logger.h +++ b/include/cutils/logger.h @@ -25,6 +25,7 @@ struct logger_entry { #define LOGGER_LOG_MAIN "log/main" #define LOGGER_LOG_RADIO "log/radio" #define LOGGER_LOG_EVENTS "log/events" +#define LOGGER_LOG_SYSTEM "log/system" #define LOGGER_ENTRY_MAX_LEN (4*1024) #define LOGGER_ENTRY_MAX_PAYLOAD \ diff --git a/include/cutils/logprint.h b/include/cutils/logprint.h index d6ec480..769c8a7 100644 --- a/include/cutils/logprint.h +++ b/include/cutils/logprint.h @@ -142,7 +142,7 @@ char *android_log_formatLogLine ( * Assumes single threaded execution * */ -int android_log_filterAndPrintLogLine( +int android_log_printLogLine( AndroidLogFormat *p_format, int fd, const AndroidLogEntry *entry); diff --git a/include/cutils/mspace.h b/include/cutils/mspace.h index 33410c1..e6e4047 100644 --- a/include/cutils/mspace.h +++ b/include/cutils/mspace.h @@ -80,6 +80,12 @@ mspace create_contiguous_mspace(size_t starting_capacity, size_t max_capacity, mspace create_contiguous_mspace_with_name(size_t starting_capacity, size_t max_capacity, int locked, const char *name); +/* + Identical to create_contiguous_mspace, but uses previously mapped memory. +*/ +mspace create_contiguous_mspace_with_base(size_t starting_capacity, + size_t max_capacity, int locked, void *base); + size_t destroy_contiguous_mspace(mspace msp); #endif diff --git a/include/cutils/adb_networking.h b/include/cutils/open_memstream.h index 409d577..b7998be 100755..100644 --- a/include/cutils/adb_networking.h +++ b/include/cutils/open_memstream.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006 The Android Open Source Project + * Copyright (C) 2010 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. @@ -14,22 +14,23 @@ * limitations under the License. */ -#ifndef _ADB_NETWORKING_H -#define _ADB_NETWORKING_H 1 -#include <netinet/in.h> -#include <arpa/inet.h> -#include <sys/socket.h> +#ifndef __CUTILS_OPEN_MEMSTREAM_H__ +#define __CUTILS_OPEN_MEMSTREAM_H__ + +#include <stdio.h> + +#ifndef HAVE_OPEN_MEMSTREAM #ifdef __cplusplus extern "C" { #endif -extern int adb_networking_connect_fd(int fd, struct sockaddr_in *p_address); -extern int adb_networking_gethostbyname(const char *name, struct in_addr *p_out_addr); +FILE* open_memstream(char** bufp, size_t* sizep); #ifdef __cplusplus } #endif -#endif /*_ADB_NETWORKING_H*/ +#endif /*!HAVE_OPEN_MEMSTREAM*/ +#endif /*__CUTILS_OPEN_MEMSTREAM_H__*/ diff --git a/include/diskconfig/diskconfig.h b/include/diskconfig/diskconfig.h new file mode 100644 index 0000000..d4f468c --- /dev/null +++ b/include/diskconfig/diskconfig.h @@ -0,0 +1,129 @@ +/* system/core/include/diskconfig/diskconfig.h + * + * Copyright 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 __LIBS_DISKCONFIG_H +#define __LIBS_DISKCONFIG_H + +#include <stdint.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#define MAX_NAME_LEN 512 +#define MAX_NUM_PARTS 16 + +/* known partition schemes */ +#define PART_SCHEME_MBR 0x1 +#define PART_SCHEME_GPT 0x2 + +/* PC Bios partition status */ +#define PC_PART_ACTIVE 0x80 +#define PC_PART_NORMAL 0x0 + +/* Known (rather, used by us) partition types */ +#define PC_PART_TYPE_LINUX 0x83 +#define PC_PART_TYPE_EXTENDED 0x05 +#define PC_PART_TYPE_FAT32 0x0c + +#define PC_NUM_BOOT_RECORD_PARTS 4 + +#define PC_EBR_LOGICAL_PART 0 +#define PC_EBR_NEXT_PTR_PART 1 + +#define PC_BIOS_BOOT_SIG 0xAA55 + +#define PC_MBR_DISK_OFFSET 0 +#define PC_MBR_SIZE 512 + +#define PART_ACTIVE_FLAG 0x1 + +struct chs { + uint8_t head; + uint8_t sector; + uint8_t cylinder; +} __attribute__((__packed__)); + +/* 16 byte pc partition descriptor that sits in MBR and EPBR. + * Note: multi-byte entities have little-endian layout on disk */ +struct pc_partition { + uint8_t status; /* byte 0 */ + struct chs start; /* bytes 1-3 */ + uint8_t type; /* byte 4 */ + struct chs end; /* bytes 5-7 */ + uint32_t start_lba; /* bytes 8-11 */ + uint32_t len_lba; /* bytes 12-15 */ +} __attribute__((__packed__)); + +struct pc_boot_record { + uint8_t code[440]; /* bytes 0-439 */ + uint32_t disk_sig; /* bytes 440-443 */ + uint16_t pad; /* bytes 444-445 */ + struct pc_partition ptable[PC_NUM_BOOT_RECORD_PARTS]; /* bytes 446-509 */ + uint16_t mbr_sig; /* bytes 510-511 */ +} __attribute__((__packed__)); + +struct part_info { + char *name; + uint8_t flags; + uint8_t type; + uint32_t len_kb; /* in 1K-bytes */ + uint32_t start_lba; /* the LBA where this partition begins */ +}; + +struct disk_info { + char *device; + uint8_t scheme; + int sect_size; /* expected sector size in bytes. MUST BE POWER OF 2 */ + uint32_t skip_lba; /* in sectors (1 unit of LBA) */ + uint32_t num_lba; /* the size of the disk in LBA units */ + struct part_info *part_lst; + int num_parts; +}; + +struct write_list { + struct write_list *next; + loff_t offset; + uint32_t len; + uint8_t data[0]; +}; + + +struct write_list *alloc_wl(uint32_t data_len); +void free_wl(struct write_list *item); +struct write_list *wlist_add(struct write_list **lst, struct write_list *item); +void wlist_free(struct write_list *lst); +int wlist_commit(int fd, struct write_list *lst, int test); + +struct disk_info *load_diskconfig(const char *fn, char *path_override); +int dump_disk_config(struct disk_info *dinfo); +int apply_disk_config(struct disk_info *dinfo, int test); +char *find_part_device(struct disk_info *dinfo, const char *name); +int process_disk_config(struct disk_info *dinfo); +struct part_info *find_part(struct disk_info *dinfo, const char *name); + +int write_raw_image(const char *dst, const char *src, loff_t offset, int test); + +/* For MBR partition schemes */ +struct write_list *config_mbr(struct disk_info *dinfo); +char *find_mbr_part(struct disk_info *dinfo, const char *name); + +#ifdef __cplusplus +} +#endif + +#endif /* __LIBS_DISKCONFIG_H */ diff --git a/include/pixelflinger/format.h b/include/pixelflinger/format.h index 6b2050c..82eeca4 100644 --- a/include/pixelflinger/format.h +++ b/include/pixelflinger/format.h @@ -39,19 +39,25 @@ enum GGLPixelFormat { GGL_PIXEL_FORMAT_LA_88 = 0xA, // 16-bit LA GGL_PIXEL_FORMAT_RGB_332 = 0xB, // 8-bit RGB (non paletted) - // YCbCr formats (SP=semi-planar, P=planar) - GGL_PIXEL_FORMAT_YCbCr_422_SP= 0x10, - GGL_PIXEL_FORMAT_YCbCr_420_SP= 0x11, - GGL_PIXEL_FORMAT_YCbCr_422_P = 0x12, - GGL_PIXEL_FORMAT_YCbCr_420_P = 0x13, - GGL_PIXEL_FORMAT_YCbCr_422_I = 0x14, - GGL_PIXEL_FORMAT_YCbCr_420_I = 0x15, + // reserved range. don't use. + GGL_PIXEL_FORMAT_RESERVED_10 = 0x10, + GGL_PIXEL_FORMAT_RESERVED_11 = 0x11, + GGL_PIXEL_FORMAT_RESERVED_12 = 0x12, + GGL_PIXEL_FORMAT_RESERVED_13 = 0x13, + GGL_PIXEL_FORMAT_RESERVED_14 = 0x14, + GGL_PIXEL_FORMAT_RESERVED_15 = 0x15, + GGL_PIXEL_FORMAT_RESERVED_16 = 0x16, + GGL_PIXEL_FORMAT_RESERVED_17 = 0x17, // reserved/special formats GGL_PIXEL_FORMAT_Z_16 = 0x18, GGL_PIXEL_FORMAT_S_8 = 0x19, GGL_PIXEL_FORMAT_SZ_24 = 0x1A, GGL_PIXEL_FORMAT_SZ_8 = 0x1B, + + // reserved range. don't use. + GGL_PIXEL_FORMAT_RESERVED_20 = 0x20, + GGL_PIXEL_FORMAT_RESERVED_21 = 0x21, }; enum GGLFormatComponents { @@ -62,10 +68,6 @@ enum GGLFormatComponents { GGL_RGBA = 0x1908, GGL_LUMINANCE = 0x1909, GGL_LUMINANCE_ALPHA = 0x190A, - GGL_Y_CB_CR_SP = 0x8000, - GGL_Y_CB_CR = GGL_Y_CB_CR_SP, - GGL_Y_CB_CR_P = 0x8001, - GGL_Y_CB_CR_I = 0x8002, }; enum GGLFormatComponentIndex { diff --git a/include/private/android_filesystem_config.h b/include/private/android_filesystem_config.h index 535f98c..1dbe171 100644 --- a/include/private/android_filesystem_config.h +++ b/include/private/android_filesystem_config.h @@ -158,9 +158,11 @@ static struct fs_path_config android_files[] = { { 00550, AID_ROOT, AID_SHELL, "system/etc/init.testmenu" }, { 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/main.conf" }, - { 00440, AID_BLUETOOTH, AID_BLUETOOTH, "system/etc/bluez/input.conf" }, - { 00440, AID_BLUETOOTH, AID_BLUETOOTH, "system/etc/bluez/audio.conf" }, + { 00440, AID_BLUETOOTH, AID_BLUETOOTH, "system/etc/bluetooth/main.conf" }, + { 00440, AID_BLUETOOTH, AID_BLUETOOTH, "system/etc/bluetooth/input.conf" }, + { 00440, AID_BLUETOOTH, AID_BLUETOOTH, "system/etc/bluetooth/audio.conf" }, + { 00444, AID_NET_BT, AID_NET_BT, "system/etc/bluetooth/blacklist.conf" }, + { 00640, AID_SYSTEM, AID_SYSTEM, "system/etc/bluetooth/auto_pairing.conf" }, { 00444, AID_RADIO, AID_AUDIO, "system/etc/AudioPara4.csv" }, { 00555, AID_ROOT, AID_ROOT, "system/etc/ppp/*" }, { 00644, AID_SYSTEM, AID_SYSTEM, "data/app/*" }, @@ -169,14 +171,18 @@ static struct fs_path_config android_files[] = { /* the following two files are INTENTIONALLY set-gid and not set-uid. * Do not change. */ { 02755, AID_ROOT, AID_NET_RAW, "system/bin/ping" }, - { 02755, AID_ROOT, AID_INET, "system/bin/netcfg" }, - /* the following four files are INTENTIONALLY set-uid, but they + { 02750, AID_ROOT, AID_INET, "system/bin/netcfg" }, + /* the following five files are INTENTIONALLY set-uid, but they * are NOT included on user builds. */ { 06755, AID_ROOT, AID_ROOT, "system/xbin/su" }, { 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" }, + { 04770, AID_ROOT, AID_RADIO, "system/bin/pppd-ril" }, + /* the following file is INTENTIONALLY set-uid, and IS included + * in user builds. */ + { 06750, AID_ROOT, AID_SHELL, "system/bin/run-as" }, { 00755, AID_ROOT, AID_SHELL, "system/bin/*" }, { 00755, AID_ROOT, AID_SHELL, "system/xbin/*" }, { 00750, AID_ROOT, AID_SHELL, "sbin/*" }, diff --git a/include/private/pixelflinger/ggl_context.h b/include/private/pixelflinger/ggl_context.h index 8a36fa9..2d7fdcf 100644 --- a/include/private/pixelflinger/ggl_context.h +++ b/include/private/pixelflinger/ggl_context.h @@ -285,8 +285,7 @@ struct clear_state_t { }; struct fog_state_t { - uint8_t color[3]; - uint8_t reserved; + uint8_t color[4]; }; struct logic_op_state_t { diff --git a/include/sysutils/FrameworkListener.h b/include/sysutils/FrameworkListener.h index 4e3d396..142f50c 100644 --- a/include/sysutils/FrameworkListener.h +++ b/include/sysutils/FrameworkListener.h @@ -23,7 +23,7 @@ class SocketClient; class FrameworkListener : public SocketListener { public: - static const int CMD_ARGS_MAX = 8; + static const int CMD_ARGS_MAX = 16; private: FrameworkCommandCollection *mCommands; diff --git a/include/sysutils/NetlinkEvent.h b/include/sysutils/NetlinkEvent.h index 95e83a3..b329b09 100644 --- a/include/sysutils/NetlinkEvent.h +++ b/include/sysutils/NetlinkEvent.h @@ -39,6 +39,8 @@ public: const char *getSubsystem() { return mSubsystem; } int getAction() { return mAction; } + + void dump(); }; #endif diff --git a/init/devices.c b/init/devices.c index 401e254..8789b89 100644 --- a/init/devices.c +++ b/init/devices.c @@ -308,8 +308,15 @@ static void make_device(const char *path, int block, int major, int minor) mode = get_device_perm(path, &uid, &gid) | (block ? S_IFBLK : S_IFCHR); dev = (major << 8) | minor; + /* Temporarily change egid to avoid race condition setting the gid of the + * device node. Unforunately changing the euid would prevent creation of + * some device nodes, so the uid has to be set with chown() and is still + * racy. Fixing the gid race at least fixed the issue with system_server + * opening dynamic input devices under the AID_INPUT gid. */ + setegid(gid); mknod(path, mode, dev); - chown(path, uid, gid); + chown(path, uid, -1); + setegid(AID_ROOT); } #if LOG_UEVENTS diff --git a/init/init.c b/init/init.c index f76eb36..4d98cc2 100755 --- a/init/init.c +++ b/init/init.c @@ -35,6 +35,7 @@ #include <sys/reboot.h> #include <cutils/sockets.h> +#include <cutils/iosched_policy.h> #include <termios.h> #include <linux/kd.h> #include <linux/keychord.h> @@ -224,6 +225,13 @@ void service_start(struct service *svc, const char *dynamic_args) } } + if (svc->ioprio_class != IoSchedClass_NONE) { + if (android_set_ioprio(getpid(), svc->ioprio_class, svc->ioprio_pri)) { + ERROR("Failed to set pid %d ioprio = %d,%d: %s\n", + getpid(), svc->ioprio_class, svc->ioprio_pri, strerror(errno)); + } + } + if (needs_console) { setsid(); open_console(); @@ -767,21 +775,31 @@ int open_keychord() void handle_keychord(int fd) { struct service *svc; + char* debuggable; + char* adb_enabled; int ret; __u16 id; - ret = read(fd, &id, sizeof(id)); - if (ret != sizeof(id)) { - ERROR("could not read keychord id\n"); - return; - } + // only handle keychords if ro.debuggable is set or adb is enabled. + // the logic here is that bugreports should be enabled in userdebug or eng builds + // and on user builds for users that are developers. + debuggable = property_get("ro.debuggable"); + adb_enabled = property_get("init.svc.adbd"); + if ((debuggable && !strcmp(debuggable, "1")) || + (adb_enabled && !strcmp(adb_enabled, "running"))) { + 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, NULL); - } else { - ERROR("service for keychord %d not found\n", id); + svc = service_find_by_keychord(id); + if (svc) { + INFO("starting service %s from keychord\n", svc->name); + service_start(svc, NULL); + } else { + ERROR("service for keychord %d not found\n", id); + } } } @@ -853,10 +871,7 @@ int main(int argc, char **argv) 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(); - } + keychord_fd = open_keychord(); if (console[0]) { snprintf(tmp, sizeof(tmp), "/dev/%s", console); diff --git a/init/init.h b/init/init.h index 60c3055..f92a4d7 100644 --- a/init/init.h +++ b/init/init.h @@ -114,7 +114,7 @@ struct svcenvinfo { #define SVC_CONSOLE 0x10 /* requires console */ #define SVC_CRITICAL 0x20 /* will reboot into recovery if keeps crashing */ -#define NR_SVC_SUPP_GIDS 6 /* six supplementary groups */ +#define NR_SVC_SUPP_GIDS 12 /* twelve supplementary groups */ #define SVC_MAXARGS 64 @@ -146,6 +146,9 @@ struct service { int nkeycodes; int keychord_id; + int ioprio_class; + int ioprio_pri; + int nargs; /* "MUST BE AT THE END OF THE STRUCT" */ char *args[1]; diff --git a/init/keywords.h b/init/keywords.h index 308118e..254c785 100644 --- a/init/keywords.h +++ b/init/keywords.h @@ -75,6 +75,7 @@ enum { KEYWORD(chmod, COMMAND, 2, do_chmod) KEYWORD(loglevel, COMMAND, 1, do_loglevel) KEYWORD(device, COMMAND, 4, do_device) + KEYWORD(ioprio, OPTION, 0, 0) #ifdef __MAKE_KEYWORD_ENUM__ KEYWORD_COUNT, }; diff --git a/init/parser.c b/init/parser.c index 54622cc..7da0d19 100644 --- a/init/parser.c +++ b/init/parser.c @@ -10,6 +10,8 @@ #include "init.h" #include "property_service.h" +#include <cutils/iosched_policy.h> + #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_ #include <sys/_system_properties.h> @@ -155,6 +157,7 @@ int lookup_keyword(const char *s) if (!strcmp(s, "ostname")) return K_hostname; break; case 'i': + if (!strcmp(s, "oprio")) return K_ioprio; if (!strcmp(s, "fup")) return K_ifup; if (!strcmp(s, "nsmod")) return K_insmod; if (!strcmp(s, "mport")) return K_import; @@ -619,6 +622,8 @@ static void parse_line_service(struct parse_state *state, int nargs, char **args return; } + svc->ioprio_class = IoSchedClass_NONE; + kw = lookup_keyword(args[0]); switch (kw) { case K_capability: @@ -636,6 +641,28 @@ static void parse_line_service(struct parse_state *state, int nargs, char **args case K_disabled: svc->flags |= SVC_DISABLED; break; + case K_ioprio: + if (nargs != 3) { + parse_error(state, "ioprio optin usage: ioprio <rt|be|idle> <ioprio 0-7>\n"); + } else { + svc->ioprio_pri = strtoul(args[2], 0, 8); + + if (svc->ioprio_pri < 0 || svc->ioprio_pri > 7) { + parse_error(state, "priority value must be range 0 - 7\n"); + break; + } + + if (!strcmp(args[1], "rt")) { + svc->ioprio_class = IoSchedClass_RT; + } else if (!strcmp(args[1], "be")) { + svc->ioprio_class = IoSchedClass_BE; + } else if (!strcmp(args[1], "idle")) { + svc->ioprio_class = IoSchedClass_IDLE; + } else { + parse_error(state, "ioprio option usage: ioprio <rt|be|idle> <0-7>\n"); + } + } + break; case K_group: if (nargs < 2) { parse_error(state, "group option requires a group id\n"); diff --git a/init/property_service.c b/init/property_service.c index 7db7c2c..d2505dd 100644 --- a/init/property_service.c +++ b/init/property_service.c @@ -77,6 +77,7 @@ struct { { "service.adb.root", AID_SHELL, 0 }, { "persist.sys.", AID_SYSTEM, 0 }, { "persist.service.", AID_SYSTEM, 0 }, + { "persist.security.", AID_SYSTEM, 0 }, { NULL, 0, 0 } }; diff --git a/libacc/Android.mk b/libacc/Android.mk index 2b4998e..5101e16 100644 --- a/libacc/Android.mk +++ b/libacc/Android.mk @@ -11,7 +11,7 @@ LOCAL_SHARED_LIBRARIES := libdl libcutils include $(BUILD_SHARED_LIBRARY) -# Shared library for host +# Static library for host # ======================================================== include $(CLEAR_VARS) @@ -23,7 +23,7 @@ LOCAL_CFLAGS := -O0 -g LOCAL_STATIC_LIBRARIES := libcutils LOCAL_LDLIBS := -ldl -include $(BUILD_HOST_SHARED_LIBRARY) +include $(BUILD_HOST_STATIC_LIBRARY) # Build children # ======================================================== diff --git a/libacc/FEATURES b/libacc/FEATURES index 97a876d..20f9d98 100644 --- a/libacc/FEATURES +++ b/libacc/FEATURES @@ -21,7 +21,7 @@ Supported C language subset: * Pointer indirection ('*') is supported. - * Square brackets can be used for pointer arithmetic. + * Square brackets are supported. * '=' and <op>= are supported. @@ -37,11 +37,14 @@ Supported C language subset: + variables can be initialized in declarations. + Only ANSI-style function declarations are supported. - "..." is not supported. - - short is not supported + - short is supported - const is not supported - - arrays are not supported + - signed and unsigned are not supported. + - arrays are supported - long doubles are not supported - - structs are not supported + - structs and unions are supported + - typedef is supported + - explicit storage class specifiers are not supported: register, auto, static, extern - Unknown functions and variables are bound at compile time by calling back to the caller. For the 'acc' command-line tool unknown functions @@ -66,9 +69,12 @@ Supported C language subset: - Float and double constants are supported. - - '#define' is supported without function like arguments. No macro - recursion is tolerated. Other preprocessor directives are - ignored. + - '#define' is supported without function like arguments. + - Macro recursion is allowed. + - Self-referential macros are handled as in gcc. + - '#pragma' is supported. The pragma text is passed to a callback function, + and is used to implement meta-information. + - Other preprocessor directives are ignored. - C Strings and C character constants are supported. All ANSI C character escapes are supported. diff --git a/libacc/acc.cpp b/libacc/acc.cpp index 808752e..8f33b0b 100644 --- a/libacc/acc.cpp +++ b/libacc/acc.cpp @@ -82,9 +82,7 @@ template<class E> class Vector { ~Vector() { if (mpBase) { - for(size_t i = 0; i < mUsed; i++) { - mpBase[mUsed].~E(); - } + clear(); free(mpBase); } } @@ -110,10 +108,20 @@ template<class E> class Vector { * ensure(1) = item; } - size_t size() { + inline size_t size() { return mUsed; } + void clear() { + if (mpBase) { + size_t used = mUsed; + for(size_t i = 0; i < used; i++) { + mpBase[i].~E(); + } + } + mUsed = 0; + } + private: E* ensure(int n) { size_t newUsed = mUsed + n; @@ -151,6 +159,7 @@ public: class Compiler : public ErrorSink { typedef int tokenid_t; enum TypeTag { + TY_UNKNOWN = -1, TY_INT, // 0 TY_CHAR, // 1 TY_SHORT, // 2 @@ -164,8 +173,18 @@ class Compiler : public ErrorSink { TY_PARAM // 10 }; + enum StorageClass { + SC_DEFAULT, // 0 + SC_AUTO, // 1 + SC_REGISTER, // 2 + SC_STATIC, // 3 + SC_EXTERN, // 4 + SC_TYPEDEF // 5 + }; + struct Type { TypeTag tag; + StorageClass storageClass; tokenid_t id; // For function arguments, global vars, local vars, struct elements tokenid_t structTag; // For structs the name of the struct int length; // length of array, offset of struct element. -1 means struct is forward defined @@ -3898,6 +3917,16 @@ class Compiler : public ErrorSink { Vector<Mark> mLevelStack; }; + struct MacroState { + tokenid_t name; // Name of the current macro we are expanding + char* dptr; // point to macro text during macro playback + int dch; // Saves old value of ch during a macro playback + }; + +#define MACRO_NESTING_MAX 32 + MacroState macroState[MACRO_NESTING_MAX]; + int macroLevel; // -1 means not playing any macro. + int ch; // Current input character, or EOF tokenid_t tok; // token intptr_t tokc; // token extra info @@ -3909,8 +3938,6 @@ class Compiler : public ErrorSink { char* glo; // global variable index String mTokenString; bool mbSuppressMacroExpansion; - char* dptr; // Macro state: Points to macro text during macro playback. - int dch; // Macro state: Saves old value of ch during a macro playback. char* pGlobalBase; ACCSymbolLookupFn mpSymbolLookupFn; void* mpSymbolLookupContext; @@ -4018,9 +4045,6 @@ class Compiler : public ErrorSink { static const int LOCAL = 0x200; - static const int SYM_FORWARD = 0; - static const int SYM_DEFINE = 1; - /* tokens in string heap */ static const int TAG_TOK = ' '; @@ -4102,11 +4126,17 @@ class Compiler : public ErrorSink { } void inp() { - if (dptr) { - ch = *dptr++; + // Close any totally empty macros. We leave them on the stack until now + // so that we know which macros are being expanded when checking if the + // last token in the macro is a macro that's already being expanded. + while (macroLevel >= 0 && macroState[macroLevel].dptr == NULL) { + macroLevel--; + } + if (macroLevel >= 0) { + ch = *macroState[macroLevel].dptr++; if (ch == 0) { - dptr = 0; - ch = dch; + ch = macroState[macroLevel].dch; + macroState[macroLevel].dptr = NULL; // This macro's done } } else { if (mbBumpLine) { @@ -4271,6 +4301,15 @@ class Compiler : public ErrorSink { // fprintf(stderr, "float constant: %s (%d) %g\n", pText, tok, tokd); } + bool currentlyBeingExpanded(tokenid_t id) { + for (int i = 0; i <= macroLevel; i++) { + if (macroState[macroLevel].name == id) { + return true; + } + } + return false; + } + void next() { int l, a; @@ -4352,12 +4391,22 @@ class Compiler : public ErrorSink { if (! mbSuppressMacroExpansion) { // Is this a macro? char* pMacroDefinition = mTokenTable[tok].mpMacroDefinition; - if (pMacroDefinition) { + if (pMacroDefinition && !currentlyBeingExpanded(tok)) { // Yes, it is a macro - dptr = pMacroDefinition; - dch = ch; - inp(); - next(); +#if 0 + printf("Expanding macro %s -> %s", + mTokenString.getUnwrapped(), pMacroDefinition); +#endif + if (macroLevel >= MACRO_NESTING_MAX-1) { + error("Too many levels of macro recursion."); + } else { + macroLevel++; + macroState[macroLevel].name = tok; + macroState[macroLevel].dptr = pMacroDefinition; + macroState[macroLevel].dch = ch; + inp(); + next(); + } } } } else { @@ -4443,9 +4492,7 @@ class Compiler : public ErrorSink { next(); mbSuppressMacroExpansion = false; tokenid_t name = tok; - String* pName = new String(); if (ch == '(') { - delete pName; error("Defines with arguments not supported"); return; } @@ -4473,6 +4520,13 @@ class Compiler : public ErrorSink { memcpy(pDefn, value.getUnwrapped(), value.len()); pDefn[value.len()] = 0; mTokenTable[name].mpMacroDefinition = pDefn; +#if 0 + { + String buf; + decodeToken(buf, name, true); + fprintf(stderr, "define %s = \"%s\"\n", buf.getUnwrapped(), pDefn); + } +#endif } void doPragma() { @@ -4771,57 +4825,59 @@ class Compiler : public ErrorSink { Type* pDecl = NULL; VariableInfo* pVI = NULL; Type* pFn = pGen->getR0Type(); - assert(pFn->tag == TY_POINTER); - assert(pFn->pHead->tag == TY_FUNC); - pDecl = pFn->pHead; - pGen->pushR0(); - Type* pArgList = pDecl->pTail; - bool varArgs = pArgList == NULL; - /* push args and invert order */ - a = pGen->beginFunctionCallArguments(); - int l = 0; - int argCount = 0; - while (tok != ')' && tok != EOF) { - if (! varArgs && !pArgList) { - error("Unexpected argument."); - } - expr(); - pGen->forceR0RVal(); - Type* pTargetType; - if (pArgList) { - pTargetType = pArgList->pHead; - pArgList = pArgList->pTail; - } else { - // This is a ... function, just pass arguments in their - // natural type. - pTargetType = pGen->getR0Type(); - if (pTargetType->tag == TY_FLOAT) { - pTargetType = mkpDouble; - } else if (pTargetType->tag == TY_ARRAY) { - // Pass arrays by pointer. - pTargetType = pTargetType->pTail; + if (pFn->tag == TY_POINTER && pFn->pHead->tag == TY_FUNC) { + pDecl = pFn->pHead; + pGen->pushR0(); + Type* pArgList = pDecl->pTail; + bool varArgs = pArgList == NULL; + /* push args and invert order */ + a = pGen->beginFunctionCallArguments(); + int l = 0; + int argCount = 0; + while (tok != ')' && tok != EOF) { + if (! varArgs && !pArgList) { + error("Unexpected argument."); } + expr(); + pGen->forceR0RVal(); + Type* pTargetType; + if (pArgList) { + pTargetType = pArgList->pHead; + pArgList = pArgList->pTail; + } else { + // This is a ... function, just pass arguments in their + // natural type. + pTargetType = pGen->getR0Type(); + if (pTargetType->tag == TY_FLOAT) { + pTargetType = mkpDouble; + } else if (pTargetType->tag == TY_ARRAY) { + // Pass arrays by pointer. + pTargetType = pTargetType->pTail; + } + } + if (pTargetType->tag == TY_VOID) { + error("Can't pass void value for argument %d", + argCount + 1); + } else { + l += pGen->storeR0ToArg(l, pTargetType); + } + if (accept(',')) { + // fine + } else if ( tok != ')') { + error("Expected ',' or ')'"); + } + argCount += 1; } - if (pTargetType->tag == TY_VOID) { - error("Can't pass void value for argument %d", - argCount + 1); - } else { - l += pGen->storeR0ToArg(l, pTargetType); - } - if (accept(',')) { - // fine - } else if ( tok != ')') { - error("Expected ',' or ')'"); + if (! varArgs && pArgList) { + error("Expected more argument(s). Saw %d", argCount); } - argCount += 1; - } - if (! varArgs && pArgList) { - error("Expected more argument(s). Saw %d", argCount); + pGen->endFunctionCallArguments(pDecl, a, l); + skip(')'); + pGen->callIndirect(l, pDecl); + pGen->adjustStackAfterCall(pDecl, l, true); + } else { + error("Expected a function value to left of '('."); } - pGen->endFunctionCallArguments(pDecl, a, l); - skip(')'); - pGen->callIndirect(l, pDecl); - pGen->adjustStackAfterCall(pDecl, l, true); } else { break; } @@ -4957,11 +5013,11 @@ class Compiler : public ErrorSink { return pGen->gtst(0, 0); } - void block(intptr_t l, bool outermostFunctionBlock) { + void block(intptr_t* breakLabel, intptr_t continueAddress, bool outermostFunctionBlock) { intptr_t a, n, t; Type* pBaseType; - if ((pBaseType = acceptPrimitiveType())) { + if ((pBaseType = acceptPrimitiveType(true))) { /* declarations */ localDeclarations(pBaseType); } else if (tok == TOK_IF) { @@ -4969,12 +5025,12 @@ class Compiler : public ErrorSink { skip('('); a = test_expr(); skip(')'); - block(l, false); + block(breakLabel, continueAddress, false); if (tok == TOK_ELSE) { next(); n = pGen->gjmp(0); /* jmp */ pGen->gsym(a); - block(l, false); + block(breakLabel, continueAddress, false); pGen->gsym(n); /* patch else jmp */ } else { pGen->gsym(a); /* patch if test */ @@ -5004,7 +5060,7 @@ class Compiler : public ErrorSink { } } skip(')'); - block((intptr_t) &a, false); + block(&a, n, false); pGen->gjmp(n - pCodeBuf->getPC() - pGen->jumpOffset()); /* jmp */ pGen->gsym(a); } else if (tok == '{') { @@ -5013,7 +5069,7 @@ class Compiler : public ErrorSink { } next(); while (tok != '}' && tok != EOF) - block(l, false); + block(breakLabel, continueAddress, false); skip('}'); if (! outermostFunctionBlock) { mLocals.popLevel(); @@ -5035,7 +5091,17 @@ class Compiler : public ErrorSink { } rsym = pGen->gjmp(rsym); /* jmp */ } else if (accept(TOK_BREAK)) { - *(int *) l = pGen->gjmp(*(int *) l); + if (breakLabel) { + *breakLabel = pGen->gjmp(*breakLabel); + } else { + error("break statement must be within a for, do, while, or switch statement"); + } + } else if (accept(TOK_CONTINUE)) { + if (continueAddress) { + pGen->gjmp(continueAddress - pCodeBuf->getPC() - pGen->jumpOffset()); + } else { + error("continue statement must be within a for, do, or while statement"); + } } else if (tok != ';') commaExpr(); skip(';'); @@ -5067,9 +5133,10 @@ class Compiler : public ErrorSink { } Type* createType(TypeTag tag, Type* pHead, Type* pTail) { - assert(tag >= TY_INT && tag <= TY_PARAM); + assert(tag >= TY_UNKNOWN && tag <= TY_PARAM); Type* pType = (Type*) mpCurrentArena->alloc(sizeof(Type)); memset(pType, 0, sizeof(*pType)); + pType->storageClass = SC_DEFAULT; pType->tag = tag; pType->pHead = pHead; pType->pTail = pTail; @@ -5232,38 +5299,124 @@ class Compiler : public ErrorSink { fprintf(stderr, "%s\n", buffer.getUnwrapped()); } - Type* acceptPrimitiveType() { - Type* pType; - if (tok == TOK_INT) { - pType = mkpInt; - } else if (tok == TOK_SHORT) { - pType = mkpShort; - } else if (tok == TOK_CHAR) { - pType = mkpChar; - } else if (tok == TOK_VOID) { - pType = mkpVoid; - } else if (tok == TOK_FLOAT) { - pType = mkpFloat; - } else if (tok == TOK_DOUBLE) { - pType = mkpDouble; - } else if (tok == TOK_STRUCT || tok == TOK_UNION) { - return acceptStruct(); + void insertTypeSpecifier(Type** ppType, TypeTag tag) { + if (! *ppType) { + *ppType = createType(tag, NULL, NULL); } else { - return NULL; + if ((*ppType)->tag != TY_UNKNOWN) { + error("Only one type specifier allowed."); + } else { + (*ppType)->tag = tag; + } + } + } + + void insertStorageClass(Type** ppType, StorageClass storageClass) { + if (! *ppType) { + *ppType = createType(TY_UNKNOWN, NULL, NULL); + } + if ((*ppType)->storageClass != SC_DEFAULT) { + error("Only one storage class allowed."); + } else { + (*ppType)->storageClass = storageClass; + } + } + + Type* acceptPrimitiveType(bool allowStorageClass) { + Type* pType = NULL; + for (bool keepGoing = true; keepGoing;) { + switch(tok) { + case TOK_AUTO: + insertStorageClass(&pType, SC_AUTO); + break; + case TOK_REGISTER: + insertStorageClass(&pType, SC_REGISTER); + break; + case TOK_STATIC: + insertStorageClass(&pType, SC_STATIC); + break; + case TOK_EXTERN: + insertStorageClass(&pType, SC_EXTERN); + break; + case TOK_TYPEDEF: + insertStorageClass(&pType, SC_TYPEDEF); + break; + case TOK_INT: + insertTypeSpecifier(&pType, TY_INT); + break; + case TOK_SHORT: + insertTypeSpecifier(&pType, TY_SHORT); + break; + case TOK_CHAR: + insertTypeSpecifier(&pType, TY_CHAR); + break; + case TOK_VOID: + insertTypeSpecifier(&pType, TY_VOID); + break; + case TOK_FLOAT: + insertTypeSpecifier(&pType, TY_FLOAT); + break; + case TOK_DOUBLE: + insertTypeSpecifier(&pType, TY_DOUBLE); + break; + case TOK_STRUCT: + case TOK_UNION: + { + insertTypeSpecifier(&pType, TY_STRUCT); + bool isStruct = (tok == TOK_STRUCT); + next(); + pType = acceptStruct(pType, isStruct); + keepGoing = false; + } + break; + default: + // Is it a typedef? + if (isSymbol(tok)) { + VariableInfo* pV = VI(tok); + if (pV && pV->pType->storageClass == SC_TYPEDEF) { + if (! pType) { + pType = createType(TY_UNKNOWN, NULL, NULL); + } + StorageClass storageClass = pType->storageClass; + *pType = *pV->pType; + pType->storageClass = storageClass; + } else { + keepGoing = false; + } + } else { + keepGoing = false; + } + } + if (keepGoing) { + next(); + } + } + if (pType) { + if (pType->tag == TY_UNKNOWN) { + pType->tag = TY_INT; + } + if (allowStorageClass) { + switch(pType->storageClass) { + case SC_AUTO: error("auto not supported."); break; + case SC_REGISTER: error("register not supported."); break; + case SC_STATIC: error("static not supported."); break; + case SC_EXTERN: error("extern not supported."); break; + default: break; + } + } else { + if (pType->storageClass != SC_DEFAULT) { + error("An explicit storage class is not allowed in this type declaration"); + } + } } - next(); return pType; } - Type* acceptStruct() { - assert(tok == TOK_STRUCT || tok == TOK_UNION); - bool isStruct = tok == TOK_STRUCT; - next(); + Type* acceptStruct(Type* pStructType, bool isStruct) { tokenid_t structTag = acceptSymbol(); bool isDeclaration = accept('{'); bool fail = false; - Type* pStructType = createType(TY_STRUCT, NULL, NULL); if (structTag) { Token* pToken = &mTokenTable[structTag]; VariableInfo* pStructInfo = pToken->mpStructInfo; @@ -5292,9 +5445,11 @@ class Compiler : public ErrorSink { if (needToDeclare) { // This is a new struct name pToken->mpStructInfo = mpCurrentSymbolStack->addStructTag(structTag); + StorageClass storageClass = pStructType->storageClass; pStructType = createType(TY_STRUCT, NULL, NULL); pStructType->structTag = structTag; pStructType->pHead = pStructType; + pStructType->storageClass = storageClass; if (! isDeclaration) { // A forward declaration pStructType->length = -1; @@ -5312,7 +5467,7 @@ class Compiler : public ErrorSink { size_t structAlignment = 0; Type** pParamHolder = & pStructType->pHead->pTail; while (tok != '}' && tok != EOF) { - Type* pPrimitiveType = expectPrimitiveType(); + Type* pPrimitiveType = expectPrimitiveType(false); if (pPrimitiveType) { while (tok != ';' && tok != EOF) { Type* pItem = acceptDeclaration(pPrimitiveType, true, false); @@ -5375,6 +5530,7 @@ class Compiler : public ErrorSink { Type* acceptDeclaration(Type* pType, bool nameAllowed, bool nameRequired) { tokenid_t declName = 0; bool reportFailure = false; + StorageClass storageClass = pType->storageClass; pType = acceptDecl2(pType, declName, nameAllowed, nameRequired, reportFailure); if (declName) { @@ -5383,6 +5539,7 @@ class Compiler : public ErrorSink { pType = createType(pType->tag, pType->pHead, pType->pTail); *pType = *pOldType; pType->id = declName; + pType->storageClass = storageClass; } else if (nameRequired) { error("Expected a variable name"); } @@ -5407,7 +5564,7 @@ class Compiler : public ErrorSink { /* Used for accepting types that appear in casts */ Type* acceptCastTypeDeclaration() { - Type* pType = acceptPrimitiveType(); + Type* pType = acceptPrimitiveType(false); if (pType) { pType = acceptDeclaration(pType, false, false); } @@ -5495,7 +5652,7 @@ class Compiler : public ErrorSink { Type* pHead = NULL; Type* pTail = NULL; for(;;) { - Type* pBaseArg = acceptPrimitiveType(); + Type* pBaseArg = acceptPrimitiveType(false); if (pBaseArg) { Type* pArg = acceptDeclaration(pBaseArg, nameAllowed, false); if (pArg) { @@ -5516,8 +5673,8 @@ class Compiler : public ErrorSink { return pHead; } - Type* expectPrimitiveType() { - Type* pType = acceptPrimitiveType(); + Type* expectPrimitiveType(bool allowStorageClass) { + Type* pType = acceptPrimitiveType(allowStorageClass); if (!pType) { String buf; decodeToken(buf, tok, true); @@ -5585,7 +5742,7 @@ class Compiler : public ErrorSink { break; } // Else it's a forward declaration of a function. - } else { + } else if (pDecl->storageClass != SC_TYPEDEF) { int variableAddress = 0; size_t alignment = pGen->alignmentOf(pDecl); assert(alignment > 0); @@ -5610,7 +5767,7 @@ class Compiler : public ErrorSink { next(); } skip(';'); - pBaseType = acceptPrimitiveType(); + pBaseType = acceptPrimitiveType(true); } } @@ -5622,8 +5779,12 @@ class Compiler : public ErrorSink { if (token == EOF ) { buffer.printf("EOF"); } else if (token == TOK_NUM) { - buffer.printf("numeric constant"); - } else if (token >= 0 && token < 256) { + buffer.printf("numeric constant %d(0x%x)", tokc, tokc); + } else if (token == TOK_NUM_FLOAT) { + buffer.printf("numeric constant float %g", tokd); + } else if (token == TOK_NUM_DOUBLE) { + buffer.printf("numeric constant double %g", tokd); + } else if (token >= 0 && token < 256) { if (token < 32) { buffer.printf("'\\x%02x'", token); } else { @@ -5670,7 +5831,7 @@ class Compiler : public ErrorSink { void globalDeclarations() { mpCurrentSymbolStack = &mGlobals; while (tok != EOF) { - Type* pBaseType = expectPrimitiveType(); + Type* pBaseType = expectPrimitiveType(true); if (!pBaseType) { break; } @@ -5687,7 +5848,6 @@ class Compiler : public ErrorSink { skip(';'); continue; } - if (! isDefined(pDecl->id)) { addGlobalSymbol(pDecl); } @@ -5698,19 +5858,23 @@ class Compiler : public ErrorSink { if (pDecl->tag < TY_FUNC) { // it's a variable declaration for(;;) { - if (name && !name->pAddress) { - name->pAddress = (int*) allocGlobalSpace( - pGen->alignmentOf(name->pType), - pGen->sizeOf(name->pType)); - } - if (accept('=')) { - if (tok == TOK_NUM) { - if (name) { - * (int*) name->pAddress = tokc; + if (pDecl->storageClass == SC_TYPEDEF) { + // Do not allocate storage. + } else { + if (name && !name->pAddress) { + name->pAddress = (int*) allocGlobalSpace( + pGen->alignmentOf(name->pType), + pGen->sizeOf(name->pType)); + } + if (accept('=')) { + if (tok == TOK_NUM) { + if (name) { + * (int*) name->pAddress = tokc; + } + next(); + } else { + error("Expected an integer constant"); } - next(); - } else { - error("Expected an integer constant"); } } if (!accept(',')) { @@ -5763,7 +5927,7 @@ class Compiler : public ErrorSink { rsym = loc = 0; pReturnType = pDecl->pHead; a = pGen->functionEntry(pDecl); - block(0, true); + block(0, 0, true); pGen->gsym(rsym); pGen->functionExit(pDecl, a, loc); mLocals.popLevel(); @@ -5830,8 +5994,7 @@ class Compiler : public ErrorSink { rsym = 0; loc = 0; glo = 0; - dptr = 0; - dch = 0; + macroLevel = -1; file = 0; pGlobalBase = 0; pCodeBuf = 0; diff --git a/libacc/tests/Android.mk b/libacc/tests/Android.mk index e9fbe03..6ddfa74 100644 --- a/libacc/tests/Android.mk +++ b/libacc/tests/Android.mk @@ -8,9 +8,13 @@ LOCAL_MODULE:= acc LOCAL_SRC_FILES:= \ main.cpp -LOCAL_SHARED_LIBRARIES := \ - libacc +LOCAL_STATIC_LIBRARIES := \ + libacc \ + libcutils + +LOCAL_LDLIBS := -ldl + LOCAL_MODULE_TAGS := tests include $(BUILD_HOST_EXECUTABLE) @@ -25,7 +29,8 @@ LOCAL_SRC_FILES:= \ disassem.cpp LOCAL_SHARED_LIBRARIES := \ - libacc + libacc \ + libdl LOCAL_CFLAGS := -O0 -g @@ -41,8 +46,11 @@ LOCAL_MODULE:= accRuntimeTest LOCAL_SRC_FILES:= \ runtimeTest.cpp -LOCAL_SHARED_LIBRARIES := \ - libacc +LOCAL_STATIC_LIBRARIES := \ + libacc \ + libcutils + +LOCAL_LDLIBS := -ldl LOCAL_MODULE_TAGS := tests @@ -57,7 +65,8 @@ LOCAL_SRC_FILES:= \ runtimeTest.cpp LOCAL_SHARED_LIBRARIES := \ - libacc + libacc \ + libdl LOCAL_CFLAGS := -O0 -g diff --git a/libacc/tests/data/continue.c b/libacc/tests/data/continue.c new file mode 100644 index 0000000..d8b8e36 --- /dev/null +++ b/libacc/tests/data/continue.c @@ -0,0 +1,13 @@ +int main() { + int i, j, sum; + sum = 0; + for (i = 0; i < 10; i++) { + if (i & 1) continue; + for (j = 0; j < 10; j++) { + if (j & 1) continue; + sum += i * j; + } + } + return sum; +} + diff --git a/libacc/tests/data/macros.c b/libacc/tests/data/macros.c new file mode 100644 index 0000000..50e54dc --- /dev/null +++ b/libacc/tests/data/macros.c @@ -0,0 +1,10 @@ +#define A B + B +#define B C + +int main() { + int C = 3; + printf("A = %d\n", A); +#define C 5 + printf("A = %d\n", A); + return 0; +} diff --git a/libacc/tests/data/typedef.c b/libacc/tests/data/typedef.c new file mode 100644 index 0000000..c392f6a --- /dev/null +++ b/libacc/tests/data/typedef.c @@ -0,0 +1,40 @@ +typedef short COORD; +typedef struct Point { + COORD x; + COORD y; +} Point; + +void add(Point* result, Point* a, Point* b) { + result->x = a->x + b->x; + result->y = a->y + b->y; +} + +void print(Point* p) { + printf("(%d, %d)", p->x, p->y); +} + +void set(Point* p, int x, int y) { + p->x = x; + p->y = y; +} + +int main() { + typedef char* String; + String s = "x = %d\n"; + { + typedef int item; + item x = 3; + printf(s, x); + } + Point a, b, c; + set(&a, 1,2); + set(&b, 3,4); + add(&c, &a, &b); + print(&c); + printf(" = "); + print(&a); + printf(" + "); + print(&b); + printf("\n"); + return 0; +} diff --git a/libacc/tests/test.py b/libacc/tests/test.py index d984301..1b444c7 100644 --- a/libacc/tests/test.py +++ b/libacc/tests/test.py @@ -10,6 +10,7 @@ gArmInitialized = False gUseArm = True gUseX86 = True gRunOTCCOutput = True +gCompileOTCCANSI = True def parseArgv(): @@ -59,7 +60,12 @@ def outputCanRun(): def checkEnvironment(): global gRunOTCCOutput - gRunOTCCOutput = uname() == "Linux" and unameM() != "x86_64" and outputCanRun() + global gCompileOTCCANSI + osName = uname() + gRunOTCCOutput = osName == "Linux" and unameM() != "x86_64" and outputCanRun() + # OSX doesn't have stdin/stdout/stderr accessible through dll load symbols, so + # we can't compile the ANSI version of the OTCC compiler on OS X. + gCompileOTCCANSI = osName == "Linux" def adb(args): return runCmd(["adb"] + args) @@ -180,13 +186,19 @@ class TestACC(unittest.TestCase): def testCompileReturnVal(self): self.compileCheck(["data/returnval-ansi.c"], "") - def testCompileOTCCANSII(self): - self.compileCheck(["data/otcc-ansi.c"], "", "", ['x86']) + def testCompileOTCCANSI(self): + global gCompileOTCCANSI + if gCompileOTCCANSI: + self.compileCheck(["data/otcc-ansi.c"], "", "", ['x86']) def testRunReturnVal(self): self.compileCheck(["-R", "data/returnval-ansi.c"], "Executing compiled code:\nresult: 42\n") + def testContinue(self): + self.compileCheck(["-R", "data/continue.c"], + "Executing compiled code:\nresult: 400\n") + def testStringLiteralConcatenation(self): self.compileCheck(["-R", "data/testStringConcat.c"], "Executing compiled code:\nresult: 13\n", "Hello, world\n") @@ -311,6 +323,12 @@ Testing read/write (double*): 8.8 9.9 result: 0""", """a = 99, b = 41 ga = 100, gb = 44""") + def testTypedef(self): + self.compileCheck(["-R", "data/typedef.c"], """Executing compiled code: +result: 0""", """x = 3 +(4, 6) = (1, 2) + (3, 4) +""") + def testPointerArithmetic(self): self.compileCheck(["-R", "data/pointers.c"], """Executing compiled code: result: 0""", """Pointer difference: 1 4 @@ -373,6 +391,12 @@ result: 0""", """testing... Total bad: 0 """) + def testMacros(self): + self.compileCheck(["-R", "data/macros.c"], """Executing compiled code: +result: 0""", """A = 6 +A = 10 +""") + def testpointers2(self): self.compileCheck(["-R", "data/pointers2.c"], """Executing compiled code: result: 0""", """a = 0, *pa = 0 diff --git a/libcutils/Android.mk b/libcutils/Android.mk index 6418590..4c45cc9 100644 --- a/libcutils/Android.mk +++ b/libcutils/Android.mk @@ -31,13 +31,15 @@ commonSources := \ config_utils.c \ cpu_info.c \ load_file.c \ + open_memstream.c \ strdup16to8.c \ strdup8to16.c \ record_stream.c \ process_name.c \ properties.c \ threads.c \ - sched_policy.c + sched_policy.c \ + iosched_policy.c commonHostSources := \ ashmem-host.c @@ -65,7 +67,6 @@ else mspace.c \ selector.c \ tztime.c \ - adb_networking.c \ zygote.c commonHostSources += \ diff --git a/libcutils/adb_networking.c b/libcutils/adb_networking.c deleted file mode 100644 index d819d44..0000000 --- a/libcutils/adb_networking.c +++ /dev/null @@ -1,172 +0,0 @@ -/* libs/utils/adb_networking.c -** -** Copyright 2006, 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 ADB_PORT 5037 - -#define _GNU_SOURCE /* for asprintf */ -#include <stdio.h> -#include <unistd.h> -#include <stdlib.h> -#include <errno.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <string.h> - -#include <cutils/adb_networking.h> -#include <cutils/sockets.h> -#include <cutils/properties.h> - -#define ADB_RESPONSE_SIZE 4 - -/** - * Unfortunately, java.net.Socket wants to create it's filedescriptor early - * So, this function takes an fd that must be an unconnected - * PF_LOCAL SOCK_STREAM - */ -int adb_networking_connect_fd(int fd, struct sockaddr_in *p_address) -{ - struct sockaddr_in local_addr; - socklen_t alen; - char *cmd; - char buf[ADB_RESPONSE_SIZE + 1]; - ssize_t count_read; - int ret; - int err; - /* for impl of inet_ntoa below*/ - union { - uint8_t b[4]; - uint32_t l; - } a; - - /* First, connect to adb */ - - memset(&local_addr, 0, sizeof(local_addr)); - local_addr.sin_family = AF_INET; - local_addr.sin_port = htons(ADB_PORT); - local_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - - do { - err = connect(fd, (struct sockaddr *) &local_addr, sizeof(local_addr)); - } while (err < 0 && errno == EINTR); - - if (err < 0) { - return -1; - } - - a.l = p_address->sin_addr.s_addr; - - // compose the command - asprintf(&cmd, "tcp:%u:%u.%u.%u.%u", - (unsigned int)ntohs(p_address->sin_port), - a.b[0],a.b[1],a.b[2],a.b[3]); - - // buf is now the ascii hex length of cmd - snprintf(buf, sizeof(buf), "%04X", strlen(cmd)); - - // write the 4-byte length - do { - err = write(fd, buf, 4); - } while (err < 0 && errno == EINTR); - - // write the command - do { - err = write(fd, cmd, strlen(cmd)); - } while (err < 0 && errno == EINTR); - - // read the result - do { - count_read = read(fd, buf, sizeof(buf) - 1); - } while (count_read < 0 && errno != EINTR); - - if (count_read == ADB_RESPONSE_SIZE - && 0 == strncmp(buf, "OKAY", ADB_RESPONSE_SIZE)) { - ret = 0; - } else { - /* what errno here? <shrug? */ - errno = ENETUNREACH; - ret = -1; - } - - free(cmd); - - return ret; -} - -/** - * Fills in *p_out_addr and returns 0 on success - * Memset's *p_out_addr and returns -1 on fail - */ - -int adb_networking_gethostbyname(const char *name, struct in_addr *p_out_addr) -{ - int fd; - char *cmd = NULL; - char buf[ADB_RESPONSE_SIZE + 1]; - int err; - ssize_t count_read; - - fd = socket_loopback_client(ADB_PORT, SOCK_STREAM); - - if (fd < 0) { - return -1; - } - - // compose the command - asprintf(&cmd, "dns:%s", name); - - // buf is now the ascii hex length of cmd - snprintf(buf, sizeof(buf), "%04X", strlen(cmd)); - - // write the 4-byte length - do { - err = write(fd, buf, 4); - } while (err < 0 && errno == EINTR); - - // write the command - do { - err = write(fd, cmd, strlen(cmd)); - } while (err < 0 && errno == EINTR); - - // read the result - do { - count_read = read(fd, buf, ADB_RESPONSE_SIZE); - } while (count_read < 0 && errno != EINTR); - - if (count_read != ADB_RESPONSE_SIZE - || 0 != strncmp(buf, "OKAY", ADB_RESPONSE_SIZE)) { - goto error; - } - - // read the actual IP address - do { - count_read = read(fd, &(p_out_addr->s_addr), sizeof(p_out_addr->s_addr)); - } while (count_read < 0 && errno != EINTR); - - if (count_read != 4) { - goto error; - } - - free(cmd); - close(fd); - return 0; -error: - free(cmd); - close(fd); - memset(p_out_addr, 0, sizeof(struct in_addr)); - return -1; -} - diff --git a/libcutils/atomic-android-arm.S b/libcutils/atomic-android-arm.S index da5c26b..1dd2363 100644 --- a/libcutils/atomic-android-arm.S +++ b/libcutils/atomic-android-arm.S @@ -24,17 +24,25 @@ .align .global android_atomic_write + .type android_atomic_write, %function .global android_atomic_inc + .type android_atomic_inc, %function .global android_atomic_dec + .type android_atomic_dec, %function .global android_atomic_add + .type android_atomic_add, %function .global android_atomic_and + .type android_atomic_and, %function .global android_atomic_or + .type android_atomic_or, %function .global android_atomic_swap + .type android_atomic_swap, %function .global android_atomic_cmpxchg + .type android_atomic_cmpxchg, %function /* * ---------------------------------------------------------------------------- diff --git a/libcutils/atomic-android-armv6.S b/libcutils/atomic-android-armv6.S index a713089..1574c9c 100644 --- a/libcutils/atomic-android-armv6.S +++ b/libcutils/atomic-android-armv6.S @@ -19,17 +19,25 @@ .align .global android_atomic_write + .type android_atomic_write, %function .global android_atomic_inc + .type android_atomic_inc, %function .global android_atomic_dec + .type android_atomic_dec, %function .global android_atomic_add + .type android_atomic_add, %function .global android_atomic_and + .type android_atomic_and, %function .global android_atomic_or + .type android_atomic_or, %function .global android_atomic_swap + .type android_atomic_swap, %function .global android_atomic_cmpxchg + .type android_atomic_cmpxchg, %function diff --git a/libcutils/iosched_policy.c b/libcutils/iosched_policy.c new file mode 100644 index 0000000..f350f58 --- /dev/null +++ b/libcutils/iosched_policy.c @@ -0,0 +1,67 @@ + +/* libs/cutils/iosched_policy.c +** +** Copyright 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. +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <fcntl.h> + +#ifdef HAVE_SCHED_H + +#include <cutils/iosched_policy.h> + +extern int ioprio_set(int which, int who, int ioprio); + +enum { + WHO_PROCESS = 1, + WHO_PGRP, + WHO_USER, +}; + +#define CLASS_SHIFT 13 +#define IOPRIO_NORM 4 + +int android_set_ioprio(int pid, IoSchedClass clazz, int ioprio) { +#ifdef HAVE_ANDROID_OS + if (ioprio_set(WHO_PROCESS, pid, ioprio | (clazz << CLASS_SHIFT))) { + return -1; + } +#endif + return 0; +} + +int android_get_ioprio(int pid, IoSchedClass *clazz, int *ioprio) { +#ifdef HAVE_ANDROID_OS + int rc; + + if ((rc = ioprio_get(WHO_PROCESS, pid)) < 0) { + return -1; + } + + *clazz = (rc >> CLASS_SHIFT); + *ioprio = (rc & 0xff); +#else + *clazz = IoSchedClass_NONE; + *ioprio = 0; +#endif + return 0; +} + +#endif /* HAVE_SCHED_H */ diff --git a/libcutils/mspace.c b/libcutils/mspace.c index 8fd5de7..63b199d 100644 --- a/libcutils/mspace.c +++ b/libcutils/mspace.c @@ -134,67 +134,47 @@ assert(nb >= 0); //xxx deal with the trim case return oldbrk; } -mspace create_contiguous_mspace_with_name(size_t starting_capacity, - size_t max_capacity, int locked, char const * name) { - int fd, ret; +mspace create_contiguous_mspace_with_base(size_t starting_capacity, + size_t max_capacity, int locked, void *base) { struct mspace_contig_state *cs; - char buf[ASHMEM_NAME_LEN] = "mspace"; - void *base; unsigned int pagesize; mstate m; - if (starting_capacity > max_capacity) - return (mspace)0; - init_mparams(); pagesize = PAGESIZE; - - /* Create the anonymous memory that will back the mspace. - * This reserves all of the virtual address space we could - * ever need. Physical pages will be mapped as the memory - * is touched. - * - * Align max_capacity to a whole page. - */ - max_capacity = (size_t)ALIGN_UP(max_capacity, pagesize); - - if (name) - snprintf(buf, sizeof(buf), "mspace/%s", name); - fd = ashmem_create_region(buf, max_capacity); - if (fd < 0) - return (mspace)0; - - base = mmap(NULL, max_capacity, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); - close(fd); - if (base == MAP_FAILED) - return (mspace)0; - - /* Make sure that base is at the beginning of a page. - */ + assert(starting_capacity <= max_capacity); assert(((uintptr_t)base & (pagesize-1)) == 0); + assert(((uintptr_t)max_capacity & (pagesize-1)) == 0); + starting_capacity = (size_t)ALIGN_UP(starting_capacity, pagesize); - /* Reserve some space for the information that our MORECORE needs. + /* Make the first page read/write. dlmalloc needs to use that page. */ - cs = base; + if (mprotect(base, starting_capacity, PROT_READ | PROT_WRITE) < 0) { + goto error; + } - /* Create the mspace, pointing to the memory we just reserved. + /* Create the mspace, pointing to the memory given. */ - m = create_mspace_with_base(base + sizeof(*cs), starting_capacity, locked); - if (m == (mspace)0) + m = create_mspace_with_base((char *)base + sizeof(*cs), starting_capacity, + locked); + if (m == (mspace)0) { goto error; - - /* Make sure that m is in the same page as cs. + } + /* Make sure that m is in the same page as base. */ assert(((uintptr_t)m & (uintptr_t)~(pagesize-1)) == (uintptr_t)base); + /* Use some space for the information that our MORECORE needs. + */ + cs = (struct mspace_contig_state *)base; /* Find out exactly how much of the memory the mspace * is using. */ cs->brk = m->seg.base + m->seg.size; cs->top = (char *)base + max_capacity; + assert((char *)base <= cs->brk); assert(cs->brk <= cs->top); - /* Prevent access to the memory we haven't handed out yet. */ if (cs->brk != cs->top) { @@ -202,8 +182,10 @@ mspace create_contiguous_mspace_with_name(size_t starting_capacity, * for cs->brk not to be page-aligned at this point. */ char *prot_brk = (char *)ALIGN_UP(cs->brk, pagesize); - if (mprotect(prot_brk, cs->top - prot_brk, PROT_NONE) < 0) + if ((mprotect(base, prot_brk - (char *)base, PROT_READ | PROT_WRITE) < 0) || + (mprotect(prot_brk, cs->top - prot_brk, PROT_NONE) < 0)) { goto error; + } } cs->m = m; @@ -212,10 +194,56 @@ mspace create_contiguous_mspace_with_name(size_t starting_capacity, return (mspace)m; error: - munmap(base, max_capacity); return (mspace)0; } + +mspace create_contiguous_mspace_with_name(size_t starting_capacity, + size_t max_capacity, int locked, char const *name) { + int fd, ret; + char buf[ASHMEM_NAME_LEN] = "mspace"; + void *base; + unsigned int pagesize; + mstate m; + + if (starting_capacity > max_capacity) + return (mspace)0; + + init_mparams(); + pagesize = PAGESIZE; + + /* Create the anonymous memory that will back the mspace. + * This reserves all of the virtual address space we could + * ever need. Physical pages will be mapped as the memory + * is touched. + * + * Align max_capacity to a whole page. + */ + max_capacity = (size_t)ALIGN_UP(max_capacity, pagesize); + + if (name) + snprintf(buf, sizeof(buf), "mspace/%s", name); + fd = ashmem_create_region(buf, max_capacity); + if (fd < 0) + return (mspace)0; + + base = mmap(NULL, max_capacity, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); + close(fd); + if (base == MAP_FAILED) + return (mspace)0; + + /* Make sure that base is at the beginning of a page. + */ + assert(((uintptr_t)base & (pagesize-1)) == 0); + + m = create_contiguous_mspace_with_base(starting_capacity, max_capacity, + locked, base); + if (m == 0) { + munmap(base, max_capacity); + } + return m; +} + mspace create_contiguous_mspace(size_t starting_capacity, size_t max_capacity, int locked) { return create_contiguous_mspace_with_name(starting_capacity, diff --git a/libcutils/open_memstream.c b/libcutils/open_memstream.c new file mode 100644 index 0000000..5b4388a --- /dev/null +++ b/libcutils/open_memstream.c @@ -0,0 +1,381 @@ +/* + * Copyright (C) 2010 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 HAVE_OPEN_MEMSTREAM + +/* + * Implementation of the POSIX open_memstream() function, which Linux has + * but BSD lacks. + * + * Summary: + * - Works like a file-backed FILE* opened with fopen(name, "w"), but the + * backing is a chunk of memory rather than a file. + * - The buffer expands as you write more data. Seeking past the end + * of the file and then writing to it zero-fills the gap. + * - The values at "*bufp" and "*sizep" should be considered read-only, + * and are only valid immediately after an fflush() or fclose(). + * - A '\0' is maintained just past the end of the file. This is not included + * in "*sizep". (The behavior w.r.t. fseek() is not clearly defined. + * The spec says the null byte is written when a write() advances EOF, + * but it looks like glibc ensures the null byte is always found at EOF, + * even if you just seeked backwards. The example on the opengroup.org + * page suggests that this is the expected behavior. The null must be + * present after a no-op fflush(), which we can't see, so we have to save + * and restore it. Annoying, but allows file truncation.) + * - After fclose(), the caller must eventually free(*bufp). + * + * This is built out of funopen(), which BSD has but Linux lacks. There is + * no flush() operator, so we need to keep the user pointers up to date + * after each operation. + * + * I don't think Windows has any of the above, but we don't need to use + * them there, so we just supply a stub. + */ +#include <cutils/open_memstream.h> +#include <stdlib.h> +#include <sys/types.h> +#include <unistd.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <assert.h> + +#if 0 +# define DBUG(x) printf x +#else +# define DBUG(x) ((void)0) +#endif + +#ifdef HAVE_FUNOPEN + +/* + * Definition of a seekable, write-only memory stream. + */ +typedef struct { + char** bufp; /* pointer to buffer pointer */ + size_t* sizep; /* pointer to eof */ + + size_t allocSize; /* size of buffer */ + size_t eof; /* furthest point we've written to */ + size_t offset; /* current write offset */ + char saved; /* required by NUL handling */ +} MemStream; + +#define kInitialSize 1024 + +/* + * Ensure that we have enough storage to write "size" bytes at the + * current offset. We also have to take into account the extra '\0' + * that we maintain just past EOF. + * + * Returns 0 on success. + */ +static int ensureCapacity(MemStream* stream, int writeSize) +{ + DBUG(("+++ ensureCap off=%d size=%d\n", stream->offset, writeSize)); + + size_t neededSize = stream->offset + writeSize + 1; + if (neededSize <= stream->allocSize) + return 0; + + size_t newSize; + + if (stream->allocSize == 0) { + newSize = kInitialSize; + } else { + newSize = stream->allocSize; + newSize += newSize / 2; /* expand by 3/2 */ + } + + if (newSize < neededSize) + newSize = neededSize; + DBUG(("+++ realloc %p->%p to size=%d\n", + stream->bufp, *stream->bufp, newSize)); + char* newBuf = (char*) realloc(*stream->bufp, newSize); + if (newBuf == NULL) + return -1; + + *stream->bufp = newBuf; + stream->allocSize = newSize; + return 0; +} + +/* + * Write data to a memstream, expanding the buffer if necessary. + * + * If we previously seeked beyond EOF, zero-fill the gap. + * + * Returns the number of bytes written. + */ +static int write_memstream(void* cookie, const char* buf, int size) +{ + MemStream* stream = (MemStream*) cookie; + + if (ensureCapacity(stream, size) < 0) + return -1; + + /* seeked past EOF earlier? */ + if (stream->eof < stream->offset) { + DBUG(("+++ zero-fill gap from %d to %d\n", + stream->eof, stream->offset-1)); + memset(*stream->bufp + stream->eof, '\0', + stream->offset - stream->eof); + } + + /* copy data, advance write pointer */ + memcpy(*stream->bufp + stream->offset, buf, size); + stream->offset += size; + + if (stream->offset > stream->eof) { + /* EOF has advanced, update it and append null byte */ + DBUG(("+++ EOF advanced to %d, appending nul\n", stream->offset)); + assert(stream->offset < stream->allocSize); + stream->eof = stream->offset; + } else { + /* within previously-written area; save char we're about to stomp */ + DBUG(("+++ within written area, saving '%c' at %d\n", + *(*stream->bufp + stream->offset), stream->offset)); + stream->saved = *(*stream->bufp + stream->offset); + } + *(*stream->bufp + stream->offset) = '\0'; + *stream->sizep = stream->offset; + + return size; +} + +/* + * Seek within a memstream. + * + * Returns the new offset, or -1 on failure. + */ +static fpos_t seek_memstream(void* cookie, fpos_t offset, int whence) +{ + MemStream* stream = (MemStream*) cookie; + off_t newPosn = (off_t) offset; + + if (whence == SEEK_CUR) { + newPosn += stream->offset; + } else if (whence == SEEK_END) { + newPosn += stream->eof; + } + + if (newPosn < 0 || ((fpos_t)((size_t) newPosn)) != newPosn) { + /* bad offset - negative or huge */ + DBUG(("+++ bogus seek offset %ld\n", (long) newPosn)); + errno = EINVAL; + return (fpos_t) -1; + } + + if (stream->offset < stream->eof) { + /* + * We were pointing to an area we'd already written to, which means + * we stomped on a character and must now restore it. + */ + DBUG(("+++ restoring char '%c' at %d\n", + stream->saved, stream->offset)); + *(*stream->bufp + stream->offset) = stream->saved; + } + + stream->offset = (size_t) newPosn; + + if (stream->offset < stream->eof) { + /* + * We're seeked backward into the stream. Preserve the character + * at EOF and stomp it with a NUL. + */ + stream->saved = *(*stream->bufp + stream->offset); + *(*stream->bufp + stream->offset) = '\0'; + *stream->sizep = stream->offset; + } else { + /* + * We're positioned at, or possibly beyond, the EOF. We want to + * publish the current EOF, not the current position. + */ + *stream->sizep = stream->eof; + } + + return newPosn; +} + +/* + * Close the memstream. We free everything but the data buffer. + */ +static int close_memstream(void* cookie) +{ + free(cookie); + return 0; +} + +/* + * Prepare a memstream. + */ +FILE* open_memstream(char** bufp, size_t* sizep) +{ + FILE* fp; + MemStream* stream; + + if (bufp == NULL || sizep == NULL) { + errno = EINVAL; + return NULL; + } + + stream = (MemStream*) calloc(1, sizeof(MemStream)); + if (stream == NULL) + return NULL; + + fp = funopen(stream, + NULL, write_memstream, seek_memstream, close_memstream); + if (fp == NULL) { + free(stream); + return NULL; + } + + *sizep = 0; + *bufp = NULL; + stream->bufp = bufp; + stream->sizep = sizep; + + return fp; +} + +#else /*not HAVE_FUNOPEN*/ +FILE* open_memstream(char** bufp, size_t* sizep) +{ + abort(); +} +#endif /*HAVE_FUNOPEN*/ + + + +#if 0 +#define _GNU_SOURCE +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * Simple regression test. + * + * To test on desktop Linux with valgrind, it's possible to make a simple + * change to open_memstream() to use fopencookie instead: + * + * cookie_io_functions_t iofuncs = + * { NULL, write_memstream, seek_memstream, close_memstream }; + * fp = fopencookie(stream, "w", iofuncs); + * + * (Some tweaks to seek_memstream are also required, as that takes a + * pointer to an offset rather than an offset, and returns 0 or -1.) + */ +int testMemStream(void) +{ + FILE *stream; + char *buf; + size_t len; + off_t eob; + + printf("Test1\n"); + + /* std example */ + stream = open_memstream(&buf, &len); + fprintf(stream, "hello my world"); + fflush(stream); + printf("buf=%s, len=%zu\n", buf, len); + eob = ftello(stream); + fseeko(stream, 0, SEEK_SET); + fprintf(stream, "good-bye"); + fseeko(stream, eob, SEEK_SET); + fclose(stream); + printf("buf=%s, len=%zu\n", buf, len); + free(buf); + + printf("Test2\n"); + + /* std example without final seek-to-end */ + stream = open_memstream(&buf, &len); + fprintf(stream, "hello my world"); + fflush(stream); + printf("buf=%s, len=%zu\n", buf, len); + eob = ftello(stream); + fseeko(stream, 0, SEEK_SET); + fprintf(stream, "good-bye"); + //fseeko(stream, eob, SEEK_SET); + fclose(stream); + printf("buf=%s, len=%zu\n", buf, len); + free(buf); + + printf("Test3\n"); + + /* fancy example; should expand buffer with writes */ + static const int kCmpLen = 1024 + 128; + char* cmp = malloc(kCmpLen); + memset(cmp, 0, 1024); + memset(cmp+1024, 0xff, kCmpLen-1024); + sprintf(cmp, "This-is-a-tes1234"); + sprintf(cmp + 1022, "abcdef"); + + stream = open_memstream (&buf, &len); + setvbuf(stream, NULL, _IONBF, 0); /* note: crashes in glibc with this */ + fprintf(stream, "This-is-a-test"); + fseek(stream, -1, SEEK_CUR); /* broken in glibc; can use {13,SEEK_SET} */ + fprintf(stream, "1234"); + fseek(stream, 1022, SEEK_SET); + fputc('a', stream); + fputc('b', stream); + fputc('c', stream); + fputc('d', stream); + fputc('e', stream); + fputc('f', stream); + fflush(stream); + + if (memcmp(buf, cmp, len+1) != 0) { + printf("mismatch\n"); + } else { + printf("match\n"); + } + + printf("Test4\n"); + stream = open_memstream (&buf, &len); + fseek(stream, 5000, SEEK_SET); + fseek(stream, 4096, SEEK_SET); + fseek(stream, -1, SEEK_SET); /* should have no effect */ + fputc('x', stream); + if (ftell(stream) == 4097) + printf("good\n"); + else + printf("BAD: offset is %ld\n", ftell(stream)); + + printf("DONE\n"); + + return 0; +} + +/* expected output: +Test1 +buf=hello my world, len=14 +buf=good-bye world, len=14 +Test2 +buf=hello my world, len=14 +buf=good-bye, len=8 +Test3 +match +Test4 +good +DONE +*/ + +#endif + +#endif /*!HAVE_OPEN_MEMSTREAM*/ diff --git a/libcutils/sched_policy.c b/libcutils/sched_policy.c index 8134aa1..f9c111e 100644 --- a/libcutils/sched_policy.c +++ b/libcutils/sched_policy.c @@ -27,8 +27,10 @@ #include "cutils/log.h" #ifdef HAVE_SCHED_H +#ifdef HAVE_PTHREADS #include <sched.h> +#include <pthread.h> #include <cutils/sched_policy.h> @@ -42,56 +44,83 @@ #define POLICY_DEBUG 0 +static pthread_once_t the_once = PTHREAD_ONCE_INIT; + static int __sys_supports_schedgroups = -1; -static int add_tid_to_cgroup(int tid, const char *grp_name) +// File descriptors open to /dev/cpuctl/../tasks, setup by initialize, or -1 on error. +static int normal_cgroup_fd = -1; +static int bg_cgroup_fd = -1; + +/* Add tid to the scheduling group defined by the policy */ +static int add_tid_to_cgroup(int tid, SchedPolicy policy) { int fd; - char path[255]; - char text[64]; - sprintf(path, "/dev/cpuctl/%s/tasks", grp_name); + if (policy == SP_BACKGROUND) { + fd = bg_cgroup_fd; + } else { + fd = normal_cgroup_fd; + } - if ((fd = open(path, O_WRONLY)) < 0) { - LOGE("add_tid_to_cgroup failed to open '%s' (%s)\n", path, - strerror(errno)); + if (fd < 0) { + SLOGE("add_tid_to_cgroup failed; background=%d\n", + policy == SP_BACKGROUND ? 1 : 0); return -1; } - sprintf(text, "%d", tid); - if (write(fd, text, strlen(text)) < 0) { - close(fd); - /* - * If the thread is in the process of exiting, - * don't flag an error - */ - if (errno == ESRCH) - return 0; - LOGW("add_tid_to_cgroup failed to write '%s' (%s)\n", path, - strerror(errno)); + // specialized itoa -- works for tid > 0 + char text[22]; + char *end = text + sizeof(text) - 1; + char *ptr = end; + *ptr = '\0'; + while (tid > 0) { + *--ptr = '0' + (tid % 10); + tid = tid / 10; + } + + if (write(fd, ptr, end - ptr) < 0) { + /* + * If the thread is in the process of exiting, + * don't flag an error + */ + if (errno == ESRCH) + return 0; + SLOGW("add_tid_to_cgroup failed to write '%s' (%s); background=%d\n", + ptr, strerror(errno), policy == SP_BACKGROUND ? 1 : 0); return -1; } - close(fd); return 0; } -static inline void initialize() -{ - if (__sys_supports_schedgroups < 0) { - if (!access("/dev/cpuctl/tasks", F_OK)) { - __sys_supports_schedgroups = 1; - } else { - __sys_supports_schedgroups = 0; +static void __initialize(void) { + char* filename; + if (!access("/dev/cpuctl/tasks", F_OK)) { + __sys_supports_schedgroups = 1; + + filename = "/dev/cpuctl/tasks"; + normal_cgroup_fd = open(filename, O_WRONLY); + if (normal_cgroup_fd < 0) { + SLOGE("open of %s failed: %s\n", filename, strerror(errno)); + } + + filename = "/dev/cpuctl/bg_non_interactive/tasks"; + bg_cgroup_fd = open(filename, O_WRONLY); + if (bg_cgroup_fd < 0) { + SLOGE("open of %s failed: %s\n", filename, strerror(errno)); } + } else { + __sys_supports_schedgroups = 0; } } /* * Try to get the scheduler group. * - * The data from /proc/<pid>/cgroup looks like: + * The data from /proc/<pid>/cgroup looks (something) like: * 2:cpu:/bg_non_interactive + * 1:cpuacct:/ * * We return the part after the "/", which will be an empty string for * the default cgroup. If the string is longer than "bufLen", the string @@ -101,34 +130,57 @@ static int getSchedulerGroup(int tid, char* buf, size_t bufLen) { #ifdef HAVE_ANDROID_OS char pathBuf[32]; - char readBuf[256]; - ssize_t count; - int fd; + char lineBuf[256]; + FILE *fp; snprintf(pathBuf, sizeof(pathBuf), "/proc/%d/cgroup", tid); - if ((fd = open(pathBuf, O_RDONLY)) < 0) { + if (!(fp = fopen(pathBuf, "r"))) { return -1; } - count = read(fd, readBuf, sizeof(readBuf)); - if (count <= 0) { - close(fd); - errno = ENODATA; - return -1; - } - close(fd); + while(fgets(lineBuf, sizeof(lineBuf) -1, fp)) { + char *next = lineBuf; + char *subsys; + char *grp; + size_t len; - readBuf[--count] = '\0'; /* remove the '\n', now count==strlen */ + /* Junk the first field */ + if (!strsep(&next, ":")) { + goto out_bad_data; + } - char* cp = strchr(readBuf, '/'); - if (cp == NULL) { - readBuf[sizeof(readBuf)-1] = '\0'; - errno = ENODATA; - return -1; + if (!(subsys = strsep(&next, ":"))) { + goto out_bad_data; + } + + if (strcmp(subsys, "cpu")) { + /* Not the subsys we're looking for */ + continue; + } + + if (!(grp = strsep(&next, ":"))) { + goto out_bad_data; + } + grp++; /* Drop the leading '/' */ + len = strlen(grp); + grp[len-1] = '\0'; /* Drop the trailing '\n' */ + + if (bufLen <= len) { + len = bufLen - 1; + } + strncpy(buf, grp, len); + buf[len] = '\0'; + fclose(fp); + return 0; } - memcpy(buf, cp+1, count); /* count-1 for cp+1, count+1 for NUL */ - return 0; + SLOGE("Failed to find cpu subsys"); + fclose(fp); + return -1; + out_bad_data: + SLOGE("Bad cgroup data {%s}", lineBuf); + fclose(fp); + return -1; #else errno = ENOSYS; return -1; @@ -137,7 +189,7 @@ static int getSchedulerGroup(int tid, char* buf, size_t bufLen) int get_sched_policy(int tid, SchedPolicy *policy) { - initialize(); + pthread_once(&the_once, __initialize); if (__sys_supports_schedgroups) { char grpBuf[32]; @@ -169,7 +221,7 @@ int get_sched_policy(int tid, SchedPolicy *policy) int set_sched_policy(int tid, SchedPolicy policy) { - initialize(); + pthread_once(&the_once, __initialize); #if POLICY_DEBUG char statfile[64]; @@ -195,22 +247,16 @@ int set_sched_policy(int tid, SchedPolicy policy) strncpy(thread_name, p, (q-p)); } if (policy == SP_BACKGROUND) { - LOGD("vvv tid %d (%s)", tid, thread_name); + SLOGD("vvv tid %d (%s)", tid, thread_name); } else if (policy == SP_FOREGROUND) { - LOGD("^^^ tid %d (%s)", tid, thread_name); + SLOGD("^^^ tid %d (%s)", tid, thread_name); } else { - LOGD("??? tid %d (%s)", tid, thread_name); + SLOGD("??? tid %d (%s)", tid, thread_name); } #endif if (__sys_supports_schedgroups) { - const char *grp = ""; - - if (policy == SP_BACKGROUND) { - grp = "bg_non_interactive"; - } - - if (add_tid_to_cgroup(tid, grp)) { + if (add_tid_to_cgroup(tid, policy)) { if (errno != ESRCH && errno != ENOENT) return -errno; } @@ -227,4 +273,5 @@ int set_sched_policy(int tid, SchedPolicy policy) return 0; } +#endif /* HAVE_PTHREADS */ #endif /* HAVE_SCHED_H */ diff --git a/libdiskconfig/Android.mk b/libdiskconfig/Android.mk new file mode 100644 index 0000000..1d0ecb4 --- /dev/null +++ b/libdiskconfig/Android.mk @@ -0,0 +1,19 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +ifneq ($(TARGET_SIMULATOR),true) + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := \ + diskconfig.c \ + diskutils.c \ + write_lst.c \ + config_mbr.c + +LOCAL_MODULE := libdiskconfig +LOCAL_SYSTEM_SHARED_LIBRARIES := libcutils liblog libc + +include $(BUILD_SHARED_LIBRARY) + +endif # ! TARGET_SIMULATOR diff --git a/libdiskconfig/config_mbr.c b/libdiskconfig/config_mbr.c new file mode 100644 index 0000000..825ba60 --- /dev/null +++ b/libdiskconfig/config_mbr.c @@ -0,0 +1,325 @@ +/* libs/diskconfig/diskconfig.c + * + * Copyright 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 "config_mbr" +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> + +#include <cutils/log.h> + +#include <diskconfig/diskconfig.h> + + +/* start and len are in LBA units */ +static void +cfg_pentry(struct pc_partition *pentry, uint8_t status, uint8_t type, + uint32_t start, uint32_t len) +{ + if (len > 0) { + /* seems that somes BIOSens can get wedged on boot while verifying + * the mbr if these are 0 */ + memset(&pentry->start, 0xff, sizeof(struct chs)); + memset(&pentry->end, 0xff, sizeof(struct chs)); + } else { + /* zero out the c/h/s entries.. they are not used */ + memset(&pentry->start, 0, sizeof(struct chs)); + memset(&pentry->end, 0, sizeof(struct chs)); + } + + pentry->status = status; + pentry->type = type; + pentry->start_lba = start; + pentry->len_lba = len; + + LOGI("Configuring pentry. status=0x%x type=0x%x start_lba=%u len_lba=%u", + pentry->status, pentry->type, pentry->start_lba, pentry->len_lba); +} + + +static inline uint32_t +kb_to_lba(uint32_t len_kb, uint32_t sect_size) +{ + uint64_t lba; + + lba = (uint64_t)len_kb * 1024; + /* bump it up to the next LBA boundary just in case */ + lba = (lba + (uint64_t)sect_size - 1) & ~((uint64_t)sect_size - 1); + lba /= (uint64_t)sect_size; + if (lba >= 0xffffffffULL) + LOGE("Error converting kb -> lba. 32bit overflow, expect weirdness"); + return (uint32_t)(lba & 0xffffffffULL); +} + + +static struct write_list * +mk_pri_pentry(struct disk_info *dinfo, struct part_info *pinfo, int pnum, + uint32_t *lba) +{ + struct write_list *item; + struct pc_partition *pentry; + + if (pnum >= PC_NUM_BOOT_RECORD_PARTS) { + LOGE("Maximum number of primary partition exceeded."); + return NULL; + } + + if (!(item = alloc_wl(sizeof(struct pc_partition)))) { + LOGE("Unable to allocate memory for partition entry."); + return NULL; + } + + { + /* DO NOT DEREFERENCE */ + struct pc_boot_record *mbr = (void *)PC_MBR_DISK_OFFSET; + /* grab the offset in mbr where to write this partition entry. */ + item->offset = (loff_t)((uint32_t)((uint8_t *)(&mbr->ptable[pnum]))); + } + + pentry = (struct pc_partition *) &item->data; + + /* need a standard primary partition entry */ + if (pinfo) { + /* need this to be 64 bit in case len_kb is large */ + uint64_t len_lba; + + if (pinfo->len_kb != (uint32_t)-1) { + /* bump it up to the next LBA boundary just in case */ + len_lba = ((uint64_t)pinfo->len_kb * 1024); + len_lba += ((uint64_t)dinfo->sect_size - 1); + len_lba &= ~((uint64_t)dinfo->sect_size - 1); + len_lba /= (uint64_t)dinfo->sect_size; + } else { + /* make it fill the rest of disk */ + len_lba = dinfo->num_lba - *lba; + } + + cfg_pentry(pentry, ((pinfo->flags & PART_ACTIVE_FLAG) ? + PC_PART_ACTIVE : PC_PART_NORMAL), + pinfo->type, *lba, (uint32_t)len_lba); + + pinfo->start_lba = *lba; + *lba += (uint32_t)len_lba; + } else { + /* this should be made an extended partition, and should take + * up the rest of the disk as a primary partition */ + cfg_pentry(pentry, PC_PART_NORMAL, PC_PART_TYPE_EXTENDED, + *lba, dinfo->num_lba - *lba); + + /* note that we do not update the *lba because we now have to + * create a chain of extended partition tables, and first one is at + * *lba */ + } + + return item; +} + + +/* This function configures an extended boot record at the beginning of an + * extended partition. This creates a logical partition and a pointer to + * the next EBR. + * + * ext_lba == The start of the toplevel extended partition (pointed to by the + * entry in the MBR). + */ +static struct write_list * +mk_ext_pentry(struct disk_info *dinfo, struct part_info *pinfo, uint32_t *lba, + uint32_t ext_lba, struct part_info *pnext) +{ + struct write_list *item; + struct pc_boot_record *ebr; + uint32_t len; /* in lba units */ + + if (!(item = alloc_wl(sizeof(struct pc_boot_record)))) { + LOGE("Unable to allocate memory for EBR."); + return NULL; + } + + /* we are going to write the ebr at the current LBA, and then bump the + * lba counter since that is where the logical data partition will start */ + item->offset = (*lba) * dinfo->sect_size; + (*lba)++; + + ebr = (struct pc_boot_record *) &item->data; + memset(ebr, 0, sizeof(struct pc_boot_record)); + ebr->mbr_sig = PC_BIOS_BOOT_SIG; + + if (pinfo->len_kb != (uint32_t)-1) + len = kb_to_lba(pinfo->len_kb, dinfo->sect_size); + else { + if (pnext) { + LOGE("Only the last partition can be specified to fill the disk " + "(name = '%s')", pinfo->name); + goto fail; + } + len = dinfo->num_lba - *lba; + /* update the pinfo structure to reflect the new size, for + * bookkeeping */ + pinfo->len_kb = + (uint32_t)(((uint64_t)len * (uint64_t)dinfo->sect_size) / + ((uint64_t)1024)); + } + + cfg_pentry(&ebr->ptable[PC_EBR_LOGICAL_PART], PC_PART_NORMAL, + pinfo->type, 1, len); + + pinfo->start_lba = *lba; + *lba += len; + + /* If this is not the last partition, we have to create a link to the + * next extended partition. + * + * Otherwise, there's nothing to do since the "pointer entry" is + * already zero-filled. + */ + if (pnext) { + /* The start lba for next partition is an offset from the beginning + * of the top-level extended partition */ + uint32_t next_start_lba = *lba - ext_lba; + uint32_t next_len_lba; + if (pnext->len_kb != (uint32_t)-1) + next_len_lba = 1 + kb_to_lba(pnext->len_kb, dinfo->sect_size); + else + next_len_lba = dinfo->num_lba - *lba; + cfg_pentry(&ebr->ptable[PC_EBR_NEXT_PTR_PART], PC_PART_NORMAL, + PC_PART_TYPE_EXTENDED, next_start_lba, next_len_lba); + } + + return item; + +fail: + free_wl(item); + return NULL; +} + + +struct write_list * +config_mbr(struct disk_info *dinfo) +{ + struct part_info *pinfo; + uint32_t cur_lba = dinfo->skip_lba; + uint32_t ext_lba = 0; + struct write_list *wr_list = NULL; + struct write_list *temp_wr = NULL; + int cnt = 0; + int extended = 0; + + if (!dinfo->part_lst) + return NULL; + + for (cnt = 0; cnt < dinfo->num_parts; ++cnt) { + pinfo = &dinfo->part_lst[cnt]; + + /* Should we create an extedned partition? */ + if (cnt == (PC_NUM_BOOT_RECORD_PARTS - 1)) { + if (cnt + 1 < dinfo->num_parts) { + extended = 1; + ext_lba = cur_lba; + if ((temp_wr = mk_pri_pentry(dinfo, NULL, cnt, &cur_lba))) + wlist_add(&wr_list, temp_wr); + else { + LOGE("Cannot create primary extended partition."); + goto fail; + } + } + } + + /* if extended, need 1 lba for ebr */ + if ((cur_lba + extended) >= dinfo->num_lba) + goto nospace; + else if (pinfo->len_kb != (uint32_t)-1) { + uint32_t sz_lba = (pinfo->len_kb / dinfo->sect_size) * 1024; + if ((cur_lba + sz_lba + extended) > dinfo->num_lba) + goto nospace; + } + + if (!extended) + temp_wr = mk_pri_pentry(dinfo, pinfo, cnt, &cur_lba); + else { + struct part_info *pnext; + pnext = cnt + 1 < dinfo->num_parts ? &dinfo->part_lst[cnt+1] : NULL; + temp_wr = mk_ext_pentry(dinfo, pinfo, &cur_lba, ext_lba, pnext); + } + + if (temp_wr) + wlist_add(&wr_list, temp_wr); + else { + LOGE("Cannot create partition %d (%s).", cnt, pinfo->name); + goto fail; + } + } + + /* fill in the rest of the MBR with empty parts (if needed). */ + for (; cnt < PC_NUM_BOOT_RECORD_PARTS; ++cnt) { + struct part_info blank; + cur_lba = 0; + memset(&blank, 0, sizeof(struct part_info)); + if (!(temp_wr = mk_pri_pentry(dinfo, &blank, cnt, &cur_lba))) { + LOGE("Cannot create blank partition %d.", cnt); + goto fail; + } + wlist_add(&wr_list, temp_wr); + } + + return wr_list; + +nospace: + LOGE("Not enough space to add parttion '%s'.", pinfo->name); + +fail: + wlist_free(wr_list); + return NULL; +} + + +/* Returns the device path of the partition referred to by 'name' + * Must be freed by the caller. + */ +char * +find_mbr_part(struct disk_info *dinfo, const char *name) +{ + struct part_info *plist = dinfo->part_lst; + int num = 0; + char *dev_name = NULL; + int has_extended = (dinfo->num_parts > PC_NUM_BOOT_RECORD_PARTS); + + for(num = 1; num <= dinfo->num_parts; ++num) { + if (!strcmp(plist[num-1].name, name)) + break; + } + + if (num > dinfo->num_parts) + return NULL; + + if (has_extended && (num >= PC_NUM_BOOT_RECORD_PARTS)) + num++; + + if (!(dev_name = malloc(MAX_NAME_LEN))) { + LOGE("Cannot allocate memory."); + return NULL; + } + + num = snprintf(dev_name, MAX_NAME_LEN, "%s%d", dinfo->device, num); + if (num >= MAX_NAME_LEN) { + LOGE("Device name is too long?!"); + free(dev_name); + return NULL; + } + + return dev_name; +} diff --git a/libdiskconfig/diskconfig.c b/libdiskconfig/diskconfig.c new file mode 100644 index 0000000..4dd8c52 --- /dev/null +++ b/libdiskconfig/diskconfig.c @@ -0,0 +1,536 @@ +/* libs/diskconfig/diskconfig.c + * + * Copyright 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 "diskconfig" + +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/ioctl.h> +#include <sys/stat.h> + +#include <linux/fs.h> + +#include <cutils/config_utils.h> +#include <cutils/log.h> + +#include <diskconfig/diskconfig.h> + + +static int +parse_len(const char *str, uint64_t *plen) +{ + char tmp[64]; + int len_str; + uint32_t multiple = 1; + + strncpy(tmp, str, sizeof(tmp)); + tmp[sizeof(tmp)-1] = '\0'; + len_str = strlen(tmp); + if (!len_str) { + LOGE("Invalid disk length specified."); + return 1; + } + + switch(tmp[len_str - 1]) { + case 'M': case 'm': + /* megabyte */ + multiple <<= 10; + case 'K': case 'k': + /* kilobytes */ + multiple <<= 10; + tmp[len_str - 1] = '\0'; + break; + default: + break; + } + + *plen = strtoull(tmp, NULL, 0); + if (!*plen) { + LOGE("Invalid length specified: %s", str); + return 1; + } + + if (*plen == (uint64_t)-1) { + if (multiple > 1) { + LOGE("Size modifier illegal when len is -1"); + return 1; + } + } else { + /* convert len to kilobytes */ + if (multiple > 1024) + multiple >>= 10; + *plen *= multiple; + + if (*plen > 0xffffffffULL) { + LOGE("Length specified is too large!: %llu KB", *plen); + return 1; + } + } + + return 0; +} + + +static int +load_partitions(cnode *root, struct disk_info *dinfo) +{ + cnode *partnode; + + dinfo->num_parts = 0; + for (partnode = root->first_child; partnode; partnode = partnode->next) { + struct part_info *pinfo = &dinfo->part_lst[dinfo->num_parts]; + const char *tmp; + + /* bleh, i will leak memory here, but i DONT CARE since + * the only right thing to do when this function fails + * is to quit */ + pinfo->name = strdup(partnode->name); + + if(config_bool(partnode, "active", 0)) + pinfo->flags |= PART_ACTIVE_FLAG; + + if (!(tmp = config_str(partnode, "type", NULL))) { + LOGE("Partition type required: %s", pinfo->name); + return 1; + } + + /* possible values are: linux, fat32 */ + if (!strcmp(tmp, "linux")) { + pinfo->type = PC_PART_TYPE_LINUX; + } else if (!strcmp(tmp, "fat32")) { + pinfo->type = PC_PART_TYPE_FAT32; + } else { + LOGE("Unsupported partition type found: %s", tmp); + return 1; + } + + if ((tmp = config_str(partnode, "len", NULL)) != NULL) { + uint64_t len; + if (parse_len(tmp, &len)) + return 1; + pinfo->len_kb = (uint32_t) len; + } else + pinfo->len_kb = 0; + + ++dinfo->num_parts; + } + + return 0; +} + +struct disk_info * +load_diskconfig(const char *fn, char *path_override) +{ + struct disk_info *dinfo; + cnode *devroot; + cnode *partnode; + cnode *root = config_node("", ""); + const char *tmp; + + if (!(dinfo = malloc(sizeof(struct disk_info)))) { + LOGE("Could not malloc disk_info"); + return NULL; + } + memset(dinfo, 0, sizeof(struct disk_info)); + + if (!(dinfo->part_lst = malloc(MAX_NUM_PARTS * sizeof(struct part_info)))) { + LOGE("Could not malloc part_lst"); + goto fail; + } + memset(dinfo->part_lst, 0, + (MAX_NUM_PARTS * sizeof(struct part_info))); + + config_load_file(root, fn); + if (root->first_child == NULL) { + LOGE("Could not read config file %s", fn); + goto fail; + } + + if (!(devroot = config_find(root, "device"))) { + LOGE("Could not find device section in config file '%s'", fn); + goto fail; + } + + + if (!(tmp = config_str(devroot, "path", path_override))) { + LOGE("device path is requried"); + goto fail; + } + dinfo->device = strdup(tmp); + + /* find the partition scheme */ + if (!(tmp = config_str(devroot, "scheme", NULL))) { + LOGE("partition scheme is required"); + goto fail; + } else if (!strcmp(tmp, "mbr")) { + dinfo->scheme = PART_SCHEME_MBR; + } else if (!strcmp(tmp, "gpt")) { + LOGE("'gpt' partition scheme not supported yet."); + goto fail; + } else { + LOGE("Unknown partition scheme specified: %s", tmp); + goto fail; + } + + /* grab the sector size (in bytes) */ + tmp = config_str(devroot, "sector_size", "512"); + dinfo->sect_size = strtol(tmp, NULL, 0); + if (!dinfo->sect_size) { + LOGE("Invalid sector size: %s", tmp); + goto fail; + } + + /* first lba where the partitions will start on disk */ + if (!(tmp = config_str(devroot, "start_lba", NULL))) { + LOGE("start_lba must be provided"); + goto fail; + } + + if (!(dinfo->skip_lba = strtol(tmp, NULL, 0))) { + LOGE("Invalid starting LBA (or zero): %s", tmp); + goto fail; + } + + /* Number of LBAs on disk */ + if (!(tmp = config_str(devroot, "num_lba", NULL))) { + LOGE("num_lba is required"); + goto fail; + } + dinfo->num_lba = strtoul(tmp, NULL, 0); + + if (!(partnode = config_find(devroot, "partitions"))) { + LOGE("Device must specify partition list"); + goto fail; + } + + if (load_partitions(partnode, dinfo)) + goto fail; + + return dinfo; + +fail: + if (dinfo->part_lst) + free(dinfo->part_lst); + if (dinfo->device) + free(dinfo->device); + free(dinfo); + return NULL; +} + +static int +sync_ptable(int fd) +{ + struct stat stat; + int rv; + + sync(); + + if (fstat(fd, &stat)) { + LOGE("Cannot stat, errno=%d.", errno); + return -1; + } + + if (S_ISBLK(stat.st_mode) && ((rv = ioctl(fd, BLKRRPART, NULL)) < 0)) { + LOGE("Could not re-read partition table. REBOOT!. (errno=%d)", errno); + return -1; + } + + return 0; +} + +/* This function verifies that the disk info provided is valid, and if so, + * returns an open file descriptor. + * + * This does not necessarily mean that it will later be successfully written + * though. If we use the pc-bios partitioning scheme, we must use extended + * partitions, which eat up some hd space. If the user manually provisioned + * every single partition, but did not account for the extra needed space, + * then we will later fail. + * + * TODO: Make validation more complete. + */ +static int +validate(struct disk_info *dinfo) +{ + int fd; + int sect_sz; + uint64_t disk_size; + uint64_t total_size; + int cnt; + struct stat stat; + + if (!dinfo) + return -1; + + if ((fd = open(dinfo->device, O_RDWR)) < 0) { + LOGE("Cannot open device '%s' (errno=%d)", dinfo->device, errno); + return -1; + } + + if (fstat(fd, &stat)) { + LOGE("Cannot stat file '%s', errno=%d.", dinfo->device, errno); + goto fail; + } + + + /* XXX: Some of the code below is kind of redundant and should probably + * be refactored a little, but it will do for now. */ + + /* Verify that we can operate on the device that was requested. + * We presently only support block devices and regular file images. */ + if (S_ISBLK(stat.st_mode)) { + /* get the sector size and make sure we agree */ + if (ioctl(fd, BLKSSZGET, §_sz) < 0) { + LOGE("Cannot get sector size (errno=%d)", errno); + goto fail; + } + + if (!sect_sz || sect_sz != dinfo->sect_size) { + LOGE("Device sector size is zero or sector sizes do not match!"); + goto fail; + } + + /* allow the user override the "disk size" if they provided num_lba */ + if (!dinfo->num_lba) { + if (ioctl(fd, BLKGETSIZE64, &disk_size) < 0) { + LOGE("Could not get block device size (errno=%d)", errno); + goto fail; + } + /* XXX: we assume that the disk has < 2^32 sectors :-) */ + dinfo->num_lba = (uint32_t)(disk_size / (uint64_t)dinfo->sect_size); + } else + disk_size = (uint64_t)dinfo->num_lba * (uint64_t)dinfo->sect_size; + } else if (S_ISREG(stat.st_mode)) { + LOGI("Requesting operation on a regular file, not block device."); + if (!dinfo->sect_size) { + LOGE("Sector size for regular file images cannot be zero"); + goto fail; + } + if (dinfo->num_lba) + disk_size = (uint64_t)dinfo->num_lba * (uint64_t)dinfo->sect_size; + else { + dinfo->num_lba = (uint32_t)(stat.st_size / dinfo->sect_size); + disk_size = (uint64_t)stat.st_size; + } + } else { + LOGE("Device does not refer to a regular file or a block device!"); + goto fail; + } + +#if 1 + LOGV("Device/file %s: size=%llu bytes, num_lba=%u, sect_size=%d", + dinfo->device, disk_size, dinfo->num_lba, dinfo->sect_size); +#endif + + /* since this is our offset into the disk, we start off with that as + * our size of needed partitions */ + total_size = dinfo->skip_lba * dinfo->sect_size; + + /* add up all the partition sizes and make sure it fits */ + for (cnt = 0; cnt < dinfo->num_parts; ++cnt) { + struct part_info *part = &dinfo->part_lst[cnt]; + if (part->len_kb != (uint32_t)-1) { + total_size += part->len_kb * 1024; + } else if (part->len_kb == 0) { + LOGE("Zero-size partition '%s' is invalid.", part->name); + goto fail; + } else { + /* the partition requests the rest of the disk. */ + if (cnt + 1 != dinfo->num_parts) { + LOGE("Only the last partition in the list can request to fill " + "the rest of disk."); + goto fail; + } + } + + if ((part->type != PC_PART_TYPE_LINUX) && + (part->type != PC_PART_TYPE_FAT32)) { + LOGE("Unknown partition type (0x%x) encountered for partition " + "'%s'\n", part->type, part->name); + goto fail; + } + } + + /* only matters for disks, not files */ + if (S_ISBLK(stat.st_mode) && total_size > disk_size) { + LOGE("Total requested size of partitions (%llu) is greater than disk " + "size (%llu).", total_size, disk_size); + goto fail; + } + + return fd; + +fail: + close(fd); + return -1; +} + +static int +validate_and_config(struct disk_info *dinfo, int *fd, struct write_list **lst) +{ + *lst = NULL; + *fd = -1; + + if ((*fd = validate(dinfo)) < 0) + return 1; + + switch (dinfo->scheme) { + case PART_SCHEME_MBR: + *lst = config_mbr(dinfo); + return *lst == NULL; + case PART_SCHEME_GPT: + /* not supported yet */ + default: + LOGE("Uknown partition scheme."); + break; + } + + close(*fd); + *lst = NULL; + return 1; +} + +/* validate and process the disk layout configuration. + * This will cause an update to the partitions' start lba. + * + * Basically, this does the same thing as apply_disk_config in test mode, + * except that wlist_commit is not called to print out the data to be + * written. + */ +int +process_disk_config(struct disk_info *dinfo) +{ + struct write_list *lst; + int fd; + + if (validate_and_config(dinfo, &fd, &lst) != 0) + return 1; + + close(fd); + wlist_free(lst); + return 0; +} + + +int +apply_disk_config(struct disk_info *dinfo, int test) +{ + int fd; + struct write_list *wr_lst = NULL; + int rv; + + if (validate_and_config(dinfo, &fd, &wr_lst) != 0) { + LOGE("Configuration is invalid."); + goto fail; + } + + if ((rv = wlist_commit(fd, wr_lst, test)) >= 0) + rv = test ? 0 : sync_ptable(fd); + + close(fd); + wlist_free(wr_lst); + return rv; + +fail: + close(fd); + if (wr_lst) + wlist_free(wr_lst); + return 1; +} + +int +dump_disk_config(struct disk_info *dinfo) +{ + int cnt; + struct part_info *part; + + printf("Device: %s\n", dinfo->device); + printf("Scheme: "); + switch (dinfo->scheme) { + case PART_SCHEME_MBR: + printf("MBR"); + break; + case PART_SCHEME_GPT: + printf("GPT (unsupported)"); + break; + default: + printf("Unknown"); + break; + } + printf ("\n"); + + printf("Sector size: %d\n", dinfo->sect_size); + printf("Skip leading LBAs: %u\n", dinfo->skip_lba); + printf("Number of LBAs: %u\n", dinfo->num_lba); + printf("Partitions:\n"); + + for (cnt = 0; cnt < dinfo->num_parts; ++cnt) { + part = &dinfo->part_lst[cnt]; + printf("\tname = %s\n", part->name); + printf("\t\tflags = %s\n", + part->flags & PART_ACTIVE_FLAG ? "Active" : "None"); + printf("\t\ttype = %s\n", + part->type == PC_PART_TYPE_LINUX ? "Linux" : "Unknown"); + if (part->len_kb == (uint32_t)-1) + printf("\t\tlen = rest of disk\n"); + else + printf("\t\tlen = %uKB\n", part->len_kb); + } + printf("Total number of partitions: %d\n", cnt); + printf("\n"); + + return 0; +} + +struct part_info * +find_part(struct disk_info *dinfo, const char *name) +{ + struct part_info *pinfo; + int cnt; + + for (cnt = 0; cnt < dinfo->num_parts; ++cnt) { + pinfo = &dinfo->part_lst[cnt]; + if (!strcmp(pinfo->name, name)) + return pinfo; + } + + return NULL; +} + +/* NOTE: If the returned ptr is non-NULL, it must be freed by the caller. */ +char * +find_part_device(struct disk_info *dinfo, const char *name) +{ + switch (dinfo->scheme) { + case PART_SCHEME_MBR: + return find_mbr_part(dinfo, name); + case PART_SCHEME_GPT: + LOGE("GPT is presently not supported"); + break; + default: + LOGE("Unknown partition table scheme"); + break; + } + + return NULL; +} + + diff --git a/libdiskconfig/diskutils.c b/libdiskconfig/diskutils.c new file mode 100644 index 0000000..22767c0 --- /dev/null +++ b/libdiskconfig/diskutils.c @@ -0,0 +1,117 @@ +/* libs/diskconfig/diskutils.c + * + * Copyright 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 "diskutils" + +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/stat.h> + +#include <cutils/log.h> + +#include <diskconfig/diskconfig.h> + +int +write_raw_image(const char *dst, const char *src, loff_t offset, int test) +{ + int dst_fd = -1; + int src_fd = -1; + uint8_t buffer[2048]; + int nr_bytes; + int tmp; + int done = 0; + uint64_t total = 0; + + LOGI("Writing RAW image '%s' to '%s' (offset=%llu)", src, dst, offset); + if ((src_fd = open(src, O_RDONLY)) < 0) { + LOGE("Could not open %s for reading (errno=%d).", src, errno); + goto fail; + } + + if (!test) { + if ((dst_fd = open(dst, O_RDWR)) < 0) { + LOGE("Could not open '%s' for read/write (errno=%d).", dst, errno); + goto fail; + } + + if (lseek64(dst_fd, offset, SEEK_SET) != offset) { + LOGE("Could not seek to offset %lld in %s.", offset, dst); + goto fail; + } + } + + while (!done) { + if ((nr_bytes = read(src_fd, buffer, sizeof(buffer))) < 0) { + /* XXX: Should we not even bother with EINTR? */ + if (errno == EINTR) + continue; + LOGE("Error (%d) while reading from '%s'", errno, src); + goto fail; + } + + if (!nr_bytes) { + /* we're done. */ + done = 1; + break; + } + + total += nr_bytes; + + /* skip the write loop if we're testing */ + if (test) + nr_bytes = 0; + + while (nr_bytes > 0) { + if ((tmp = write(dst_fd, buffer, nr_bytes)) < 0) { + /* XXX: Should we not even bother with EINTR? */ + if (errno == EINTR) + continue; + LOGE("Error (%d) while writing to '%s'", errno, dst); + goto fail; + } + if (!tmp) + continue; + nr_bytes -= tmp; + } + } + + if (!done) { + LOGE("Exited read/write loop without setting flag! WTF?!"); + goto fail; + } + + if (dst_fd >= 0) + fsync(dst_fd); + + LOGI("Wrote %llu bytes to %s @ %lld", total, dst, offset); + + close(src_fd); + if (dst_fd >= 0) + close(dst_fd); + return 0; + +fail: + if (dst_fd >= 0) + close(dst_fd); + if (src_fd >= 0) + close(src_fd); + return 1; +} diff --git a/vold/switch.h b/libdiskconfig/dump_diskconfig.c index 6729f2d..fff19f5 100644 --- a/vold/switch.h +++ b/libdiskconfig/dump_diskconfig.c @@ -1,12 +1,12 @@ - -/* - * Copyright (C) 2008 The Android Open Source Project +/* libs/diskconfig/dump_diskconfig.c + * + * Copyright 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 + * 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, @@ -15,11 +15,28 @@ * limitations under the License. */ -#ifndef _SWITCH_H -#define _SWITCH_H +#define LOG_TAG "dump_diskconfig" +#include <stdio.h> + +#include <cutils/log.h> + +#include "diskconfig.h" + +int +main(int argc, char *argv[]) +{ + struct disk_info *dinfo; + + if (argc < 2) { + LOGE("usage: %s <conf file>", argv[0]); + return 1; + } + + if (!(dinfo = load_diskconfig(argv[1], NULL))) + return 1; -#include "vold.h" + dump_disk_config(dinfo); -#define SYSFS_CLASS_SWITCH_PATH "/sys/class/switch" + return 0; +} -#endif diff --git a/libdiskconfig/write_lst.c b/libdiskconfig/write_lst.c new file mode 100644 index 0000000..12b7cd7 --- /dev/null +++ b/libdiskconfig/write_lst.c @@ -0,0 +1,92 @@ +/* libs/diskconfig/write_lst.c + * + * Copyright 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 "write_lst" +#include <sys/types.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#include <cutils/log.h> + +#include <diskconfig/diskconfig.h> + +struct write_list * +alloc_wl(uint32_t data_len) +{ + struct write_list *item; + + if (!(item = malloc(sizeof(struct write_list) + data_len))) { + LOGE("Unable to allocate memory."); + return NULL; + } + + item->len = data_len; + return item; +} + +void +free_wl(struct write_list *item) +{ + if (item) + free(item); +} + +struct write_list * +wlist_add(struct write_list **lst, struct write_list *item) +{ + item->next = (*lst); + *lst = item; + return item; +} + +void +wlist_free(struct write_list *lst) +{ + struct write_list *temp_wr; + while (lst) { + temp_wr = lst->next; + free_wl(lst); + lst = temp_wr; + } +} + +int +wlist_commit(int fd, struct write_list *lst, int test) +{ + for(; lst; lst = lst->next) { + if (lseek64(fd, lst->offset, SEEK_SET) != (loff_t)lst->offset) { + LOGE("Cannot seek to the specified position (%lld).", lst->offset); + goto fail; + } + + if (!test) { + if (write(fd, lst->data, lst->len) != (int)lst->len) { + LOGE("Failed writing %u bytes at position %lld.", lst->len, + lst->offset); + goto fail; + } + } else + LOGI("Would write %d bytes @ offset %lld.", lst->len, lst->offset); + } + + return 0; + +fail: + return -1; +} diff --git a/liblog/logd_write.c b/liblog/logd_write.c index 241dbf0..9923bba 100644 --- a/liblog/logd_write.c +++ b/liblog/logd_write.c @@ -27,6 +27,7 @@ #include <cutils/logger.h> #include <cutils/logd.h> +#include <cutils/log.h> #define LOG_BUF_SIZE 1024 @@ -41,21 +42,13 @@ #define log_close(filedes) close(filedes) #endif -typedef enum { - LOG_ID_MAIN = 0, - LOG_ID_RADIO, - LOG_ID_EVENTS, - LOG_ID_MAX -} log_id_t; - static int __write_to_log_init(log_id_t, struct iovec *vec, size_t nr); -static int (*write_to_log)(log_id_t, struct iovec *vec, size_t nr) = - __write_to_log_init; +static int (*write_to_log)(log_id_t, struct iovec *vec, size_t nr) = __write_to_log_init; #ifdef HAVE_PTHREADS static pthread_mutex_t log_init_lock = PTHREAD_MUTEX_INITIALIZER; #endif -static int log_fds[(int)LOG_ID_MAX] = { -1, -1, -1 }; +static int log_fds[(int)LOG_ID_MAX] = { -1, -1, -1, -1 }; /* * This is used by the C++ code to decide if it should write logs through @@ -110,6 +103,7 @@ static int __write_to_log_init(log_id_t log_id, struct iovec *vec, size_t nr) log_fds[LOG_ID_MAIN] = log_open("/dev/"LOGGER_LOG_MAIN, O_WRONLY); log_fds[LOG_ID_RADIO] = log_open("/dev/"LOGGER_LOG_RADIO, O_WRONLY); log_fds[LOG_ID_EVENTS] = log_open("/dev/"LOGGER_LOG_EVENTS, O_WRONLY); + log_fds[LOG_ID_SYSTEM] = log_open("/dev/"LOGGER_LOG_SYSTEM, O_WRONLY); write_to_log = __write_to_log_kernel; @@ -123,6 +117,10 @@ static int __write_to_log_init(log_id_t log_id, struct iovec *vec, size_t nr) log_fds[LOG_ID_EVENTS] = -1; write_to_log = __write_to_log_null; } + + if (log_fds[LOG_ID_SYSTEM] < 0) { + log_fds[LOG_ID_SYSTEM] = log_fds[LOG_ID_MAIN]; + } } #ifdef HAVE_PTHREADS @@ -161,6 +159,34 @@ int __android_log_write(int prio, const char *tag, const char *msg) return write_to_log(log_id, vec, 3); } +int __android_log_buf_write(int bufID, int prio, const char *tag, const char *msg) +{ + struct iovec vec[3]; + + if (!tag) + tag = ""; + + /* XXX: This needs to go! */ + if (!strcmp(tag, "HTC_RIL") || + !strncmp(tag, "RIL", 3) || /* Any log tag with "RIL" as the prefix */ + !strcmp(tag, "AT") || + !strcmp(tag, "GSM") || + !strcmp(tag, "STK") || + !strcmp(tag, "CDMA") || + !strcmp(tag, "PHONE") || + !strcmp(tag, "SMS")) + bufID = LOG_ID_RADIO; + + vec[0].iov_base = (unsigned char *) &prio; + vec[0].iov_len = 1; + vec[1].iov_base = (void *) tag; + vec[1].iov_len = strlen(tag) + 1; + vec[2].iov_base = (void *) msg; + vec[2].iov_len = strlen(msg) + 1; + + return write_to_log(bufID, vec, 3); +} + int __android_log_vprint(int prio, const char *tag, const char *fmt, va_list ap) { char buf[LOG_BUF_SIZE]; @@ -173,7 +199,7 @@ int __android_log_vprint(int prio, const char *tag, const char *fmt, va_list ap) int __android_log_print(int prio, const char *tag, const char *fmt, ...) { va_list ap; - char buf[LOG_BUF_SIZE]; + char buf[LOG_BUF_SIZE]; va_start(ap, fmt); vsnprintf(buf, LOG_BUF_SIZE, fmt, ap); @@ -182,6 +208,18 @@ int __android_log_print(int prio, const char *tag, const char *fmt, ...) return __android_log_write(prio, tag, buf); } +int __android_log_buf_print(int bufID, int prio, const char *tag, const char *fmt, ...) +{ + va_list ap; + char buf[LOG_BUF_SIZE]; + + va_start(ap, fmt); + vsnprintf(buf, LOG_BUF_SIZE, fmt, ap); + va_end(ap); + + return __android_log_buf_write(bufID, prio, tag, buf); +} + void __android_log_assert(const char *cond, const char *tag, const char *fmt, ...) { diff --git a/liblog/logprint.c b/liblog/logprint.c index acfa9f4..4c5b3e5 100644 --- a/liblog/logprint.c +++ b/liblog/logprint.c @@ -850,7 +850,7 @@ char *android_log_formatLogLine ( * Returns count bytes written */ -int android_log_filterAndPrintLogLine( +int android_log_printLogLine( AndroidLogFormat *p_format, int fd, const AndroidLogEntry *entry) @@ -860,11 +860,6 @@ int android_log_filterAndPrintLogLine( char *outBuffer = NULL; size_t totalLen; - if (0 == android_log_shouldPrintLine(p_format, entry->tag, - entry->priority)) { - return 0; - } - outBuffer = android_log_formatLogLine(p_format, defaultBuffer, sizeof(defaultBuffer), entry, &totalLen); diff --git a/libmincrypt/tools/DumpPublicKey.java b/libmincrypt/tools/DumpPublicKey.java index c9e7e4d..d2935e0 100644 --- a/libmincrypt/tools/DumpPublicKey.java +++ b/libmincrypt/tools/DumpPublicKey.java @@ -77,7 +77,7 @@ class DumpPublicKey { // Write out modulus as little endian array of integers. result.append(",{"); for (int i = 0; i < nwords; ++i) { - int n = N.mod(B).intValue(); + long n = N.mod(B).longValue(); result.append(n); if (i != nwords - 1) { @@ -91,7 +91,7 @@ class DumpPublicKey { // Write R^2 as little endian array of integers. result.append(",{"); for (int i = 0; i < nwords; ++i) { - int rr = RR.mod(B).intValue(); + long rr = RR.mod(B).longValue(); result.append(rr); if (i != nwords - 1) { diff --git a/libnetutils/dhcp_utils.c b/libnetutils/dhcp_utils.c index 43f5ec7..cb0960f 100644 --- a/libnetutils/dhcp_utils.c +++ b/libnetutils/dhcp_utils.c @@ -24,8 +24,9 @@ #include <cutils/properties.h> -static const char DAEMON_NAME[] = "dhcpcd"; -static const char DAEMON_PROP_NAME[] = "init.svc.dhcpcd"; +static const char DAEMON_NAME[] = "dhcpcd"; +static const char DAEMON_PROP_NAME[] = "init.svc.dhcpcd"; +static const char HOSTNAME_PROP_NAME[] = "net.hostname"; static const char DHCP_PROP_NAME_PREFIX[] = "dhcp"; static const int NAP_TIME = 1; /* wait for 1 second at a time */ /* when polling for property values */ @@ -137,6 +138,7 @@ int dhcp_do_request(const char *interface, { char result_prop_name[PROPERTY_KEY_MAX]; char prop_value[PROPERTY_VALUE_MAX] = {'\0'}; + char daemon_cmd[PROPERTY_VALUE_MAX * 2]; const char *ctrl_prop = "ctl.start"; const char *desired_status = "running"; @@ -147,7 +149,13 @@ int dhcp_do_request(const char *interface, property_set(result_prop_name, ""); /* Start the daemon and wait until it's ready */ - property_set(ctrl_prop, DAEMON_NAME); + if (property_get(HOSTNAME_PROP_NAME, prop_value, NULL) && (prop_value[0] != '\0')) + snprintf(daemon_cmd, sizeof(daemon_cmd), "%s:-h %s %s", DAEMON_NAME, + prop_value, interface); + else + snprintf(daemon_cmd, sizeof(daemon_cmd), "%s:%s", DAEMON_NAME, interface); + memset(prop_value, '\0', PROPERTY_VALUE_MAX); + property_set(ctrl_prop, daemon_cmd); if (wait_for_property(DAEMON_PROP_NAME, desired_status, 10) < 0) { snprintf(errmsg, sizeof(errmsg), "%s", "Timed out waiting for dhcpcd to start"); return -1; diff --git a/libpixelflinger/format.cpp b/libpixelflinger/format.cpp index 161e6d6..6546e8c 100644 --- a/libpixelflinger/format.cpp +++ b/libpixelflinger/format.cpp @@ -40,12 +40,12 @@ static GGLFormat const gPixelFormatInfos[] = { 0, 0, {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 0 }, // PIXEL_FORMAT_NONE { 0, 0, {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 0 }, // PIXEL_FORMAT_NONE - { 1, 16, {{ 0, 8, 0, 8, 0, 8, 0, 0 }}, GGL_Y_CB_CR_SP },// PIXEL_FORMAT_YCbCr_422_SP - { 1, 12, {{ 0, 8, 0, 8, 0, 8, 0, 0 }}, GGL_Y_CB_CR_SP },// PIXEL_FORMAT_YCbCr_420_SP - { 1, 16, {{ 0, 8, 0, 8, 0, 8, 0, 0 }}, GGL_Y_CB_CR_P }, // PIXEL_FORMAT_YCbCr_422_P - { 1, 12, {{ 0, 8, 0, 8, 0, 8, 0, 0 }}, GGL_Y_CB_CR_P }, // PIXEL_FORMAT_YCbCr_420_P - { 1, 16, {{ 0, 8, 0, 8, 0, 8, 0, 0 }}, GGL_Y_CB_CR_I }, // PIXEL_FORMAT_YCbCr_422_I - { 1, 12, {{ 0, 8, 0, 8, 0, 8, 0, 0 }}, GGL_Y_CB_CR_I }, // PIXEL_FORMAT_YCbCr_420_I + { 0, 0, {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 0 }, // PIXEL_FORMAT_NONE + { 0, 0, {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 0 }, // PIXEL_FORMAT_NONE + { 0, 0, {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 0 }, // PIXEL_FORMAT_NONE + { 0, 0, {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 0 }, // PIXEL_FORMAT_NONE + { 0, 0, {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 0 }, // PIXEL_FORMAT_NONE + { 0, 0, {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 0 }, // PIXEL_FORMAT_NONE { 0, 0, {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 0 }, // PIXEL_FORMAT_NONE { 0, 0, {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 0 }, // PIXEL_FORMAT_NONE @@ -53,6 +53,15 @@ static GGLFormat const gPixelFormatInfos[] = { 1, 8, {{ 8, 0, 0, 0, 0, 0, 0, 0 }}, GGL_STENCIL_INDEX }, { 4, 24, {{ 0, 0, 24, 0, 0, 0, 0, 0 }}, GGL_DEPTH_COMPONENT}, { 4, 8, {{ 32,24, 0, 0, 0, 0, 0, 0 }}, GGL_STENCIL_INDEX }, + + { 0, 0, {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 0 }, // PIXEL_FORMAT_NONE + { 0, 0, {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 0 }, // PIXEL_FORMAT_NONE + { 0, 0, {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 0 }, // PIXEL_FORMAT_NONE + { 0, 0, {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 0 }, // PIXEL_FORMAT_NONE + + { 0, 0, {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 0 }, // PIXEL_FORMAT_NONE + { 0, 0, {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 0 }, // PIXEL_FORMAT_NONE + }; }; // namespace android diff --git a/libpixelflinger/pixelflinger.cpp b/libpixelflinger/pixelflinger.cpp index b54da0c..84e584e 100644 --- a/libpixelflinger/pixelflinger.cpp +++ b/libpixelflinger/pixelflinger.cpp @@ -281,6 +281,7 @@ static void ggl_fogColor3xv(void* con, const GGLclampx* color) const int32_t r = gglClampx(color[0]); const int32_t g = gglClampx(color[1]); const int32_t b = gglClampx(color[2]); + c->state.fog.color[GGLFormat::ALPHA]= 0xFF; // unused c->state.fog.color[GGLFormat::RED] = (r - (r>>8))>>8; c->state.fog.color[GGLFormat::GREEN]= (g - (g>>8))>>8; c->state.fog.color[GGLFormat::BLUE] = (b - (b>>8))>>8; diff --git a/libsysutils/src/FrameworkClient.cpp b/libsysutils/src/FrameworkClient.cpp index 1686996..562dd67 100644 --- a/libsysutils/src/FrameworkClient.cpp +++ b/libsysutils/src/FrameworkClient.cpp @@ -21,7 +21,7 @@ int FrameworkClient::sendMsg(const char *msg) { pthread_mutex_lock(&mWriteMutex); if (write(mSocket, msg, strlen(msg) +1) < 0) { - LOGW("Unable to send msg '%s' (%s)", msg, strerror(errno)); + SLOGW("Unable to send msg '%s' (%s)", msg, strerror(errno)); } pthread_mutex_unlock(&mWriteMutex); return 0; diff --git a/libsysutils/src/FrameworkCommand.cpp b/libsysutils/src/FrameworkCommand.cpp index c52eac7..038d87e 100644 --- a/libsysutils/src/FrameworkCommand.cpp +++ b/libsysutils/src/FrameworkCommand.cpp @@ -26,7 +26,7 @@ FrameworkCommand::FrameworkCommand(const char *cmd) { } int FrameworkCommand::runCommand(SocketClient *c, int argc, char **argv) { - LOGW("Command %s has no run handler!", getCommand()); + SLOGW("Command %s has no run handler!", getCommand()); errno = ENOSYS; return -1; } diff --git a/libsysutils/src/FrameworkListener.cpp b/libsysutils/src/FrameworkListener.cpp index 4c74765..80f678d 100644 --- a/libsysutils/src/FrameworkListener.cpp +++ b/libsysutils/src/FrameworkListener.cpp @@ -34,7 +34,7 @@ bool FrameworkListener::onDataAvailable(SocketClient *c) { int len; if ((len = read(c->getSocket(), buffer, sizeof(buffer) -1)) < 0) { - LOGE("read() failed (%s)", strerror(errno)); + SLOGE("read() failed (%s)", strerror(errno)); return errno; } else if (!len) return false; @@ -114,7 +114,7 @@ void FrameworkListener::dispatchCommand(SocketClient *cli, char *data) { argv[argc++] = strdup(tmp); #if 0 for (k = 0; k < argc; k++) { - LOGD("arg[%d] = '%s'", k, argv[k]); + SLOGD("arg[%d] = '%s'", k, argv[k]); } #endif @@ -128,7 +128,7 @@ void FrameworkListener::dispatchCommand(SocketClient *cli, char *data) { if (!strcmp(argv[0], c->getCommand())) { if (c->runCommand(cli, argc, argv)) { - LOGW("Handler '%s' error (%s)", c->getCommand(), strerror(errno)); + SLOGW("Handler '%s' error (%s)", c->getCommand(), strerror(errno)); } goto out; } diff --git a/libsysutils/src/NetlinkEvent.cpp b/libsysutils/src/NetlinkEvent.cpp index 5f959a7..c2ba647 100644 --- a/libsysutils/src/NetlinkEvent.cpp +++ b/libsysutils/src/NetlinkEvent.cpp @@ -46,6 +46,16 @@ NetlinkEvent::~NetlinkEvent() { } } +void NetlinkEvent::dump() { + int i; + + for (i = 0; i < NL_PARAMS_MAX; i++) { + if (!mParams[i]) + break; + SLOGD("NL param '%s'\n", mParams[i]); + } +} + bool NetlinkEvent::decode(char *buffer, int size) { char *s = buffer; char *end; @@ -92,6 +102,6 @@ const char *NetlinkEvent::findParam(const char *paramName) { return &mParams[i][strlen(paramName) + 1]; } - LOGE("NetlinkEvent::FindParam(): Parameter '%s' not found", paramName); + SLOGE("NetlinkEvent::FindParam(): Parameter '%s' not found", paramName); return NULL; } diff --git a/libsysutils/src/NetlinkListener.cpp b/libsysutils/src/NetlinkListener.cpp index 5586dcc..e2a354e 100644 --- a/libsysutils/src/NetlinkListener.cpp +++ b/libsysutils/src/NetlinkListener.cpp @@ -35,13 +35,13 @@ bool NetlinkListener::onDataAvailable(SocketClient *cli) int count; if ((count = recv(socket, mBuffer, sizeof(mBuffer), 0)) < 0) { - LOGE("recv failed (%s)", strerror(errno)); + SLOGE("recv failed (%s)", strerror(errno)); return false; } NetlinkEvent *evt = new NetlinkEvent(); if (!evt->decode(mBuffer, count)) { - LOGE("Error decoding NetlinkEvent"); + SLOGE("Error decoding NetlinkEvent"); goto out; } diff --git a/libsysutils/src/ServiceManager.cpp b/libsysutils/src/ServiceManager.cpp index 700ac91..60b161a 100644 --- a/libsysutils/src/ServiceManager.cpp +++ b/libsysutils/src/ServiceManager.cpp @@ -11,11 +11,11 @@ ServiceManager::ServiceManager() { int ServiceManager::start(const char *name) { if (isRunning(name)) { - LOGW("Service '%s' is already running", name); + SLOGW("Service '%s' is already running", name); return 0; } - LOGD("Starting service '%s'", name); + SLOGD("Starting service '%s'", name); property_set("ctl.start", name); int count = 200; @@ -25,21 +25,21 @@ int ServiceManager::start(const char *name) { break; } if (!count) { - LOGW("Timed out waiting for service '%s' to start", name); + SLOGW("Timed out waiting for service '%s' to start", name); errno = ETIMEDOUT; return -1; } - LOGD("Sucessfully started '%s'", name); + SLOGD("Sucessfully started '%s'", name); return 0; } int ServiceManager::stop(const char *name) { if (!isRunning(name)) { - LOGW("Service '%s' is already stopped", name); + SLOGW("Service '%s' is already stopped", name); return 0; } - LOGD("Stopping service '%s'", name); + SLOGD("Stopping service '%s'", name); property_set("ctl.stop", name); int count = 200; @@ -50,11 +50,11 @@ int ServiceManager::stop(const char *name) { } if (!count) { - LOGW("Timed out waiting for service '%s' to stop", name); + SLOGW("Timed out waiting for service '%s' to stop", name); errno = ETIMEDOUT; return -1; } - LOGD("Sucessfully stopped '%s'", name); + SLOGD("Sucessfully stopped '%s'", name); return 0; } diff --git a/libsysutils/src/SocketClient.cpp b/libsysutils/src/SocketClient.cpp index 857ed4d..e9ae23a 100644 --- a/libsysutils/src/SocketClient.cpp +++ b/libsysutils/src/SocketClient.cpp @@ -41,11 +41,11 @@ int SocketClient::sendMsg(const char *msg) { pthread_mutex_lock(&mWriteMutex); while(brtw) { if ((rc = write(mSocket,p, brtw)) < 0) { - LOGW("Unable to send msg '%s' (%s)", msg, strerror(errno)); + SLOGW("Unable to send msg '%s' (%s)", msg, strerror(errno)); pthread_mutex_unlock(&mWriteMutex); return -1; } else if (!rc) { - LOGW("0 length write :("); + SLOGW("0 length write :("); errno = EIO; pthread_mutex_unlock(&mWriteMutex); return -1; diff --git a/libsysutils/src/SocketListener.cpp b/libsysutils/src/SocketListener.cpp index 72e128d..7af221f 100644 --- a/libsysutils/src/SocketListener.cpp +++ b/libsysutils/src/SocketListener.cpp @@ -64,30 +64,30 @@ SocketListener::~SocketListener() { int SocketListener::startListener() { if (!mSocketName && mSock == -1) { - LOGE("Failed to start unbound listener"); + SLOGE("Failed to start unbound listener"); errno = EINVAL; return -1; } else if (mSocketName) { if ((mSock = android_get_control_socket(mSocketName)) < 0) { - LOGE("Obtaining file descriptor socket '%s' failed: %s", + SLOGE("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)); + SLOGE("Unable to listen on socket (%s)", strerror(errno)); return -1; } else if (!mListen) mClients->push_back(new SocketClient(mSock)); if (pipe(mCtrlPipe)) { - LOGE("pipe failed (%s)", strerror(errno)); + SLOGE("pipe failed (%s)", strerror(errno)); return -1; } if (pthread_create(&mThread, NULL, SocketListener::threadStart, this)) { - LOGE("pthread_create (%s)", strerror(errno)); + SLOGE("pthread_create (%s)", strerror(errno)); return -1; } @@ -98,13 +98,13 @@ int SocketListener::stopListener() { char c = 0; if (write(mCtrlPipe[1], &c, 1) != 1) { - LOGE("Error writing to control pipe (%s)", strerror(errno)); + SLOGE("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)); + SLOGE("Error joining to listener thread (%s)", strerror(errno)); return -1; } close(mCtrlPipe[0]); @@ -161,7 +161,7 @@ void SocketListener::runListener() { pthread_mutex_unlock(&mClientsLock); if ((rc = select(max + 1, &read_fds, NULL, NULL, NULL)) < 0) { - LOGE("select failed (%s)", strerror(errno)); + SLOGE("select failed (%s)", strerror(errno)); sleep(1); continue; } else if (!rc) @@ -175,7 +175,7 @@ void SocketListener::runListener() { int c; if ((c = accept(mSock, &addr, &alen)) < 0) { - LOGE("accept failed (%s)", strerror(errno)); + SLOGE("accept failed (%s)", strerror(errno)); sleep(1); continue; } @@ -212,7 +212,7 @@ void SocketListener::sendBroadcast(int code, const char *msg, bool addErrno) { for (i = mClients->begin(); i != mClients->end(); ++i) { if ((*i)->sendMsg(code, msg, addErrno)) { - LOGW("Error sending broadcast (%s)", strerror(errno)); + SLOGW("Error sending broadcast (%s)", strerror(errno)); } } pthread_mutex_unlock(&mClientsLock); @@ -224,7 +224,7 @@ void SocketListener::sendBroadcast(const char *msg) { for (i = mClients->begin(); i != mClients->end(); ++i) { if ((*i)->sendMsg(msg)) { - LOGW("Error sending broadcast (%s)", strerror(errno)); + SLOGW("Error sending broadcast (%s)", strerror(errno)); } } pthread_mutex_unlock(&mClientsLock); diff --git a/logcat/Android.mk b/logcat/Android.mk index 5a9f12d..7b8eb01 100644 --- a/logcat/Android.mk +++ b/logcat/Android.mk @@ -3,24 +3,10 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) -LOCAL_SRC_FILES:= logcat.cpp +LOCAL_SRC_FILES:= logcat.cpp event.logtags LOCAL_SHARED_LIBRARIES := liblog LOCAL_MODULE:= logcat include $(BUILD_EXECUTABLE) - -######################## -include $(CLEAR_VARS) - -LOCAL_MODULE := event-log-tags - -# This will install the file in /system/etc -# -LOCAL_MODULE_CLASS := ETC - -LOCAL_SRC_FILES := $(LOCAL_MODULE) -LOCAL_PREBUILT_STRIP_COMMENTS := 1 - -include $(BUILD_PREBUILT) diff --git a/logcat/event-log-tags b/logcat/event-log-tags deleted file mode 100644 index 5c4c962..0000000 --- a/logcat/event-log-tags +++ /dev/null @@ -1,404 +0,0 @@ -# The entries in this file map a sparse set of log tag numbers to tag names. -# This is installed on the device, in /system/etc, and parsed by logcat. -# -# Tag numbers are decimal integers, from 0 to 2^31. (Let's leave the -# negative values alone for now.) -# -# Tag names are one or more ASCII letters and numbers or underscores, i.e. -# "[A-Z][a-z][0-9]_". Do not include spaces or punctuation (the former -# impacts log readability, the latter makes regex searches more annoying). -# -# Tag numbers and names are separated by whitespace. Blank lines and lines -# starting with '#' are ignored. -# -# Optionally, after the tag names can be put a description for the value(s) -# of the tag. Description are in the format -# (<name>|data type[|data unit]) -# Multiple values are separated by commas. -# -# The data type is a number from the following values: -# 1: int -# 2: long -# 3: string -# 4: list -# -# The data unit is a number taken from the following list: -# 1: Number of objects -# 2: Number of bytes -# 3: Number of milliseconds -# 4: Number of allocations -# 5: Id -# 6: Percent -# Default value for data of type int/long is 2 (bytes). -# -# TODO: generate ".java" and ".h" files with integer constants from this file. - -# These are used for testing, do not modify without updating -# tests/framework-tests/src/android/util/EventLogFunctionalTest.java. -42 answer (to life the universe etc|3) -314 pi -2718 e - -2719 configuration_changed (config mask|1|5) -# "account" is the java hash of the account name -2720 sync (id|3),(event|1|5),(source|1|5),(account|1|5) -2721 cpu (total|1|6),(user|1|6),(system|1|6),(iowait|1|6),(irq|1|6),(softirq|1|6) -2722 battery_level (level|1|6),(voltage|1|1),(temperature|1|1) -2723 battery_status (status|1|5),(health|1|5),(present|1|5),(plugged|1|5),(technology|3) -# This is logged when the device is being forced to sleep (typically by -# the user pressing the power button). -2724 power_sleep_requested (wakeLocksCleared|1|1) -# This is logged when the screen on broadcast has completed -2725 power_screen_broadcast_send (wakelockCount|1|1) -# This is logged when the screen broadcast has completed -2726 power_screen_broadcast_done (on|1|5),(broadcastDuration|2|3),(wakelockCount|1|1) -# This is logged when the screen on broadcast has completed -2727 power_screen_broadcast_stop (which|1|5),(wakelockCount|1|1) -# This is logged when the screen is turned on or off. -2728 power_screen_state (offOrOn|1|5),(becauseOfUser|1|5),(totalTouchDownTime|2|3),(touchCycles|1|1) -# This is logged when the partial wake lock (keeping the device awake -# regardless of whether the screen is off) is acquired or released. -2729 power_partial_wake_state (releasedorAcquired|1|5),(tag|3) -# This is logged when battery goes from discharging to charging. -# It lets us count the total amount of time between charges and the discharge level -2730 battery_discharge (duration|2|3),(minLevel|1|6),(maxLevel|1|6) -# -# Leave IDs through 2739 for more power logs -# - -# This event is logged when the location service uploads location data. -2740 location_controller -# This event is logged when someone is deciding to force a garbage collection -2741 force_gc (reason|3) -# This event is logged on each tickle -2742 tickle (authority|3) -# What happens in a sync operation (bytes sent and received, and -# operation details) -2743 sync_details (authority|3),(send|1|2),(recv|1|2),(details|3) - -# The disk space free on the /data partition, in bytes -2744 free_storage_changed (data|2|2) -# Device low memory notification and disk space free on the /data partition, in bytes at that time -2745 low_storage (data|2|2) -# disk space free on the /data, /system, and /cache partitions in bytes -2746 free_storage_left (data|2|2),(system|2|2),(cache|2|2) - -# contacts aggregation: time and number of contacts. -# count is negative for query phase, positive for merge phase -2747 contacts_aggregation (aggregation time|2|3), (count|1|1) - -# when a NotificationManager.notify is called -2750 notification_enqueue (pkg|3),(id|1|5),(notification|3) -# when someone tries to cancel a notification, the notification manager sometimes -# calls this with flags too -2751 notification_cancel (pkg|3),(id|1|5),(required_flags|1) -# when someone tries to cancel all of the notifications for a particular package -2752 notification_cancel_all (pkg|3),(required_flags|1) - -# This event is logged when GTalkService encounters important events -2800 gtalkservice (eventType|1) -# This event is logged for GTalk connection state changes. The status field is an int, but -# it really contains 4 separate values, each taking up a byte -# (eventType << 24) + (connection state << 16) + (connection error << 8) + network state -2801 gtalk_connection (status|1) - -2802 watchdog (Service|3) -2803 watchdog_proc_pss (Process|3),(Pid|1|5),(Pss|1|2) -2804 watchdog_soft_reset (Process|3),(Pid|1|5),(MaxPss|1|2),(Pss|1|2),(Skip|3) -2805 watchdog_hard_reset (Process|3),(Pid|1|5),(MaxPss|1|2),(Pss|1|2) -2806 watchdog_pss_stats (EmptyPss|1|2),(EmptyCount|1|1),(BackgroundPss|1|2),(BackgroundCount|1|1),(ServicePss|1|2),(ServiceCount|1|1),(VisiblePss|1|2),(VisibleCount|1|1),(ForegroundPss|1|2),(ForegroundCount|1|1),(NoPssCount|1|1) -2807 watchdog_proc_stats (DeathsInOne|1|1),(DeathsInTwo|1|1),(DeathsInThree|1|1),(DeathsInFour|1|1),(DeathsInFive|1|1) -2808 watchdog_scheduled_reboot (Now|2|1),(Interval|1|3),(StartTime|1|3),(Window|1|3),(Skip|3) -2809 watchdog_meminfo (MemFree|1|2),(Buffers|1|2),(Cached|1|2),(Active|1|2),(Inactive|1|2),(AnonPages|1|2),(Mapped|1|2),(Slab|1|2),(SReclaimable|1|2),(SUnreclaim|1|2),(PageTables|1|2) -2810 watchdog_vmstat (runtime|2|3),(pgfree|1|1),(pgactivate|1|1),(pgdeactivate|1|1),(pgfault|1|1),(pgmajfault|1|1) -2811 watchdog_requested_reboot (NoWait|1|1),(ScheduleInterval|1|3),(RecheckInterval|1|3),(StartTime|1|3),(Window|1|3),(MinScreenOff|1|3),(MinNextAlarm|1|3) - -2820 backup_data_changed (Package|3) -2821 backup_start (Transport|3) -2822 backup_transport_failure (Package|3) -2823 backup_agent_failure (Package|3),(Message|3) -2824 backup_package (Package|3),(Size|1|2) -2825 backup_success (Packages|1|1),(Time|1|3) -2826 backup_reset (Transport|3) -2827 backup_initialize - -2830 restore_start (Transport|3),(Source|2|5) -2831 restore_transport_failure -2832 restore_agent_failure (Package|3),(Message|3) -2833 restore_package (Package|3),(Size|1|2) -2834 restore_success (Packages|1|1),(Time|1|3) - -# Device boot timings. We include monotonic clock values because the -# intrinsic event log times are wall-clock. -# -# Runtime starts: -3000 boot_progress_start (time|2|3) -# SystemServer.run() starts: -3010 boot_progress_system_run (time|2|3) -# ZygoteInit class preloading starts: -3020 boot_progress_preload_start (time|2|3) -# ZygoteInit class preloading ends: -3030 boot_progress_preload_end (time|2|3) -# ActivityManagerService.systemReady() starts: -3040 boot_progress_ams_ready (time|2|3) -# ActivityManagerService calls enableScreenAfterBoot(): -3050 boot_progress_enable_screen (time|2|3) -# Package Manager starts: -3060 boot_progress_pms_start (time|2|3) -# Package Manager .apk scan starts: -3070 boot_progress_pms_system_scan_start (time|2|3) -# Package Manager .apk scan starts: -3080 boot_progress_pms_data_scan_start (time|2|3) -# Package Manager .apk scan ends: -3090 boot_progress_pms_scan_end (time|2|3) -# Package Manager ready: -3100 boot_progress_pms_ready (time|2|3) -# + check activity_launch_time for Home app - -# This event is logged when GTalk connection is closed. -# The status field is an int, but contains 2 different values, it's represented as -# -# (networkType << 8) + connection error -# -# the possible error values are -# -# no_error=0, no_network=1, connection_failed=2, unknown_host=3, auth_failed=4, -# auth_expired=5, heart_beat_timeout=6, server_error=7, server_reject_rate_limiting=8, unknown=10 -# -# duration is the connection duration. -4000 gtalk_conn_close (status|1),(duration|1) - -# This event is logged for GTalk heartbeat resets -# interval_and_nt contains both the heartbeat interval and the network type, It's represented as -# (networkType << 16) + interval -# interval is in seconds; network type can be 0 (mobile) or 1 (wifi); ip is the host ip addr. -4001 gtalk_heartbeat_reset (interval_and_nt|1),(ip|3) - -# dvm_gc_info: LIST (LONG, LONG, LONG) -# -# First LONG: -# -# [63] 1 -# [62-24] ASCII process identifier -# [23-12] GC time in ms -# [11- 0] Bytes freed -# -# Second LONG (aggregated heap info): -# -# [63-62] 10 -# [61-60] Reserved; must be zero -# [59-48] Objects freed -# [47-36] Actual size (current footprint) -# [35-24] Allowed size (current hard max) -# [23-12] Objects allocated -# [11- 0] Bytes allocated -# -# Third LONG (zygote heap info): -# -# [63-62] 11 -# [61-60] Reserved; must be zero -# [59-48] Soft limit -# [47-36] Actual size (current footprint) -# [35-24] Allowed size (current hard max) -# [23-12] Objects allocated -# [11- 0] Bytes allocated -# -# Fourth LONG: -# -# [63-48] Reserved; must be zero -# [47-36] dlmallocFootprint -# [35-24] mallinfo: total allocated space -# [23-12] External byte limit -# [11- 0] External bytes allocated -# -# See HeapDebug.c -# -20001 dvm_gc_info (custom|2),(custom|2),(custom|2),(custom|2) -20002 dvm_gc_madvise_info (total|1|2),(zygote|1|2) - -# Do not change these names without updating the checkin_events setting in -# google3/googledata/wireless/android/provisioning/gservices.config !! -# -# An activity is being finished: -30001 am_finish_activity (Token|1|5),(Task ID|1|5),(Component Name|3),(Reason|3) -# A task is being brought to the front of the screen: -30002 am_task_to_front (Task|1|5) -# An existing activity is being given a new intent: -30003 am_new_intent (Token|1|5),(Task ID|1|5),(Component Name|3),(Action|3),(MIME Type|3),(URI|3),(Flags|1|5) -# A new task is being created: -30004 am_create_task (Task ID|1|5) -# A new activity is being created in an existing task: -30005 am_create_activity (Token|1|5),(Task ID|1|5),(Component Name|3),(Action|3),(MIME Type|3),(URI|3),(Flags|1|5) -# An activity has been resumed into the foreground but was not already running: -30006 am_restart_activity (Token|1|5),(Task ID|1|5),(Component Name|3) -# An activity has been resumed and is now in the foreground: -30007 am_resume_activity (Token|1|5),(Task ID|1|5),(Component Name|3) -# Application Not Responding -30008 anr (pid|1|5),(Package Name|3),(reason|3) -# Activity launch time -30009 activity_launch_time (Token|1|5),(Component Name|3),(time|2|3) -# Application process bound to work -30010 am_proc_bound (PID|1|5),(Process Name|3) -# Application process died -30011 am_proc_died (PID|1|5),(Process Name|3) -# The Activity Manager failed to pause the given activity. -30012 am_failed_to_pause (Token|1|5),(Wanting to pause|3),(Currently pausing|3) -# Attempting to pause the current activity -30013 am_pause_activity (Token|1|5),(Component Name|3) -# Application process has been started -30014 am_proc_start (PID|1|5),(UID|1|5),(Process Name|3),(Type|3),(Component|3) -# An application process has been marked as bad -30015 am_proc_bad (UID|1|5),(Process Name|3) -# An application process that was bad is now marked as good -30016 am_proc_good (UID|1|5),(Process Name|3) -# Reporting to applications that memory is low -30017 am_low_memory (Num Processes|1|1) -# An activity is being destroyed: -30018 am_destroy_activity (Token|1|5),(Task ID|1|5),(Component Name|3) -# An activity has been relaunched, resumed, and is now in the foreground: -30019 am_relaunch_resume_activity (Token|1|5),(Task ID|1|5),(Component Name|3) -# An activity has been relaunched: -30020 am_relaunch_activity (Token|1|5),(Task ID|1|5),(Component Name|3) -# The activity's onPause has been called. -30021 am_on_paused_called (Component Name|3) -# The activity's onResume has been called. -30022 am_on_resume_called (Component Name|3) -# Kill a process to reclaim memory. -30023 am_kill_for_memory (PID|1|5),(Process Name|3),(OomAdj|1|5) -# Discard an undelivered serialized broadcast (timeout/ANR/crash) -30024 am_broadcast_discard_filter (Broadcast|1|5),(Action|3),(Receiver Number|1|1),(BroadcastFilter|1|5) -30025 am_broadcast_discard_app (Broadcast|1|5),(Action|3),(Receiver Number|1|1),(App|3) -# A service is being created -30030 am_create_service (Service Record|1|5),(Name|3),(Intent|3),(PID|1|5) -# A service is being destroyed -30031 am_destroy_service (Service Record|1|5),(Name|3),(PID|1|5) -# A process has crashed too many times, it is being cleared -30032 am_process_crashed_too_much (Name|3),(PID|1|5) -# An unknown process is trying to attach to the activity manager -30033 am_drop_process (PID|1|5) -# A service has crashed too many times, it is being stopped -30034 am_service_crashed_too_much (Crash Count|1|1),(Component Name|3),(PID|1|5) -# A service is going to be restarted after its process went away -30035 am_schedule_service_restart (Component Name|3),(Time|2|3) -# A client was waiting for a content provider, but its process was lost -30036 am_provider_lost_process (Package Name|3),(UID|1|5),(Name|3) -# The activity manager gave up on a new process taking too long to start -30037 am_process_start_timeout (PID|1|5),(UID|1|5),(Process Name|3) - -# Out of memory for surfaces. -31000 wm_no_surface_memory (Window|3),(PID|1|5),(Operation|3) - -# Re-connecting to input method service because we haven't received its interface -32000 imf_force_reconnect_ime (IME|4),(Time Since Connect|2|3),(Showing|1|1) - -75000 sqlite_mem_alarm_current (current|1|2) -75001 sqlite_mem_alarm_max (max|1|2) -75002 sqlite_mem_alarm_alloc_attempt (attempts|1|4) -75003 sqlite_mem_released (Memory released|1|2) -75004 sqlite_db_corrupt (Database file corrupt|3) - -40000 checkin (Check in time|2|3) - -50000 menu_item_selected (Menu type where 0 is options and 1 is context|1|5),(Menu item title|3) -50001 menu_opened (Menu type where 0 is options and 1 is context|1|5) -# Connectivity state changed: -# [31-13] Reserved for future use -# [12- 9] Network subtype (for mobile network, as defined by TelephonyManager) -# [ 8- 3] Detailed state ordinal (as defined by NetworkInfo.DetailedState) -# [ 2- 0] Network type (as defined by ConnectivityManager) -50020 connectivity_state_changed (custom|1|5) - -# Wi-Fi network state changed: -# [31- 6] Reserved for future use -# [ 5- 0] Detailed state ordinal (as defined by NetworkInfo.DetailedState) -50021 wifi_network_state_changed (network_state|1|5) - -# Wi-Fi supplicant state changed: -# [31- 6] Reserved for future use -# [ 5- 0] Supplicant state ordinal (as defined by SupplicantState) -50022 wifi_supplicant_state_changed (supplicant_state|1|5) - -# Wi-Fi driver state changed: -# [31- 1] Reserved for future use -# [ 0- 0] Driver start (1) or stopped (0) -50023 wifi_driver_state_changed (driver_state|1|5) - -# Wi-Fi interface configuration state changed: -# [31- 1] Reserved for future use -# [ 0- 0] Interface configuration succeeded (1) or failed (0) -50024 wifi_interface_configuration_state_changed (IP_configuration|1|5) - -# Wi-Fi supplicant connection state changed: -# [31- 2] Reserved for future use -# [ 1- 0] Connected to supplicant (1) or disconnected from supplicant (0), -# or supplicant died (2) -50025 wifi_supplicant_connection_state_changed (connected|1|5) - -# PDP Context has a bad DNS address -50100 pdp_bad_dns_address (dns_address|3) - -# For data connection on PDP context, reached the data-out-without-data-in -# packet count that triggers a countdown to radio restart -50101 pdp_radio_reset_countdown_triggered (out_packet_count|1|1) - -# Radio restart - timed out with no incoming packets. -50102 pdp_radio_reset (out_packet_count|1|1) - -# PDP context reset - timed out with no incoming packets. -50103 pdp_context_reset (out_packet_count|1|1) - -# Reregister to data network - timed out with no incoming packets. -50104 pdp_reregister_network (out_packet_count|1|1) - -# PDP Setup failures -50105 pdp_setup_fail (cause|1|5), (cid|1|5), (network_type|1|5) - -# Call drops -50106 call_drop (cause|1|5), (cid|1|5), (network_type|1|5) - -# Data network registration failed after successful voice registration -50107 data_network_registration_fail (op_numeric|1|5), (cid|1|5) - -# Suspicious status of data connection while radio poweroff -50108 data_network_status_on_radio_off (dc_state|3), (enable|1|5) - -# 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) - -# GSM radio access technology switched -50112 gsm_rat_switched (cid|1|5), (network_from|1|5), (network_to|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) - -# db stats. 0 is query, 1 is write (may become more fine grained in the -# future) -52000 db_operation (name|3),(op_type|1|5),(time|2|3) - -# http request/response stats -52001 http_stats (useragent|3),(response|2|3),(processing|2|3),(tx|1|2),(rx|1|2) -60000 viewroot_draw (Draw time|1|3) -60001 viewroot_layout (Layout time|1|3) -60002 view_build_drawing_cache (View created drawing cache|1|5) -60003 view_use_drawing_cache (View drawn using bitmap cache|1|5) - -# 0 for screen off, 1 for screen on, 2 for key-guard done -70000 screen_toggled (screen_state|1|5) - -# 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) - -# aggregation service -70200 aggregation (aggregation time|2|3) -70201 aggregation_test (field1|1|2),(field2|1|2),(field3|1|2),(field4|1|2),(field5|1|2) - -# 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. diff --git a/logcat/event.logtags b/logcat/event.logtags new file mode 100644 index 0000000..f146738 --- /dev/null +++ b/logcat/event.logtags @@ -0,0 +1,171 @@ +# The entries in this file map a sparse set of log tag numbers to tag names. +# This is installed on the device, in /system/etc, and parsed by logcat. +# +# Tag numbers are decimal integers, from 0 to 2^31. (Let's leave the +# negative values alone for now.) +# +# Tag names are one or more ASCII letters and numbers or underscores, i.e. +# "[A-Z][a-z][0-9]_". Do not include spaces or punctuation (the former +# impacts log readability, the latter makes regex searches more annoying). +# +# Tag numbers and names are separated by whitespace. Blank lines and lines +# starting with '#' are ignored. +# +# Optionally, after the tag names can be put a description for the value(s) +# of the tag. Description are in the format +# (<name>|data type[|data unit]) +# Multiple values are separated by commas. +# +# The data type is a number from the following values: +# 1: int +# 2: long +# 3: string +# 4: list +# +# The data unit is a number taken from the following list: +# 1: Number of objects +# 2: Number of bytes +# 3: Number of milliseconds +# 4: Number of allocations +# 5: Id +# 6: Percent +# Default value for data of type int/long is 2 (bytes). +# +# TODO: generate ".java" and ".h" files with integer constants from this file. + +# These are used for testing, do not modify without updating +# tests/framework-tests/src/android/util/EventLogFunctionalTest.java. +42 answer (to life the universe etc|3) +314 pi +2718 e + +# "account" is the java hash of the account name +2720 sync (id|3),(event|1|5),(source|1|5),(account|1|5) + +# This event is logged when the location service uploads location data. +2740 location_controller +# This event is logged when someone is deciding to force a garbage collection +2741 force_gc (reason|3) +# This event is logged on each tickle +2742 tickle (authority|3) + +# contacts aggregation: time and number of contacts. +# count is negative for query phase, positive for merge phase +2747 contacts_aggregation (aggregation time|2|3), (count|1|1) + +# Device boot timings. We include monotonic clock values because the +# intrinsic event log times are wall-clock. +# +# Runtime starts: +3000 boot_progress_start (time|2|3) +# ZygoteInit class preloading starts: +3020 boot_progress_preload_start (time|2|3) +# ZygoteInit class preloading ends: +3030 boot_progress_preload_end (time|2|3) + +# dvm_gc_info: LIST (LONG, LONG, LONG) +# +# First LONG: +# +# [63] 1 +# [62-24] ASCII process identifier +# [23-12] GC time in ms +# [11- 0] Bytes freed +# +# Second LONG (aggregated heap info): +# +# [63-62] 10 +# [61-60] Reserved; must be zero +# [59-48] Objects freed +# [47-36] Actual size (current footprint) +# [35-24] Allowed size (current hard max) +# [23-12] Objects allocated +# [11- 0] Bytes allocated +# +# Third LONG (zygote heap info): +# +# [63-62] 11 +# [61-60] Reserved; must be zero +# [59-48] Soft limit +# [47-36] Actual size (current footprint) +# [35-24] Allowed size (current hard max) +# [23-12] Objects allocated +# [11- 0] Bytes allocated +# +# Fourth LONG: +# +# [63-48] Reserved; must be zero +# [47-36] dlmallocFootprint +# [35-24] mallinfo: total allocated space +# [23-12] External byte limit +# [11- 0] External bytes allocated +# +# See HeapDebug.c +# +20001 dvm_gc_info (custom|2),(custom|2),(custom|2),(custom|2) +20002 dvm_gc_madvise_info (total|1|2),(zygote|1|2) +20003 dvm_lock_sample (process|3),(main|1|5),(thread|3),(time|1|3),(file|3),(line|1|5),(sample_percent|1|6) + +75000 sqlite_mem_alarm_current (current|1|2) +75001 sqlite_mem_alarm_max (max|1|2) +75002 sqlite_mem_alarm_alloc_attempt (attempts|1|4) +75003 sqlite_mem_released (Memory released|1|2) +75004 sqlite_db_corrupt (Database file corrupt|3) + +50000 menu_item_selected (Menu type where 0 is options and 1 is context|1|5),(Menu item title|3) +50001 menu_opened (Menu type where 0 is options and 1 is context|1|5) + +# Wi-Fi network state changed: +# [31- 6] Reserved for future use +# [ 5- 0] Detailed state ordinal (as defined by NetworkInfo.DetailedState) +50021 wifi_network_state_changed (network_state|1|5) + +# Wi-Fi supplicant state changed: +# [31- 6] Reserved for future use +# [ 5- 0] Supplicant state ordinal (as defined by SupplicantState) +50022 wifi_supplicant_state_changed (supplicant_state|1|5) + +# Wi-Fi driver state changed: +# [31- 1] Reserved for future use +# [ 0- 0] Driver start (1) or stopped (0) +50023 wifi_driver_state_changed (driver_state|1|5) + +# Wi-Fi interface configuration state changed: +# [31- 1] Reserved for future use +# [ 0- 0] Interface configuration succeeded (1) or failed (0) +50024 wifi_interface_configuration_state_changed (IP_configuration|1|5) + +# Wi-Fi supplicant connection state changed: +# [31- 2] Reserved for future use +# [ 1- 0] Connected to supplicant (1) or disconnected from supplicant (0), +# or supplicant died (2) +50025 wifi_supplicant_connection_state_changed (connected|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) + +# Database operation samples. +# db: the filename of the database +# sql: the executed query (without query args) +# time: cpu time millis (not wall time), including lock acquisition +# blocking_package: if this is on a main thread, the package name, otherwise "" +# sample_percent: the percent likelihood this query was logged +52000 db_sample (db|3),(sql|3),(time|1|3),(blocking_package|3),(sample_percent|1|6) + +# http request/response stats +52001 http_stats (useragent|3),(response|2|3),(processing|2|3),(tx|1|2),(rx|1|2) +60000 viewroot_draw (Draw time|1|3) +60001 viewroot_layout (Layout time|1|3) +60002 view_build_drawing_cache (View created drawing cache|1|5) +60003 view_use_drawing_cache (View drawn using bitmap cache|1|5) + +# 0 for screen off, 1 for screen on, 2 for key-guard done +70000 screen_toggled (screen_state|1|5) + +# aggregation service +70200 aggregation (aggregation time|2|3) +70201 aggregation_test (field1|1|2),(field2|1|2),(field3|1|2),(field4|1|2),(field5|1|2) + +# 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. diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp index 3130a1c..5acdf77 100644 --- a/logcat/logcat.cpp +++ b/logcat/logcat.cpp @@ -24,12 +24,66 @@ #define DEFAULT_MAX_ROTATED_LOGS 4 static AndroidLogFormat * g_logformat; +static bool g_nonblock = false; +static int g_tail_lines = 0; /* logd prefixes records with a length field */ #define RECORD_LENGTH_FIELD_SIZE_BYTES sizeof(uint32_t) #define LOG_FILE_DIR "/dev/log/" +struct queued_entry_t { + union { + unsigned char buf[LOGGER_ENTRY_MAX_LEN + 1] __attribute__((aligned(4))); + struct logger_entry entry __attribute__((aligned(4))); + }; + queued_entry_t* next; + + queued_entry_t() { + next = NULL; + } +}; + +static int cmp(queued_entry_t* a, queued_entry_t* b) { + int n = a->entry.sec - b->entry.sec; + if (n != 0) { + return n; + } + return a->entry.nsec - b->entry.nsec; +} + +struct log_device_t { + char* device; + bool binary; + int fd; + bool printed; + char label; + + queued_entry_t* queue; + log_device_t* next; + + log_device_t(char* d, bool b, char l) { + device = d; + binary = b; + label = l; + queue = NULL; + next = NULL; + printed = false; + } + + void enqueue(queued_entry_t* entry) { + if (this->queue == NULL) { + this->queue = entry; + } else { + queued_entry_t** e = &this->queue; + while (*e && cmp(entry, *e) >= 0) { + e = &((*e)->next); + } + entry->next = *e; + *e = entry; + } + } +}; namespace android { @@ -40,8 +94,8 @@ static int g_logRotateSizeKBytes = 0; // 0 means "no log rotat static int g_maxRotatedLogs = DEFAULT_MAX_ROTATED_LOGS; // 0 means "unbounded" static int g_outFD = -1; static off_t g_outByteCount = 0; -static int g_isBinary = 0; static int g_printBinary = 0; +static int g_devCount = 0; static EventTagMap* g_eventTagMap = NULL; @@ -103,14 +157,14 @@ void printBinary(struct logger_entry *buf) } while (ret < 0 && errno == EINTR); } -static void processBuffer(struct logger_entry *buf) +static void processBuffer(log_device_t* dev, struct logger_entry *buf) { - int bytesWritten; + int bytesWritten = 0; int err; AndroidLogEntry entry; char binaryMsgBuf[1024]; - if (g_isBinary) { + if (dev->binary) { err = android_log_processBinaryLogBuffer(buf, &entry, g_eventTagMap, binaryMsgBuf, sizeof(binaryMsgBuf)); //printf(">>> pri=%d len=%d msg='%s'\n", @@ -118,15 +172,27 @@ static void processBuffer(struct logger_entry *buf) } else { err = android_log_processLogBuffer(buf, &entry); } - if (err < 0) + if (err < 0) { goto error; + } - bytesWritten = android_log_filterAndPrintLogLine( - g_logformat, g_outFD, &entry); + if (android_log_shouldPrintLine(g_logformat, entry.tag, entry.priority)) { + if (false && g_devCount > 1) { + binaryMsgBuf[0] = dev->label; + binaryMsgBuf[1] = ' '; + bytesWritten = write(g_outFD, binaryMsgBuf, 2); + if (bytesWritten < 0) { + perror("output error"); + exit(-1); + } + } - if (bytesWritten < 0) { - perror("output error"); - exit(-1); + bytesWritten = android_log_printLogLine(g_logformat, g_outFD, &entry); + + if (bytesWritten < 0) { + perror("output error"); + exit(-1); + } } g_outByteCount += bytesWritten; @@ -142,36 +208,142 @@ error: return; } -static void readLogLines(int logfd) -{ - while (1) { - unsigned char buf[LOGGER_ENTRY_MAX_LEN + 1] __attribute__((aligned(4))); - struct logger_entry *entry = (struct logger_entry *) buf; - int ret; +static void chooseFirst(log_device_t* dev, log_device_t** firstdev) { + for (*firstdev = NULL; dev != NULL; dev = dev->next) { + if (dev->queue != NULL && (*firstdev == NULL || cmp(dev->queue, (*firstdev)->queue) < 0)) { + *firstdev = dev; + } + } +} - ret = read(logfd, entry, LOGGER_ENTRY_MAX_LEN); - if (ret < 0) { - if (errno == EINTR) - continue; - if (errno == EAGAIN) - break; - perror("logcat read"); - exit(EXIT_FAILURE); +static void maybePrintStart(log_device_t* dev) { + if (!dev->printed) { + dev->printed = true; + if (g_devCount > 1 && !g_printBinary) { + char buf[1024]; + snprintf(buf, sizeof(buf), "--------- beginning of %s\n", dev->device); + if (write(g_outFD, buf, strlen(buf)) < 0) { + perror("output error"); + exit(-1); + } } - else if (!ret) { - fprintf(stderr, "read: Unexpected EOF!\n"); - exit(EXIT_FAILURE); + } +} + +static void skipNextEntry(log_device_t* dev) { + maybePrintStart(dev); + queued_entry_t* entry = dev->queue; + dev->queue = entry->next; + delete entry; +} + +static void printNextEntry(log_device_t* dev) { + maybePrintStart(dev); + if (g_printBinary) { + printBinary(&dev->queue->entry); + } else { + processBuffer(dev, &dev->queue->entry); + } + skipNextEntry(dev); +} + +static void readLogLines(log_device_t* devices) +{ + log_device_t* dev; + int max = 0; + int ret; + int queued_lines = 0; + bool sleep = true; + + int result; + fd_set readset; + + for (dev=devices; dev; dev = dev->next) { + if (dev->fd > max) { + max = dev->fd; } + } + + while (1) { + do { + timeval timeout = { 0, 5000 /* 5ms */ }; // If we oversleep it's ok, i.e. ignore EINTR. + FD_ZERO(&readset); + for (dev=devices; dev; dev = dev->next) { + FD_SET(dev->fd, &readset); + } + result = select(max + 1, &readset, NULL, NULL, sleep ? NULL : &timeout); + } while (result == -1 && errno == EINTR); + + if (result >= 0) { + for (dev=devices; dev; dev = dev->next) { + if (FD_ISSET(dev->fd, &readset)) { + queued_entry_t* entry = new queued_entry_t(); + /* NOTE: driver guarantees we read exactly one full entry */ + ret = read(dev->fd, entry->buf, LOGGER_ENTRY_MAX_LEN); + if (ret < 0) { + if (errno == EINTR) { + delete entry; + goto next; + } + if (errno == EAGAIN) { + delete entry; + break; + } + perror("logcat read"); + exit(EXIT_FAILURE); + } + else if (!ret) { + fprintf(stderr, "read: Unexpected EOF!\n"); + exit(EXIT_FAILURE); + } - /* NOTE: driver guarantees we read exactly one full entry */ + entry->entry.msg[entry->entry.len] = '\0'; - entry->msg[entry->len] = '\0'; + dev->enqueue(entry); + ++queued_lines; + } + } - if (g_printBinary) { - printBinary(entry); - } else { - (void) processBuffer(entry); + if (result == 0) { + // we did our short timeout trick and there's nothing new + // print everything we have and wait for more data + sleep = true; + while (true) { + chooseFirst(devices, &dev); + if (dev == NULL) { + break; + } + if (g_tail_lines == 0 || queued_lines <= g_tail_lines) { + printNextEntry(dev); + } else { + skipNextEntry(dev); + } + --queued_lines; + } + + // the caller requested to just dump the log and exit + if (g_nonblock) { + exit(0); + } + } else { + // print all that aren't the last in their list + sleep = false; + while (g_tail_lines == 0 || queued_lines > g_tail_lines) { + chooseFirst(devices, &dev); + if (dev == NULL || dev->queue->next == NULL) { + break; + } + if (g_tail_lines == 0) { + printNextEntry(dev); + } else { + skipNextEntry(dev); + } + --queued_lines; + } + } } +next: + ; } } @@ -228,6 +400,7 @@ static void show_help(const char *cmd) " brief process tag thread raw time threadtime long\n\n" " -c clear (flush) the entire log and exit\n" " -d dump the log and then exit (don't block)\n" + " -t <count> print only the most recent <count> lines (implies -d)\n" " -g get the size of the log's ring buffer and exit\n" " -b <buffer> request alternate ring buffer\n" " ('main' (default), 'radio', 'events')\n" @@ -275,16 +448,17 @@ static int setLogFormat(const char * formatString) extern "C" void logprint_run_tests(void); -int main (int argc, char **argv) +int main(int argc, char **argv) { - int logfd; int err; int hasSetLogFormat = 0; int clearLog = 0; int getLogSize = 0; int mode = O_RDONLY; - char *log_device = strdup("/dev/"LOGGER_LOG_MAIN); const char *forceFilters = NULL; + log_device_t* devices = NULL; + log_device_t* dev; + bool needBinary = false; g_logformat = android_log_format_new(); @@ -301,7 +475,7 @@ int main (int argc, char **argv) for (;;) { int ret; - ret = getopt(argc, argv, "cdgsQf:r::n:v:b:B"); + ret = getopt(argc, argv, "cdt:gsQf:r::n:v:b:B"); if (ret < 0) { break; @@ -319,21 +493,39 @@ int main (int argc, char **argv) break; case 'd': - mode |= O_NONBLOCK; + g_nonblock = true; + break; + + case 't': + g_nonblock = true; + g_tail_lines = atoi(optarg); break; case 'g': getLogSize = 1; break; - case 'b': - free(log_device); - log_device = - (char*) malloc(strlen(LOG_FILE_DIR) + strlen(optarg) + 1); - strcpy(log_device, LOG_FILE_DIR); - strcat(log_device, optarg); + case 'b': { + char* buf = (char*) malloc(strlen(LOG_FILE_DIR) + strlen(optarg) + 1); + strcpy(buf, LOG_FILE_DIR); + strcat(buf, optarg); - android::g_isBinary = (strcmp(optarg, "events") == 0); + bool binary = strcmp(optarg, "events") == 0; + if (binary) { + needBinary = true; + } + + if (devices) { + dev = devices; + while (dev->next) { + dev = dev->next; + } + dev->next = new log_device_t(buf, binary, optarg[0]); + } else { + devices = new log_device_t(buf, binary, optarg[0]); + } + android::g_devCount++; + } break; case 'B': @@ -460,6 +652,19 @@ int main (int argc, char **argv) } } + if (!devices) { + devices = new log_device_t(strdup("/dev/"LOGGER_LOG_MAIN), false, 'm'); + android::g_devCount = 1; + int accessmode = + (mode & O_RDONLY) ? R_OK : 0 + | (mode & O_WRONLY) ? W_OK : 0; + // only add this if it's available + if (0 == access("/dev/"LOGGER_LOG_SYSTEM, accessmode)) { + devices->next = new log_device_t(strdup("/dev/"LOGGER_LOG_SYSTEM), false, 's'); + android::g_devCount++; + } + } + if (android::g_logRotateSizeKBytes != 0 && android::g_outputFileName == NULL ) { @@ -516,42 +721,52 @@ int main (int argc, char **argv) } } - logfd = open(log_device, mode); - if (logfd < 0) { - fprintf(stderr, "Unable to open log device '%s': %s\n", - log_device, strerror(errno)); - exit(EXIT_FAILURE); - } - - if (clearLog) { - int ret; - ret = android::clearLog(logfd); - if (ret) { - perror("ioctl"); + dev = devices; + while (dev) { + dev->fd = open(dev->device, mode); + if (dev->fd < 0) { + fprintf(stderr, "Unable to open log device '%s': %s\n", + dev->device, strerror(errno)); exit(EXIT_FAILURE); } - return 0; - } - - if (getLogSize) { - int size, readable; - size = android::getLogSize(logfd); - if (size < 0) { - perror("ioctl"); - exit(EXIT_FAILURE); + if (clearLog) { + int ret; + ret = android::clearLog(dev->fd); + if (ret) { + perror("ioctl"); + exit(EXIT_FAILURE); + } } - readable = android::getLogReadableSize(logfd); - if (readable < 0) { - perror("ioctl"); - exit(EXIT_FAILURE); + if (getLogSize) { + int size, readable; + + size = android::getLogSize(dev->fd); + if (size < 0) { + perror("ioctl"); + exit(EXIT_FAILURE); + } + + readable = android::getLogReadableSize(dev->fd); + if (readable < 0) { + perror("ioctl"); + exit(EXIT_FAILURE); + } + + printf("%s: ring buffer is %dKb (%dKb consumed), " + "max entry is %db, max payload is %db\n", dev->device, + size / 1024, readable / 1024, + (int) LOGGER_ENTRY_MAX_LEN, (int) LOGGER_ENTRY_MAX_PAYLOAD); } - printf("ring buffer is %dKb (%dKb consumed), " - "max entry is %db, max payload is %db\n", - size / 1024, readable / 1024, - (int) LOGGER_ENTRY_MAX_LEN, (int) LOGGER_ENTRY_MAX_PAYLOAD); + dev = dev->next; + } + + if (getLogSize) { + return 0; + } + if (clearLog) { return 0; } @@ -559,10 +774,10 @@ int main (int argc, char **argv) //LOG_EVENT_LONG(11, 0x1122334455667788LL); //LOG_EVENT_STRING(0, "whassup, doc?"); - if (android::g_isBinary) + if (needBinary) android::g_eventTagMap = android_openEventTagMap(EVENT_TAG_MAP_FILE); - android::readLogLines(logfd); + android::readLogLines(devices); return 0; } diff --git a/rootdir/Android.mk b/rootdir/Android.mk index 3bb2262..7ac991c 100644 --- a/rootdir/Android.mk +++ b/rootdir/Android.mk @@ -8,7 +8,7 @@ copy_from := \ etc/hosts ifeq ($(TARGET_PRODUCT),generic) -copy_from += etc/vold.conf +copy_from += etc/vold.fstab endif # the /system/etc/init.goldfish.sh is needed to enable emulator support diff --git a/rootdir/etc/vold.conf b/rootdir/etc/vold.conf deleted file mode 100644 index 4e04509..0000000 --- a/rootdir/etc/vold.conf +++ /dev/null @@ -1,10 +0,0 @@ -## vold configuration file for the 'generic' target - -volume_sdcard { - ## This is the direct uevent device path to the SD slot on the device - media_path /devices/platform/goldfish_mmc.0/mmc_host/mmc0 - - media_type mmc - mount_point /sdcard - ums_path /devices/platform/usb_mass_storage/lun0 -} diff --git a/rootdir/etc/vold.fstab b/rootdir/etc/vold.fstab new file mode 100644 index 0000000..4aad8dc --- /dev/null +++ b/rootdir/etc/vold.fstab @@ -0,0 +1,24 @@ +## Vold 2.0 Generic fstab +## - San Mehat (san@android.com) +## + +####################### +## Regular device mount +## +## Format: dev_mount <label> <mount_point> <part> <sysfs_path1...> +## label - Label for the volume +## mount_point - Where the volume will be mounted +## part - Partition # (1 based), or 'auto' for first usable partition. +## <sysfs_path> - List of sysfs paths to source devices +###################### + +## Example of a standard sdcard mount for the emulator / Dream +# Mounts the first usable partition of the specified device +dev_mount sdcard /mnt/sdcard auto /devices/platform/goldfish_mmc.0 /devices/platform/msm_sdcc.2/mmc_host/mmc1 + +## Example of a dual card setup +# dev_mount left_sdcard /sdcard1 auto /devices/platform/goldfish_mmc.0 /devices/platform/msm_sdcc.2/mmc_host/mmc1 +# dev_mount right_sdcard /sdcard2 auto /devices/platform/goldfish_mmc.1 /devices/platform/msm_sdcc.3/mmc_host/mmc1 + +## Example of specifying a specific partition for mounts +# dev_mount sdcard /sdcard 2 /devices/platform/goldfish_mmc.0 /devices/platform/msm_sdcc.2/mmc_host/mmc1 diff --git a/rootdir/init.rc b/rootdir/init.rc index b0aa5f2..1e446f7 100644 --- a/rootdir/init.rc +++ b/rootdir/init.rc @@ -12,21 +12,44 @@ loglevel 3 export ANDROID_ROOT /system export ANDROID_ASSETS /system/app export ANDROID_DATA /data - export EXTERNAL_STORAGE /sdcard + export EXTERNAL_STORAGE /mnt/sdcard + export ASEC_MOUNTPOINT /mnt/asec export BOOTCLASSPATH /system/framework/core.jar:/system/framework/ext.jar:/system/framework/framework.jar:/system/framework/android.policy.jar:/system/framework/services.jar # Backward compatibility symlink /system/etc /etc symlink /sys/kernel/debug /d -# create mountpoints and mount tmpfs on sqlite_stmt_journals - mkdir /sdcard 0000 system system +# create mountpoints + mkdir /mnt 0775 root system + mkdir /mnt/sdcard 0000 system system + +# Create cgroup mount point for cpu accounting + mkdir /acct + mount cgroup none /acct cpuacct + mkdir /acct/uid + +# Backwards Compat - XXX: Going away in G* + symlink /mnt/sdcard /sdcard + mkdir /system mkdir /data 0771 system system mkdir /cache 0770 system cache mkdir /config 0500 root root - mkdir /sqlite_stmt_journals 01777 root root - mount tmpfs tmpfs /sqlite_stmt_journals size=4m + + # Directory for putting things only root should see. + mkdir /mnt/secure 0700 root root + + # Directory for staging bindmounts + mkdir /mnt/secure/staging 0700 root root + + # Directory-target for where the secure container + # imagefile directory will be bind-mounted + mkdir /mnt/secure/asec 0700 root root + + # Secure container public mount points. + mkdir /mnt/asec 0700 root system + mount tmpfs tmpfs /mnt/asec mode=0755,gid=1000 mount rootfs rootfs / ro remount @@ -92,18 +115,26 @@ loglevel 3 chmod 0770 /cache # This may have been created by the recovery system with odd permissions - chown system system /cache/recovery + chown system cache /cache/recovery chmod 0770 /cache/recovery #change permissions on vmallocinfo so we can grab it from bugreports chown root log /proc/vmallocinfo chmod 0440 /proc/vmallocinfo + #change permissions on kmsg & sysrq-trigger so bugreports can grab kthread stacks + chown root system /proc/kmsg + chmod 0440 /proc/kmsg + chown root system /proc/sysrq-trigger + chmod 0220 /proc/sysrq-trigger + # create basic filesystem structure mkdir /data/misc 01771 system misc mkdir /data/misc/bluetoothd 0770 bluetooth bluetooth + mkdir /data/misc/bluetooth 0770 system system mkdir /data/misc/keystore 0700 keystore keystore mkdir /data/misc/vpn 0770 system system + mkdir /data/misc/systemkeys 0700 system system mkdir /data/misc/vpn/profiles 0770 system system # give system access to wpa_supplicant.conf for backup and restore mkdir /data/misc/wifi 0770 wifi wifi @@ -116,7 +147,6 @@ loglevel 3 mkdir /data/app 0771 system system mkdir /data/property 0700 root root - # create dalvik-cache and double-check the perms mkdir /data/dalvik-cache 0771 system system chown system system /data/dalvik-cache @@ -255,13 +285,10 @@ service servicemanager /system/bin/servicemanager service vold /system/bin/vold socket vold stream 0660 root mount + ioprio be 2 -service nexus /system/bin/nexus - socket nexus stream 0660 root system - disabled - -#service mountd /system/bin/mountd -# socket mountd stream 0660 root mount +service netd /system/bin/netd + socket netd stream 0660 root system service debuggerd /system/bin/debuggerd @@ -279,12 +306,8 @@ service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-sys service media /system/bin/mediaserver user media - group system audio camera graphics inet net_bt net_bt_admin - -service bootsound /system/bin/playmp3 - user media - group audio - oneshot + group system audio camera graphics inet net_bt net_bt_admin net_raw + ioprio rt 4 service bootanim /system/bin/bootanimation user graphics diff --git a/run-as/Android.mk b/run-as/Android.mk new file mode 100644 index 0000000..326f5af --- /dev/null +++ b/run-as/Android.mk @@ -0,0 +1,12 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= run-as.c package.c + +LOCAL_MODULE:= run-as + +LOCAL_FORCE_STATIC_EXECUTABLE := true + +LOCAL_STATIC_LIBRARIES := libc + +include $(BUILD_EXECUTABLE) diff --git a/run-as/NOTICE b/run-as/NOTICE new file mode 100644 index 0000000..c5b1efa --- /dev/null +++ b/run-as/NOTICE @@ -0,0 +1,190 @@ + + 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 + diff --git a/run-as/package.c b/run-as/package.c new file mode 100644 index 0000000..46f8239 --- /dev/null +++ b/run-as/package.c @@ -0,0 +1,471 @@ +/* +** +** Copyright 2010, 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 <fcntl.h> +#include <unistd.h> +#include <sys/stat.h> +#include <private/android_filesystem_config.h> +#include "package.h" + +/* + * WARNING WARNING WARNING WARNING + * + * The following code runs as root on production devices, before + * the run-as command has dropped the uid/gid. Hence be very + * conservative and keep in mind the following: + * + * - Performance does not matter here, clarity and safety of the code + * does however. Documentation is a must. + * + * - Avoid calling C library functions with complex implementations + * like malloc() and printf(). You want to depend on simple system + * calls instead, which behaviour is not going to be altered in + * unpredictible ways by environment variables or system properties. + * + * - Do not trust user input and/or the filesystem whenever possible. + * + */ + +/* The file containing the list of installed packages on the system */ +#define PACKAGES_LIST_FILE "/data/system/packages.list" + +/* This should be large enough to hold the content of the package database file */ +#define PACKAGES_LIST_BUFFER_SIZE 8192 + +/* Copy 'srclen' string bytes from 'src' into buffer 'dst' of size 'dstlen' + * This function always zero-terminate the destination buffer unless + * 'dstlen' is 0, even in case of overflow. + */ +static void +string_copy(char* dst, size_t dstlen, const char* src, size_t srclen) +{ + const char* srcend = src + srclen; + const char* dstend = dst + dstlen; + + if (dstlen == 0) + return; + + dstend--; /* make room for terminating zero */ + + while (dst < dstend && src < srcend && *src != '\0') + *dst++ = *src++; + + *dst = '\0'; /* zero-terminate result */ +} + +/* Read up to 'buffsize' bytes into 'buff' from the file + * named 'filename'. Return byte length on success, or -1 + * on error. + */ +static int +read_file(const char* filename, char* buff, size_t buffsize) +{ + int fd, len, old_errno; + + /* check the input buffer size */ + if (buffsize >= INT_MAX) { + errno = EINVAL; + return -1; + } + + /* open the file for reading */ + do { + fd = open(filename, O_RDONLY); + } while (fd < 0 && errno == EINTR); + + if (fd < 0) + return -1; + + /* read the content */ + do { + len = read(fd, buff, buffsize); + } while (len < 0 && errno == EINTR); + + /* close the file, preserve old errno for better diagnostics */ + old_errno = errno; + close(fd); + errno = old_errno; + + return len; +} + +/* Check that a given directory: + * - exists + * - is owned by a given uid/gid + * - is a real directory, not a symlink + * - isn't readable or writable by others + * + * Return 0 on success, or -1 on error. + * errno is set to EINVAL in case of failed check. + */ +static int +check_directory_ownership(const char* path, uid_t uid) +{ + int ret; + struct stat st; + + do { + ret = lstat(path, &st); + } while (ret < 0 && errno == EINTR); + + if (ret < 0) + return -1; + + /* must be a real directory, not a symlink */ + if (!S_ISDIR(st.st_mode)) + goto BAD; + + /* must be owned by specific uid/gid */ + if (st.st_uid != uid || st.st_gid != uid) + goto BAD; + + /* must not be readable or writable by others */ + if ((st.st_mode & (S_IROTH|S_IWOTH)) != 0) + goto BAD; + + /* everything ok */ + return 0; + +BAD: + errno = EINVAL; + return -1; +} + +/* This function is used to check the data directory path for safety. + * We check that every sub-directory is owned by the 'system' user + * and exists and is not a symlink. We also check that the full directory + * path is properly owned by the user ID. + * + * Return 0 on success, -1 on error. + */ +int +check_data_path(const char* dataPath, uid_t uid) +{ + int nn; + + /* the path should be absolute */ + if (dataPath[0] != '/') { + errno = EINVAL; + return -1; + } + + /* look for all sub-paths, we do that by finding + * directory separators in the input path and + * checking each sub-path independently + */ + for (nn = 1; dataPath[nn] != '\0'; nn++) + { + char subpath[PATH_MAX]; + + /* skip non-separator characters */ + if (dataPath[nn] != '/') + continue; + + /* handle trailing separator case */ + if (dataPath[nn+1] == '\0') { + break; + } + + /* found a separator, check that dataPath is not too long. */ + if (nn >= (int)(sizeof subpath)) { + errno = EINVAL; + return -1; + } + + /* reject any '..' subpath */ + if (nn >= 3 && + dataPath[nn-3] == '/' && + dataPath[nn-2] == '.' && + dataPath[nn-1] == '.') { + errno = EINVAL; + return -1; + } + + /* copy to 'subpath', then check ownership */ + memcpy(subpath, dataPath, nn); + subpath[nn] = '\0'; + + if (check_directory_ownership(subpath, AID_SYSTEM) < 0) + return -1; + } + + /* All sub-paths were checked, now verify that the full data + * directory is owned by the application uid + */ + if (check_directory_ownership(dataPath, uid) < 0) + return -1; + + /* all clear */ + return 0; +} + +/* Return TRUE iff a character is a space or tab */ +static inline int +is_space(char c) +{ + return (c == ' ' || c == '\t'); +} + +/* Skip any space or tab character from 'p' until 'end' is reached. + * Return new position. + */ +static const char* +skip_spaces(const char* p, const char* end) +{ + while (p < end && is_space(*p)) + p++; + + return p; +} + +/* Skip any non-space and non-tab character from 'p' until 'end'. + * Return new position. + */ +static const char* +skip_non_spaces(const char* p, const char* end) +{ + while (p < end && !is_space(*p)) + p++; + + return p; +} + +/* Find the first occurence of 'ch' between 'p' and 'end' + * Return its position, or 'end' if none is found. + */ +static const char* +find_first(const char* p, const char* end, char ch) +{ + while (p < end && *p != ch) + p++; + + return p; +} + +/* Check that the non-space string starting at 'p' and eventually + * ending at 'end' equals 'name'. Return new position (after name) + * on success, or NULL on failure. + * + * This function fails is 'name' is NULL, empty or contains any space. + */ +static const char* +compare_name(const char* p, const char* end, const char* name) +{ + /* 'name' must not be NULL or empty */ + if (name == NULL || name[0] == '\0' || p == end) + return NULL; + + /* compare characters to those in 'name', excluding spaces */ + while (*name) { + /* note, we don't check for *p == '\0' since + * it will be caught in the next conditional. + */ + if (p >= end || is_space(*p)) + goto BAD; + + if (*p != *name) + goto BAD; + + p++; + name++; + } + + /* must be followed by end of line or space */ + if (p < end && !is_space(*p)) + goto BAD; + + return p; + +BAD: + return NULL; +} + +/* Parse one or more whitespace characters starting from '*pp' + * until 'end' is reached. Updates '*pp' on exit. + * + * Return 0 on success, -1 on failure. + */ +static int +parse_spaces(const char** pp, const char* end) +{ + const char* p = *pp; + + if (p >= end || !is_space(*p)) { + errno = EINVAL; + return -1; + } + p = skip_spaces(p, end); + *pp = p; + return 0; +} + +/* Parse a positive decimal number starting from '*pp' until 'end' + * is reached. Adjust '*pp' on exit. Return decimal value or -1 + * in case of error. + * + * If the value is larger than INT_MAX, -1 will be returned, + * and errno set to EOVERFLOW. + * + * If '*pp' does not start with a decimal digit, -1 is returned + * and errno set to EINVAL. + */ +static int +parse_positive_decimal(const char** pp, const char* end) +{ + const char* p = *pp; + int value = 0; + int overflow = 0; + + if (p >= end || *p < '0' || *p > '9') { + errno = EINVAL; + return -1; + } + + while (p < end) { + int ch = *p; + unsigned d = (unsigned)(ch - '0'); + int val2; + + if (d >= 10U) /* d is unsigned, no lower bound check */ + break; + + val2 = value*10 + (int)d; + if (val2 < value) + overflow = 1; + value = val2; + p++; + } + *pp = p; + + if (overflow) { + errno = EOVERFLOW; + value = -1; + } + return value; + +BAD: + *pp = p; + return -1; +} + +/* Read the system's package database and extract information about + * 'pkgname'. Return 0 in case of success, or -1 in case of error. + * + * If the package is unknown, return -1 and set errno to ENOENT + * If the package database is corrupted, return -1 and set errno to EINVAL + */ +int +get_package_info(const char* pkgName, PackageInfo *info) +{ + static char buffer[PACKAGES_LIST_BUFFER_SIZE]; + int buffer_len; + const char* p; + const char* buffer_end; + int result; + + info->uid = 0; + info->isDebuggable = 0; + info->dataDir[0] = '\0'; + + buffer_len = read_file(PACKAGES_LIST_FILE, buffer, sizeof buffer); + if (buffer_len < 0) + return -1; + + p = buffer; + buffer_end = buffer + buffer_len; + + /* expect the following format on each line of the control file: + * + * <pkgName> <uid> <debugFlag> <dataDir> + * + * where: + * <pkgName> is the package's name + * <uid> is the application-specific user Id (decimal) + * <debugFlag> is 1 if the package is debuggable, or 0 otherwise + * <dataDir> is the path to the package's data directory (e.g. /data/data/com.example.foo) + * + * The file is generated in com.android.server.PackageManagerService.Settings.writeLP() + */ + + while (p < buffer_end) { + /* find end of current line and start of next one */ + const char* end = find_first(p, buffer_end, '\n'); + const char* next = (end < buffer_end) ? end + 1 : buffer_end; + const char* q; + int uid, debugFlag; + + /* first field is the package name */ + p = compare_name(p, end, pkgName); + if (p == NULL) + goto NEXT_LINE; + + /* skip spaces */ + if (parse_spaces(&p, end) < 0) + goto BAD_FORMAT; + + /* second field is the pid */ + uid = parse_positive_decimal(&p, end); + if (uid < 0) + return -1; + + info->uid = (uid_t) uid; + + /* skip spaces */ + if (parse_spaces(&p, end) < 0) + goto BAD_FORMAT; + + /* third field is debug flag (0 or 1) */ + debugFlag = parse_positive_decimal(&p, end); + switch (debugFlag) { + case 0: + info->isDebuggable = 0; + break; + case 1: + info->isDebuggable = 1; + break; + default: + goto BAD_FORMAT; + } + + /* skip spaces */ + if (parse_spaces(&p, end) < 0) + goto BAD_FORMAT; + + /* fourth field is data directory path and must not contain + * spaces. + */ + q = skip_non_spaces(p, end); + if (q == p) + goto BAD_FORMAT; + + string_copy(info->dataDir, sizeof info->dataDir, p, q - p); + + /* Ignore the rest */ + return 0; + + NEXT_LINE: + p = next; + } + + /* the package is unknown */ + errno = ENOENT; + return -1; + +BAD_FORMAT: + errno = EINVAL; + return -1; +} diff --git a/run-as/package.h b/run-as/package.h new file mode 100644 index 0000000..852af06 --- /dev/null +++ b/run-as/package.h @@ -0,0 +1,41 @@ +/* +** +** Copyright 2010, 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 RUN_AS_PACKAGE_H +#define RUN_AS_PACKAGE_H + +#include <limits.h> +#include <sys/types.h> + +typedef enum { + PACKAGE_IS_DEBUGGABLE = 0, + PACKAGE_IS_NOT_DEBUGGABLE, + PACKAGE_IS_UNKNOWN, +} PackageStatus; + +typedef struct { + uid_t uid; + char isDebuggable; + char dataDir[PATH_MAX]; +} PackageInfo; + +/* see documentation in package.c for these functiosn */ + +extern int get_package_info(const char* packageName, PackageInfo* info); + +extern int check_data_path(const char* dataDir, uid_t uid); + +#endif /* RUN_AS_PACKAGE_H */ diff --git a/run-as/run-as.c b/run-as/run-as.c new file mode 100644 index 0000000..d2a44e1 --- /dev/null +++ b/run-as/run-as.c @@ -0,0 +1,178 @@ +/* +** +** Copyright 2010, 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 PROGNAME "run-as" +#define LOG_TAG PROGNAME + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <dirent.h> +#include <errno.h> +#include <unistd.h> +#include <time.h> +#include <stdarg.h> + +#include <private/android_filesystem_config.h> +#include "package.h" + +/* + * WARNING WARNING WARNING WARNING + * + * This program runs as set-uid root on Android production devices. + * Be very conservative when modifying it to avoid any serious + * security issue. Keep in mind the following: + * + * - This program should only run for the 'root' or 'shell' users + * + * - Statically link against the C library, and avoid anything that + * is more complex than simple system calls until the uid/gid has + * been dropped to that of a normal user or you are sure to exit. + * + * This avoids depending on environment variables, system properties + * and other external factors that may affect the C library in + * unpredictable ways. + * + * - Do not trust user input and/or the filesystem whenever possible. + * + * Read README.TXT for more details. + * + * + * + * The purpose of this program is to run a command as a specific + * application user-id. Typical usage is: + * + * run-as <package-name> <command> <args> + * + * The 'run-as' binary is setuid, but will check the following: + * + * - that it is invoked from the 'shell' or 'root' user (abort otherwise) + * - that '<package-name>' is the name of an installed and debuggable package + * - that the package's data directory is well-formed (see package.c) + * + * If so, it will cd to the package's data directory, drop to the application's + * user id / group id then run the command there. + * + * This can be useful for a number of different things on production devices: + * + * - Allow application developers to look at their own applicative data + * during development. + * + * - Run the 'gdbserver' binary executable to allow native debugging + */ + +static void +usage(void) +{ + const char* str = "Usage: " PROGNAME " <package-name> <command> [<args>]\n\n"; + write(1, str, strlen(str)); + exit(1); +} + + +static void +panic(const char* format, ...) +{ + va_list args; + + fprintf(stderr, "%s: ", PROGNAME); + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + exit(1); +} + + +int main(int argc, char **argv) +{ + const char* pkgname; + int myuid, uid, gid; + PackageInfo info; + + /* check arguments */ + if (argc < 2) + usage(); + + /* check userid of caller - must be 'shell' or 'root' */ + myuid = getuid(); + if (myuid != AID_SHELL && myuid != AID_ROOT) { + panic("only 'shell' or 'root' users can run this program\n"); + } + + /* retrieve package information from system */ + pkgname = argv[1]; + if (get_package_info(pkgname, &info) < 0) { + panic("Package '%s' is unknown\n", pkgname); + return 1; + } + + /* reject system packages */ + if (info.uid < AID_APP) { + panic("Package '%s' is not an application\n", pkgname); + return 1; + } + + /* reject any non-debuggable package */ + if (!info.isDebuggable) { + panic("Package '%s' is not debuggable\n", pkgname); + return 1; + } + + /* check that the data directory path is valid */ + if (check_data_path(info.dataDir, info.uid) < 0) { + panic("Package '%s' has corrupt installation\n", pkgname); + return 1; + } + + /* then move to it */ + { + int ret; + do { + ret = chdir(info.dataDir); + } while (ret < 0 && errno == EINTR); + + if (ret < 0) { + panic("Could not cd to package's data directory: %s\n", strerror(errno)); + return 1; + } + } + + /* Ensure that we change all real/effective/saved IDs at the + * same time to avoid nasty surprises. + */ + uid = gid = info.uid; + if(setresgid(gid,gid,gid) || setresuid(uid,uid,uid)) { + panic("Permission denied\n"); + return 1; + } + + /* User specified command for exec. */ + if (argc >= 3 ) { + if (execvp(argv[2], argv+2) < 0) { + panic("exec failed for %s Error:%s\n", argv[2], strerror(errno)); + return -errno; + } + } + + /* Default exec shell. */ + execlp("/system/bin/sh", "sh", NULL); + + panic("exec failed\n"); + return 1; +} diff --git a/sh/miscbltin.c b/sh/miscbltin.c index 1a8e252..d89029a 100644 --- a/sh/miscbltin.c +++ b/sh/miscbltin.c @@ -277,8 +277,6 @@ umaskcmd(int argc, char **argv) return 0; } -typedef unsigned long rlim_t; - #if 1 /* * ulimit builtin diff --git a/toolbox/Android.mk b/toolbox/Android.mk index bf7cfde..05b2a34 100644 --- a/toolbox/Android.mk +++ b/toolbox/Android.mk @@ -51,7 +51,9 @@ TOOLS := \ iftop \ id \ uptime \ - vmstat + vmstat \ + nandread \ + ionice LOCAL_SRC_FILES:= \ toolbox.c \ diff --git a/toolbox/chown.c b/toolbox/chown.c index 13617db..e9d108b 100644 --- a/toolbox/chown.c +++ b/toolbox/chown.c @@ -35,19 +35,29 @@ int chown_main(int argc, char **argv) gid_t gid = -1; // passing -1 to chown preserves current group pw = getpwnam(user); - if (pw == NULL) { - fprintf(stderr, "No such user '%s'\n", user); - return 10; + if (pw != NULL) { + uid = pw->pw_uid; + } else { + char* endptr; + uid = (int) strtoul(user, &endptr, 0); + if (endptr == user) { // no conversion + fprintf(stderr, "No such user '%s'\n", user); + return 10; + } } - uid = pw->pw_uid; if (group != NULL) { grp = getgrnam(group); - if (grp == NULL) { - fprintf(stderr, "No such group '%s'\n", group); - return 10; + if (grp != NULL) { + gid = grp->gr_gid; + } else { + char* endptr; + gid = (int) strtoul(group, &endptr, 0); + if (endptr == group) { // no conversion + fprintf(stderr, "No such group '%s'\n", group); + return 10; + } } - gid = grp->gr_gid; } for (i = 2; i < argc; i++) { @@ -59,4 +69,3 @@ int chown_main(int argc, char **argv) return 0; } - diff --git a/toolbox/ionice.c b/toolbox/ionice.c new file mode 100644 index 0000000..4a182f2 --- /dev/null +++ b/toolbox/ionice.c @@ -0,0 +1,57 @@ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> + +#include <cutils/iosched_policy.h> + +static char *classes[] = {"none", "rt", "be", "idle", NULL}; + +int ionice_main(int argc, char *argv[]) +{ + IoSchedClass clazz = IoSchedClass_NONE; + int ioprio = 0; + int pid; + + if(argc != 2 && argc != 4) { + fprintf(stderr, "usage: ionice <pid> [none|rt|be|idle] [prio]\n"); + return 1; + } + + if (!(pid = atoi(argv[1]))) { + fprintf(stderr, "Invalid pid specified\n"); + return 1; + } + + if (argc == 2) { + if (android_get_ioprio(pid, &clazz, &ioprio)) { + fprintf(stderr, "Failed to read priority (%s)\n", strerror(errno)); + return 1; + } + fprintf(stdout, "Pid %d, class %s (%d), prio %d\n", pid, classes[clazz], clazz, ioprio); + return 0; + } + + if (!strcmp(argv[2], "none")) { + clazz = IoSchedClass_NONE; + } else if (!strcmp(argv[2], "rt")) { + clazz = IoSchedClass_RT; + } else if (!strcmp(argv[2], "be")) { + clazz = IoSchedClass_BE; + } else if (!strcmp(argv[2], "idle")) { + clazz = IoSchedClass_IDLE; + } else { + fprintf(stderr, "Unsupported class '%s'\n", argv[2]); + return 1; + } + + ioprio = atoi(argv[3]); + + printf("Setting pid %d i/o class to %d, prio %d\n", pid, clazz, ioprio); + if (android_set_ioprio(pid, clazz, ioprio)) { + fprintf(stderr, "Failed to set priority (%s)\n", strerror(errno)); + return 1; + } + + return 0; +} diff --git a/toolbox/ls.c b/toolbox/ls.c index aa0113b..6c8de7a 100644 --- a/toolbox/ls.c +++ b/toolbox/ls.c @@ -210,15 +210,50 @@ static void group2str(unsigned gid, char *out) } } -static int listfile_size(const char *path, int flags) +static int show_total_size(const char *dirname, DIR *d, int flags) { + struct dirent *de; + char tmp[1024]; struct stat s; + int sum = 0; + + /* run through the directory and sum up the file block sizes */ + while ((de = readdir(d)) != 0) { + if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0) + continue; + if (de->d_name[0] == '.' && (flags & LIST_ALL) == 0) + continue; + + if (strcmp(dirname, "/") == 0) + snprintf(tmp, sizeof(tmp), "/%s", de->d_name); + else + snprintf(tmp, sizeof(tmp), "%s/%s", dirname, de->d_name); + + if (lstat(tmp, &s) < 0) { + fprintf(stderr, "stat failed on %s: %s\n", tmp, strerror(errno)); + rewinddir(d); + return -1; + } + + sum += s.st_blocks / 2; + } + + printf("total %d\n", sum); + rewinddir(d); + return 0; +} - if (lstat(path, &s) < 0) +static int listfile_size(const char *path, const char *filename, int flags) +{ + struct stat s; + + if (lstat(path, &s) < 0) { + fprintf(stderr, "lstat '%s' failed: %s\n", path, strerror(errno)); return -1; + } /* blocks are 512 bytes, we want output to be KB */ - printf("%lld %s\n", s.st_blocks / 2, path); + printf("%lld %s\n", s.st_blocks / 2, filename); return 0; } @@ -313,7 +348,7 @@ static int listfile(const char *dirname, const char *filename, int flags) if ((flags & LIST_LONG) != 0) { return listfile_long(pathname, flags); } else /*((flags & LIST_SIZE) != 0)*/ { - return listfile_size(pathname, flags); + return listfile_size(pathname, filename, flags); } } @@ -330,6 +365,10 @@ static int listdir(const char *name, int flags) return -1; } + if ((flags & LIST_SIZE) != 0) { + show_total_size(name, d, flags); + } + while((de = readdir(d)) != 0){ if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) continue; if(de->d_name[0] == '.' && (flags & LIST_ALL) == 0) continue; diff --git a/toolbox/nandread.c b/toolbox/nandread.c new file mode 100644 index 0000000..9644973 --- /dev/null +++ b/toolbox/nandread.c @@ -0,0 +1,286 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <errno.h> +#include <fcntl.h> + +#include <mtd/mtd-user.h> +#include <sys/ioctl.h> + +static int test_empty(const char *buf, size_t size) +{ + while(size--) { + if (*buf++ != 0xff) + return 0; + } + return 1; +} + +int nandread_main(int argc, char **argv) +{ + char *devname = NULL; + char *filename = NULL; + char *statusfilename = NULL; + char *statusext = ".stat"; + int fd; + int outfd = -1; + FILE *statusfile = NULL; + int ret; + int verbose = 0; + void *buffer; + loff_t pos, opos, end, bpos; + loff_t start = 0, len = 0; + int c; + int i; + int empty_pages = 0; + int page_count = 0; + int bad_block; + int rawmode = 0; + uint32_t *oob_data; + uint8_t *oob_fixed; + size_t spare_size = 64; + struct mtd_info_user mtdinfo; + struct mtd_ecc_stats initial_ecc, last_ecc, ecc; + struct mtd_oob_buf oobbuf; + struct nand_ecclayout ecclayout; + + do { + c = getopt(argc, argv, "d:f:s:S:L:Rhv"); + if (c == EOF) + break; + switch (c) { + case 'd': + devname = optarg; + break; + case 'f': + filename = optarg; + break; + case 's': + spare_size = atoi(optarg); + break; + case 'S': + start = strtoll(optarg, NULL, 0); + break; + case 'L': + len = strtoll(optarg, NULL, 0); + break; + case 'R': + rawmode = 1; + break; + case 'v': + verbose++; + break; + case 'h': + fprintf(stderr, "%s [-d <dev>] [-f file] [-s sparesize] [-vh]\n" + " -d <dev> Read from <dev>\n" + " -f <file> Write to <file>\n" + " -s <size> Number of spare bytes in file (default 64)\n" + " -R Raw mode\n" + " -S <start> Start offset (default 0)\n" + " -L <len> Length (default 0)\n" + " -v Print info\n" + " -h Print help\n", argv[0]); + return -1; + case '?': + fprintf(stderr, "%s: invalid option -%c\n", + argv[0], optopt); + exit(1); + } + } while (1); + + if (optind < argc) { + fprintf(stderr, "%s: extra arguments\n", argv[0]); + return 1; + } + if (!devname) { + fprintf(stderr, "%s: specify device name\n", argv[0]); + return 1; + } + + fd = open(devname, O_RDONLY); + if (fd < 0) { + fprintf(stderr, "cannot open %s, %s\n", devname, strerror(errno)); + return 1; + } + + if (filename) { + outfd = creat(filename, 0666); + if (outfd < 0) { + fprintf(stderr, "cannot open %s, %s\n", filename, strerror(errno)); + return 1; + } + statusfilename = malloc(strlen(filename) + strlen(statusext) + 1); + strcpy(statusfilename, filename); + strcat(statusfilename, statusext); + statusfile = fopen(statusfilename, "w+"); + if (!statusfile) { + fprintf(stderr, "cannot open %s, %s\n", statusfilename, strerror(errno)); + return 1; + } + } + + ret = ioctl(fd, MEMGETINFO, &mtdinfo); + if (ret) { + fprintf(stderr, "failed get mtd info for %s, %s\n", + devname, strerror(errno)); + return 1; + } + + if (verbose) { + printf("size: %u\n", mtdinfo.size); + printf("erase size: %u\n", mtdinfo.erasesize); + printf("write size: %u\n", mtdinfo.writesize); + printf("oob size: %u\n", mtdinfo.oobsize); + } + + buffer = malloc(mtdinfo.writesize + mtdinfo.oobsize + spare_size); + if (!buffer) { + fprintf(stderr, "failed allocate readbuffer size %u\n", + mtdinfo.writesize + mtdinfo.oobsize); + return 1; + } + + oobbuf.length = mtdinfo.oobsize; + oob_data = (uint32_t *)((uint8_t *)buffer + mtdinfo.writesize); + memset(oob_data, 0xff, mtdinfo.oobsize + spare_size); + oobbuf.ptr = (uint8_t *)oob_data + spare_size; + + ret = ioctl(fd, ECCGETLAYOUT, &ecclayout); + if (ret) { + fprintf(stderr, "failed get ecc layout for %s, %s\n", + devname, strerror(errno)); + return 1; + } + if (verbose) { + printf("ecc bytes: %u\n", ecclayout.eccbytes); + printf("oobavail: %u\n", ecclayout.oobavail); + } + if (ecclayout.oobavail > spare_size) + printf("oobavail, %d > image spare size, %d\n", ecclayout.oobavail, spare_size); + + ret = ioctl(fd, ECCGETSTATS, &initial_ecc); + if (ret) { + fprintf(stderr, "failed get ecc stats for %s, %s\n", + devname, strerror(errno)); + return 1; + } + last_ecc = initial_ecc; + + if (verbose) { + printf("initial ecc corrected: %u\n", initial_ecc.corrected); + printf("initial ecc failed: %u\n", initial_ecc.failed); + printf("initial ecc badblocks: %u\n", initial_ecc.badblocks); + printf("initial ecc bbtblocks: %u\n", initial_ecc.bbtblocks); + } + + if (rawmode) { + rawmode = mtdinfo.oobsize; + ret = ioctl(fd, MTDFILEMODE, MTD_MODE_RAW); + if (ret) { + fprintf(stderr, "failed set raw mode for %s, %s\n", + devname, strerror(errno)); + return 1; + } + } + + end = len ? (start + len) : mtdinfo.size; + for (pos = start, opos = 0; pos < end; pos += mtdinfo.writesize) { + bad_block = 0; + if (verbose > 3) + printf("reading at %llx\n", pos); + lseek64(fd, pos, SEEK_SET); + ret = read(fd, buffer, mtdinfo.writesize + rawmode); + if (ret < (int)mtdinfo.writesize) { + fprintf(stderr, "short read at %llx, %d\n", pos, ret); + bad_block = 2; + } + if (!rawmode) { + oobbuf.start = pos; + ret = ioctl(fd, MEMREADOOB, &oobbuf); + if (ret) { + fprintf(stderr, "failed to read oob data at %llx, %d\n", pos, ret); + bad_block = 2; + } + } + ret = ioctl(fd, ECCGETSTATS, &ecc); + if (ret) { + fprintf(stderr, "failed get ecc stats for %s, %s\n", + devname, strerror(errno)); + return 1; + } + bpos = pos / mtdinfo.erasesize * mtdinfo.erasesize; + ret = ioctl(fd, MEMGETBADBLOCK, &bpos); + if (ret && errno != EOPNOTSUPP) { + printf("badblock at %llx\n", pos); + bad_block = 1; + } + if (ecc.corrected != last_ecc.corrected) + printf("ecc corrected, %u, at %llx\n", ecc.corrected - last_ecc.corrected, pos); + if (ecc.failed != last_ecc.failed) + printf("ecc failed, %u, at %llx\n", ecc.failed - last_ecc.failed, pos); + if (ecc.badblocks != last_ecc.badblocks) + printf("ecc badblocks, %u, at %llx\n", ecc.badblocks - last_ecc.badblocks, pos); + if (ecc.bbtblocks != last_ecc.bbtblocks) + printf("ecc bbtblocks, %u, at %llx\n", ecc.bbtblocks - last_ecc.bbtblocks, pos); + + if (!rawmode) { + oob_fixed = (uint8_t *)oob_data; + for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES; i++) { + int len = ecclayout.oobfree[i].length; + if (oob_fixed + len > oobbuf.ptr) + len = oobbuf.ptr - oob_fixed; + if (len) { + memcpy(oob_fixed, oobbuf.ptr + ecclayout.oobfree[i].offset, len); + oob_fixed += len; + } + } + } + + if (outfd >= 0) { + ret = write(outfd, buffer, mtdinfo.writesize + spare_size); + if (ret < (int)(mtdinfo.writesize + spare_size)) { + fprintf(stderr, "short write at %llx, %d\n", pos, ret); + close(outfd); + outfd = -1; + } + if (ecc.corrected != last_ecc.corrected) + fprintf(statusfile, "%08llx: ecc corrected\n", opos); + if (ecc.failed != last_ecc.failed) + fprintf(statusfile, "%08llx: ecc failed\n", opos); + if (bad_block == 1) + fprintf(statusfile, "%08llx: badblock\n", opos); + if (bad_block == 2) + fprintf(statusfile, "%08llx: read error\n", opos); + opos += mtdinfo.writesize + spare_size; + } + + last_ecc = ecc; + page_count++; + if (test_empty(buffer, mtdinfo.writesize + mtdinfo.oobsize + spare_size)) + empty_pages++; + else if (verbose > 2 || (verbose > 1 && !(pos & (mtdinfo.erasesize - 1)))) + printf("page at %llx (%d oobbytes): %08x %08x %08x %08x " + "%08x %08x %08x %08x\n", pos, oobbuf.start, + oob_data[0], oob_data[1], oob_data[2], oob_data[3], + oob_data[4], oob_data[5], oob_data[6], oob_data[7]); + } + + if (outfd >= 0) { + fprintf(statusfile, "read %d pages, %d empty\n", page_count, empty_pages); + fprintf(statusfile, "total ecc corrected, %u\n", ecc.corrected - initial_ecc.corrected); + fprintf(statusfile, "total ecc failed, %u\n", ecc.failed - initial_ecc.failed); + fprintf(statusfile, "total ecc badblocks, %u\n", ecc.badblocks - initial_ecc.badblocks); + fprintf(statusfile, "total ecc bbtblocks, %u\n", ecc.bbtblocks - initial_ecc.bbtblocks); + } + if (verbose) { + printf("total ecc corrected, %u\n", ecc.corrected - initial_ecc.corrected); + printf("total ecc failed, %u\n", ecc.failed - initial_ecc.failed); + printf("total ecc badblocks, %u\n", ecc.badblocks - initial_ecc.badblocks); + printf("total ecc bbtblocks, %u\n", ecc.bbtblocks - initial_ecc.bbtblocks); + } + printf("read %d pages, %d empty\n", page_count, empty_pages); + + return 0; +} + diff --git a/toolbox/newfs_msdos.c b/toolbox/newfs_msdos.c index 4483cc0..ff9e844 100644 --- a/toolbox/newfs_msdos.c +++ b/toolbox/newfs_msdos.c @@ -235,35 +235,6 @@ static void setstr(u_int8_t *, const char *, size_t); static void usage(void); #ifdef ANDROID -static void err(int val, const char *fmt, ...) { - va_list ap; - va_start(ap, fmt); - char *fmt2; - asprintf(&fmt2, "%s\n", fmt); - vfprintf(stderr, fmt2, ap); - free(fmt2); - va_end(ap); -} - -static void errx(int val, const char *fmt, ...) { - va_list ap; - va_start(ap, fmt); - char *fmt2; - asprintf(&fmt2, "%s\n", fmt); - vfprintf(stderr, fmt2, ap); - free(fmt2); - va_end(ap); -} - -static void warnx(const char *fmt, ...) { - va_list ap; - va_start(ap, fmt); - char *fmt2; - asprintf(&fmt2, "%s\n", fmt); - vfprintf(stderr, fmt2, ap); - free(fmt2); - va_end(ap); -} #define powerof2(x) ((((x) - 1) & (x)) == 0) #define howmany(x, y) (((x) + ((y) - 1)) / (y)) #define MAX(x,y) ((x) > (y) ? (x) : (y)) @@ -443,11 +414,14 @@ newfs_msdos_main(int argc, char *argv[]) if (!(opt_f || (opt_h && opt_u && opt_S && opt_s && oflag))) { off_t delta; getdiskinfo(fd, fname, dtype, oflag, &bpb); + if (opt_s) { + bpb.bsec = opt_s; + } bpb.bsec -= (opt_ofs / bpb.bps); delta = bpb.bsec % bpb.spt; if (delta != 0) { - warnx("trim %d sectors to adjust to a multiple of %d", - (int)delta, bpb.spt); + warnx("trim %d sectors from %d to adjust to a multiple of %d", + (int)delta, bpb.bsec, bpb.spt); bpb.bsec -= delta; } if (bpb.spc == 0) { /* set defaults */ @@ -745,8 +719,10 @@ newfs_msdos_main(int argc, char *argv[]) } if ((n = write(fd, img, bpb.bps)) == -1) err(1, "%s", fname); - if ((unsigned)n != bpb.bps) + if ((unsigned)n != bpb.bps) { errx(1, "%s: can't write sector %u", fname, lsn); + exit(1); + } } } return 0; @@ -811,20 +787,31 @@ getdiskinfo(int fd, const char *fname, const char *dtype, __unused int oflag, struct hd_geometry geom; if (ioctl(fd, BLKSSZGET, &bpb->bps)) { - fprintf(stderr, "Error getting bytes / sector (%s)", strerror(errno)); + fprintf(stderr, "Error getting bytes / sector (%s)\n", strerror(errno)); exit(1); } ckgeom(fname, bpb->bps, "bytes/sector"); if (ioctl(fd, BLKGETSIZE, &bpb->bsec)) { - fprintf(stderr, "Error getting blocksize (%s)", strerror(errno)); + fprintf(stderr, "Error getting blocksize (%s)\n", strerror(errno)); exit(1); } if (ioctl(fd, HDIO_GETGEO, &geom)) { - fprintf(stderr, "Error getting gemoetry (%s)", strerror(errno)); - exit(1); + fprintf(stderr, "Error getting gemoetry (%s) - trying sane values\n", strerror(errno)); + geom.heads = 64; + geom.sectors = 63; + } + + if (!geom.heads) { + printf("Bogus heads from kernel - setting sane value\n"); + geom.heads = 64; + } + + if (!geom.sectors) { + printf("Bogus sectors from kernel - setting sane value\n"); + geom.sectors = 63; } bpb->spt = geom.sectors; diff --git a/vold/Android.mk b/vold/Android.mk deleted file mode 100644 index 3dd9f87..0000000 --- a/vold/Android.mk +++ /dev/null @@ -1,32 +0,0 @@ -LOCAL_PATH:= $(call my-dir) - -include $(CLEAR_VARS) - -LOCAL_SRC_FILES:= \ - vold.c \ - cmd_dispatch.c \ - uevent.c \ - mmc.c \ - misc.c \ - blkdev.c \ - ums.c \ - geom_mbr_enc.c \ - volmgr.c \ - media.c \ - volmgr_vfat.c \ - volmgr_ext3.c \ - logwrapper.c \ - ProcessKiller.c\ - switch.c \ - format.c \ - devmapper.c - -LOCAL_MODULE:= vold - -LOCAL_C_INCLUDES := $(KERNEL_HEADERS) - -LOCAL_CFLAGS := - -LOCAL_SHARED_LIBRARIES := libcutils - -include $(BUILD_EXECUTABLE) diff --git a/vold/ProcessKiller.c b/vold/ProcessKiller.c deleted file mode 100644 index fc3eb37..0000000 --- a/vold/ProcessKiller.c +++ /dev/null @@ -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 "vold.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", 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", 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", 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", 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!"); - hit = true; - break; - } - } - - if (!hit) { - LOG_ERROR("Killing process %d", pid); - kill(pid, (sigkill ? SIGKILL : SIGTERM)); - } - } - } - - closedir(dir); -} diff --git a/vold/blkdev.c b/vold/blkdev.c deleted file mode 100644 index 33fed1b..0000000 --- a/vold/blkdev.c +++ /dev/null @@ -1,329 +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 <stdlib.h> -#include <string.h> -#include <dirent.h> -#include <errno.h> -#include <fcntl.h> - -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <sys/mman.h> - -#include <linux/fs.h> -#include <linux/msdos_fs.h> - -#include "vold.h" -#include "blkdev.h" -#include "diskmbr.h" -#include "media.h" - -#define DEBUG_BLKDEV 0 - -static blkdev_list_t *list_root = NULL; - -static blkdev_t *_blkdev_create(blkdev_t *disk, char *devpath, int major, - int minor, char *type, struct media *media); - -static int fat_valid_media(unsigned char media) -{ - return 0xf8 <= media || media == 0xf0; -} - -char *blkdev_get_devpath(blkdev_t *blk) -{ - char *dp = malloc(256); - sprintf(dp, "%s/vold/%d:%d", DEVPATH, blk->major, blk->minor); - return dp; -} - -int blkdev_refresh(blkdev_t *blk) -{ - int fd = 0; - char *devpath = NULL; - unsigned char *block = NULL; - int i, rc; - - if (!(block = malloc(512))) - goto out; - - /* - * Get the device size - */ - devpath = blkdev_get_devpath(blk); - - if ((fd = open(devpath, O_RDONLY)) < 0) { - LOGE("Unable to open device '%s' (%s)", devpath, strerror(errno)); - return -errno; - } - - if (ioctl(fd, BLKGETSIZE, &blk->nr_sec)) { - LOGE("Unable to get device size (%s)", strerror(errno)); - return -errno; - } - close(fd); - free(devpath); - - /* - * Open the disk partition table - */ - devpath = blkdev_get_devpath(blk->disk); - if ((fd = open(devpath, O_RDONLY)) < 0) { - LOGE("Unable to open device '%s' (%s)", devpath, - strerror(errno)); - free(devpath); - return -errno; - } - - free(devpath); - - if ((rc = read(fd, block, 512)) != 512) { - LOGE("Unable to read device partition table (%d, %s)", - rc, strerror(errno)); - goto out; - } - - /* - * If we're a disk, then process the partition table. Otherwise we're - * a partition so get the partition type - */ - - if (blk->type == blkdev_disk) { - blk->nr_parts = 0; - - if ((block[0x1fe] != 0x55) || (block[0x1ff] != 0xAA)) { - LOGI("Disk %d:%d does not contain a partition table", - blk->major, blk->minor); - goto out; - } - - for (i = 0; i < NDOSPART; i++) { - struct dos_partition part; - - dos_partition_dec(block + DOSPARTOFF + i * sizeof(struct dos_partition), &part); - if (part.dp_flag != 0 && part.dp_flag != 0x80) { - struct fat_boot_sector *fb = (struct fat_boot_sector *) &block[0]; - - if (!i && fb->reserved && fb->fats && fat_valid_media(fb->media)) { - LOGI("Detected FAT filesystem in partition table"); - break; - } else { - LOGI("Partition table looks corrupt"); - break; - } - } - if (part.dp_size != 0 && part.dp_typ != 0) - blk->nr_parts++; - } - } else if (blk->type == blkdev_partition) { - struct dos_partition part; - int part_no; - - if (blk->media->media_type == media_mmc) - part_no = blk->minor % MMC_PARTS_PER_CARD -1; - else - part_no = blk->minor -1; - - if (part_no < NDOSPART) { - dos_partition_dec(block + DOSPARTOFF + part_no * sizeof(struct dos_partition), &part); - blk->part_type = part.dp_typ; - } else { - LOGW("Skipping partition %d", part_no); - } - } - - out: - - if (block) - free(block); - - char tmp[255]; - char tmp2[32]; - sprintf(tmp, "%s (blkdev %d:%d), %u secs (%u MB)", - (blk->type == blkdev_disk ? "Disk" : "Partition"), - blk->major, blk->minor, - blk->nr_sec, - (uint32_t) (((uint64_t) blk->nr_sec * 512) / 1024) / 1024); - - if (blk->type == blkdev_disk) - sprintf(tmp2, " %d partitions", blk->nr_parts); - else - sprintf(tmp2, " type 0x%x", blk->part_type); - - strcat(tmp, tmp2); - LOGI(tmp); - - close(fd); - - return 0; -} - -blkdev_t *blkdev_create(blkdev_t *disk, char *devpath, int major, int minor, struct media *media, char *type) -{ - return _blkdev_create(disk, devpath, major, minor, type, media); -} - -static blkdev_t *_blkdev_create(blkdev_t *disk, char *devpath, int major, - int minor, char *type, struct media *media) -{ - blkdev_t *new; - struct blkdev_list *list_entry; - - if (disk && disk->type != blkdev_disk) { - LOGE("Non disk parent specified for blkdev!"); - return NULL; - } - - if (!(new = malloc(sizeof(blkdev_t)))) - return NULL; - - memset(new, 0, sizeof(blkdev_t)); - - if (!(list_entry = malloc(sizeof(struct blkdev_list)))) { - free (new); - return NULL; - } - list_entry->dev = new; - list_entry->next = NULL; - - if (!list_root) - list_root = list_entry; - else { - struct blkdev_list *list_scan = list_root; - while (list_scan->next) - list_scan = list_scan->next; - list_scan->next = list_entry; - } - - if (devpath) - new->devpath = strdup(devpath); - new->major = major; - new->minor = minor; - new->media = media; - new->nr_sec = 0xffffffff; - - if (disk) - new->disk = disk; - else - new->disk = new; // Note the self disk pointer - - /* Create device nodes */ - char nodepath[255]; - mode_t mode = 0660 | S_IFBLK; - dev_t dev = (major << 8) | minor; - - sprintf(nodepath, "%s/vold/%d:%d", DEVPATH, major, minor); - if (mknod(nodepath, mode, dev) < 0) { - LOGE("Error making device nodes for '%s' (%s)", - nodepath, strerror(errno)); - } - - if (!strcmp(type, "disk")) - new->type = blkdev_disk; - else if (!strcmp(type, "partition")) - new->type = blkdev_partition; - else { - LOGE("Unknown block device type '%s'", type); - new->type = blkdev_unknown; - } - - return new; -} - -void blkdev_destroy(blkdev_t *blkdev) -{ - struct blkdev_list *list_next; - - if (list_root->dev == blkdev) { - list_next = list_root->next; - free (list_root); - list_root = list_next; - } else { - struct blkdev_list *list_scan = list_root; - while (list_scan->next->dev != blkdev) - list_scan = list_scan -> next; - list_next = list_scan->next->next; - free(list_scan->next); - list_scan->next = list_next; - } - - if (blkdev->devpath) - free(blkdev->devpath); - - char nodepath[255]; - sprintf(nodepath, "%s/vold/%d:%d", DEVPATH, blkdev->major, blkdev->minor); - unlink(nodepath); - - free(blkdev); -} - -blkdev_t *blkdev_lookup_by_path(char *devpath) -{ - struct blkdev_list *list_scan = list_root; - - while (list_scan) { - if (!strcmp(list_scan->dev->devpath, devpath)) - return list_scan->dev; - list_scan = list_scan->next; - } - return NULL; -} - -blkdev_t *blkdev_lookup_by_devno(int maj, int min) -{ - struct blkdev_list *list_scan = list_root; - - while (list_scan) { - if ((list_scan->dev->major == maj) && - (list_scan->dev->minor == min)) - return list_scan->dev; - list_scan = list_scan->next; - } - return NULL; -} - -/* - * Given a disk device, return the number of partitions which - * have yet to be processed. - */ -int blkdev_get_num_pending_partitions(blkdev_t *blk) -{ - struct blkdev_list *list_scan = list_root; - int num = blk->nr_parts; - - if (blk->type != blkdev_disk) - return -EINVAL; - - while (list_scan) { - if (list_scan->dev->type != blkdev_partition) - goto next; - - if (list_scan->dev->major != blk->major) - goto next; - - if (list_scan->dev->nr_sec != 0xffffffff && - list_scan->dev->devpath) { - num--; - } - next: - list_scan = list_scan->next; - } - return num; -} - diff --git a/vold/blkdev.h b/vold/blkdev.h deleted file mode 100644 index e789739..0000000 --- a/vold/blkdev.h +++ /dev/null @@ -1,64 +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 _BLKDEV_H -#define _BLKDEV_H - -#include <sys/types.h> - -struct media; - -enum blk_type { blkdev_unknown, blkdev_disk, blkdev_partition }; - -struct blkdev { - char *devpath; - enum blk_type type; - struct media *media; - - // If type == blkdev_disk then nr_parts = number of partitions - int nr_parts; - - // If type == blkdev_partition then part_type = partition type - uint8_t part_type; - // If type == blkdev_partition - struct blkdev *disk; - - unsigned int nr_sec; - - int major; - int minor; -}; - -struct blkdev_list { - struct blkdev *dev; - struct blkdev_list *next; -}; - -typedef struct blkdev blkdev_t; -typedef struct blkdev_list blkdev_list_t; - -blkdev_t *blkdev_create(blkdev_t *disk, char *devpath, int major, int minor, struct media *media, char *type); -blkdev_t *blkdev_create_pending_partition(blkdev_t *disk, char *dev_fspath, int major, int minor, struct media *media); -blkdev_t *blkdev_lookup_by_path(char *devpath); -blkdev_t *blkdev_lookup_by_devno(int maj, int min); -char *blkdev_get_devpath(blkdev_t *blk); - -void blkdev_destroy(blkdev_t *blk); - -int blkdev_get_num_pending_partitions(blkdev_t *blk); -int blkdev_refresh(blkdev_t *blk); -#endif diff --git a/vold/cmd_dispatch.c b/vold/cmd_dispatch.c deleted file mode 100644 index ab65fd9..0000000 --- a/vold/cmd_dispatch.c +++ /dev/null @@ -1,115 +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 <unistd.h> -#include <errno.h> - -#include "vold.h" -#include "cmd_dispatch.h" -#include "ums.h" -#include "volmgr.h" - -struct cmd_dispatch { - char *cmd; - int (* dispatch) (char *); -}; - -static void dispatch_cmd(char *cmd); -static int do_send_ums_status(char *cmd); -static int do_set_ums_enable(char *cmd); -static int do_mount_volume(char *cmd); -static int do_eject_media(char *cmd); -static int do_format_media(char *cmd); - -static struct cmd_dispatch dispatch_table[] = { - { VOLD_CMD_ENABLE_UMS, do_set_ums_enable }, - { VOLD_CMD_DISABLE_UMS, do_set_ums_enable }, - { VOLD_CMD_SEND_UMS_STATUS, do_send_ums_status }, - { VOLD_CMD_MOUNT_VOLUME, do_mount_volume }, - { VOLD_CMD_EJECT_MEDIA, do_eject_media }, - { VOLD_CMD_FORMAT_MEDIA, do_format_media }, - { NULL, NULL } -}; - -int process_framework_command(int socket) -{ - int rc; - char buffer[101]; - - if ((rc = read(socket, buffer, sizeof(buffer) -1)) < 0) { - LOGE("Unable to read framework command (%s)", strerror(errno)); - return -errno; - } else if (!rc) - return -ECONNRESET; - - int start = 0; - int i; - - buffer[rc] = 0; - - for (i = 0; i < rc; i++) { - if (buffer[i] == 0) { - dispatch_cmd(buffer + start); - start = i + 1; - } - } - return 0; -} - -static void dispatch_cmd(char *cmd) -{ - struct cmd_dispatch *c; - - LOG_VOL("dispatch_cmd(%s):", cmd); - - for (c = dispatch_table; c->cmd != NULL; c++) { - if (!strncmp(c->cmd, cmd, strlen(c->cmd))) { - c->dispatch(cmd); - return; - } - } - - LOGE("No cmd handlers defined for '%s'", cmd); -} - -static int do_send_ums_status(char *cmd) -{ - return ums_send_status(); -} - -static int do_set_ums_enable(char *cmd) -{ - if (!strcmp(cmd, VOLD_CMD_ENABLE_UMS)) - return volmgr_enable_ums(true); - - return volmgr_enable_ums(false); -} - -static int do_mount_volume(char *cmd) -{ - return volmgr_start_volume_by_mountpoint(&cmd[strlen("mount_volume:")]); -} - -static int do_format_media(char *cmd) -{ - return volmgr_format_volume(&cmd[strlen("format_media:")]); -} - -static int do_eject_media(char *cmd) -{ - return volmgr_stop_volume_by_mountpoint(&cmd[strlen("eject_media:")]); -} diff --git a/vold/cmd_dispatch.h b/vold/cmd_dispatch.h deleted file mode 100644 index f8ba6b3..0000000 --- a/vold/cmd_dispatch.h +++ /dev/null @@ -1,31 +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 _CMD_DISPATCH_H -#define _CMD_DISPATCH_H - -// These must match the strings in java/android/android/os/UsbListener.java -#define VOLD_CMD_ENABLE_UMS "enable_ums" -#define VOLD_CMD_DISABLE_UMS "disable_ums" -#define VOLD_CMD_SEND_UMS_STATUS "send_ums_status" - -// these commands should contain a volume mount point after the colon -#define VOLD_CMD_MOUNT_VOLUME "mount_volume:" -#define VOLD_CMD_EJECT_MEDIA "eject_media:" -#define VOLD_CMD_FORMAT_MEDIA "format_media:" - -#endif diff --git a/vold/devmapper.c b/vold/devmapper.c deleted file mode 100644 index ef44c90..0000000 --- a/vold/devmapper.c +++ /dev/null @@ -1,463 +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 <stdlib.h> -#include <string.h> -#include <errno.h> -#include <dirent.h> -#include <unistd.h> -#include <sched.h> -#include <fcntl.h> - -#include <sys/mount.h> - -#include <linux/loop.h> -#include <linux/dm-ioctl.h> - -#include <cutils/config_utils.h> -#include <cutils/properties.h> - -#include "vold.h" -#include "devmapper.h" - -#define DEBUG_DEVMAPPER 1 - -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 devmapping *dm, 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(dm->key); i++) { - char tmp[8]; - - sprintf(tmp, "%02x", dm->key[i]); - strcat(key, tmp); - } - - char srcdev[128]; - - // XXX: Handle non crypt targets and non twofish (use param) - if (dm->src_type == dmsrc_loopback) - strcpy(srcdev, dm->type_data.loop.loop_dev); - else if (dm->src_type == dmsrc_partition) - strcpy(srcdev, dm->type_data.part.part_dev); - - sprintf(params, "twofish %s 0 %s 0", key, srcdev); - -LOG_VOL("Params = '%s'", params); - - if (len < min_size) - len = min_size; - - if (!(buffer = malloc(len))) { - LOGE("out of memory"); - 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, dm->target, sizeof(io->name)); - - tgt->status = 0; - tgt->sector_start = 0; - tgt->length = (dm->size_mb * (1024 * 1024)) / 512; - 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 get_next_available_dm() -{ - 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; - } - - LOGE("Out of device mapper numbers"); - return -1; -} - -static int create_devmapping(struct devmapping *dm) -{ - struct dm_ioctl *io; - int rc, fd; - -#if DEBUG_DEVMAPPER - LOG_VOL("create_devmapping():"); -#endif - - if (dm->dm_no < 0) { - LOGE("Invalid dm_no set"); - return -EINVAL; - } - - if ((fd = open("/dev/device-mapper", O_RDWR)) < 0) { - LOGE("Error opening device mapper (%d)", errno); - return -errno; - } - - if (!(io = _dm_ioctl_setup(dm, 0))) { - LOGE("Unable to setup ioctl (out of memory)"); - close(fd); - return -ENOMEM; - } - - if ((rc = ioctl(fd, DM_DEV_CREATE, io)) < 0) { - LOGE("device-mapper create ioctl failed (%d)", errno); - rc = -errno; - goto out_free; - } - - free(io); - - if (!(io = _dm_ioctl_setup(dm, DM_STATUS_TABLE_FLAG))) { - LOGE("Unable to setup ioctl (out of memory)"); - rc = -ENOMEM; - goto out_nofree; - } - - if ((rc = ioctl(fd, DM_TABLE_LOAD, io)) < 0) { - LOGE("device-mapper load ioctl failed (%d)", errno); - rc = -errno; - goto out_free; - } - - free(io); - - if (!(io = _dm_ioctl_setup(dm, 0))) { - LOGE("Unable to setup ioctl (out of memory)"); - rc = -ENOMEM; - goto out_nofree; - } - - if ((rc = ioctl(fd, DM_DEV_SUSPEND, io)) < 0) { - LOGE("device-mapper resume ioctl failed (%d)", errno); - rc = -errno; - goto out_free; - } - -out_free: - free (io); -out_nofree: - close (fd); - return rc; -} - -static int loopback_start(struct devmapping *dm) -{ - int i; - int fd; - char filename[255]; - int rc; - -#if DEBUG_DEVMAPPER - LOG_VOL("loopback_start(%s):", dm->type_data.loop.loop_src); -#endif - - for (i = 0; i < MAX_LOOP; i++) { - struct loop_info info; - - sprintf(filename, "/dev/block/loop%d", i); - - if ((fd = open(filename, O_RDWR)) < 0) { - LOGE("Unable to open %s (%s)", filename, strerror(errno)); - return -errno; - } - - rc = ioctl(fd, LOOP_GET_STATUS, &info); - if (rc < 0 && errno == ENXIO) - break; - - close(fd); - - if (rc < 0) { - LOGE("Unable to get loop status for %s (%s)", filename, - strerror(errno)); - return -errno; - } - } - - if (i == MAX_LOOP) { - LOGE("Out of loop devices"); - return -ENOSPC; - } - - int file_fd; - - if ((file_fd = open(dm->type_data.loop.loop_src, O_RDWR)) < 0) { - LOGE("Unable to open %s (%s)", dm->type_data.loop.loop_src, - strerror(errno)); - return -errno; - } - - if (ioctl(fd, LOOP_SET_FD, file_fd) < 0) { - LOGE("Error setting up loopback interface (%s)", strerror(errno)); - return -errno; - } - - dm->type_data.loop.loop_dev = strdup(filename); - dm->type_data.loop.loop_no = i; - - close(fd); - close(file_fd); - -#if DEBUG_DEVMAPPER - LOG_VOL("Loop setup on %s for %s", dm->type_data.loop.loop_dev, - dm->type_data.loop.loop_src); -#endif - - return 0; -} - -int devmapper_start(struct devmapping *dm) -{ - int rc; - char src_blkdev_path[255]; - -#if DEBUG_DEVMAPPER - LOG_VOL("devmapper_start()"); -#endif - - if (dm->src_type == dmsrc_loopback) { - if ((rc = loopback_start(dm)) < 0) - return rc; - } else if (dm->src_type == dmsrc_partition) { - LOGE("partition maps not yet supported"); - return -ENOSYS; - } else { - LOGE("devmapper_start(): Unsupported source type '%d'", dm->src_type); - return -ENOENT; - } - - /* - * Configure the device mapper - */ - if ((rc = create_devmapping(dm)) < 0) { - LOGE("Failed to create devmapping (%d)", rc); - // XXX: if loopback then tear down - return rc; - } - - return 0; -} - -struct devmapping *devmapper_init(char *src, char *src_type, uint32_t size_mb, - char *target, char *params, char *tgt_fs, char *mediapath) -{ - struct devmapping *dm; - - if (!(dm = malloc(sizeof(struct devmapping)))) { - LOGE("devmapper_init(): out of memory"); - return NULL; - } - - memset(dm, 0, sizeof(struct devmapping)); - - if (!strcmp(src_type, "loopback_file")) { - dm->src_type = dmsrc_loopback; - dm->type_data.loop.loop_src = strdup(src); - } else if (!strncmp(src_type, "partition ", strlen("partition "))) { - dm->src_type = dmsrc_partition; - char *p = strtok(src_type, " "); - if (!p) { - LOGE("Invalid partition specifier"); - goto out_free; - } - dm->type_data.part.part_type = strtoul(p, NULL, 0); - } else { - LOGE("Invalid src_type defined (%s)", src_type); - goto out_free; - } - - // XXX: Validate these - dm->size_mb = size_mb; - dm->target = strdup(target); - dm->params = strdup(params); - dm->tgt_fs = strdup(tgt_fs); - - if ((dm->dm_no = get_next_available_dm()) < 0) - goto out_free; - - sprintf(mediapath, "/devices/virtual/block/dm-%d", dm->dm_no); - - if (!(dm->media = media_create(mediapath, - "unknown", - "unknown", - media_devmapper))) { - LOGE("Unable to create media"); - goto out_free; - } - - return dm; - out_free: - if (dm->target) - free(dm->target); - if (dm->params) - free(dm->params); - if (dm->tgt_fs) - free(dm->tgt_fs); - - free(dm); - return NULL; -} - -int devmapper_genesis(struct devmapping *dm) -{ - - if (dm->src_type == dmsrc_loopback) { - int fd; - - LOG_VOL("devmapper_genesis(): Working on %s", - dm->type_data.loop.loop_src); - - unlink(dm->type_data.loop.loop_src); - - LOG_VOL("devmapper_genesis(): Creating imagefile (%u MB)", - dm->size_mb); - - if ((fd = creat(dm->type_data.loop.loop_src, 0600)) < 0) { - LOGE("Error creating imagefile (%s)", strerror(errno)); - return -errno; - } - - if (ftruncate(fd, (dm->size_mb * (1024 * 1024))) < 0) { - LOGE("Error truncating imagefile (%s)", strerror(errno)); - close(fd); - return -errno; - } - close(fd); - } else if (dm->src_type == dmsrc_partition) { - LOGE("partition maps not yet supported"); - return -ENOSYS; - } - - return devmapper_start(dm); -} - -static int destroy_devmapping(struct devmapping *dm) -{ - struct dm_ioctl *io; - int dmFd; - int rc = 0; - - LOG_VOL("destroy_devmapping():"); - - if ((dmFd = open("/dev/device-mapper", O_RDWR)) < 0) { - LOGE("Error opening device mapper (%d)", errno); - return -errno; - } - - if (!(io = _dm_ioctl_setup(dm, DM_PERSISTENT_DEV_FLAG))) { - LOGE("Unable to setup ioctl (out of memory)"); - rc = -ENOMEM; - goto out_nofree; - } - - if ((rc = ioctl(dmFd, DM_DEV_REMOVE, io)) < 0) { - LOGE("device-mapper remove ioctl failed (%d)", errno); - rc = -errno; - goto out_free; - } - -out_free: - free (io); -out_nofree: - close (dmFd); - return rc; -} - -static int loopback_stop(struct devmapping *dm) -{ - char devname[255]; - int device_fd; - int rc = 0; - - LOG_VOL("loopback_stop():"); - - device_fd = open(dm->type_data.loop.loop_dev, O_RDONLY); - if (device_fd < 0) { - LOG_ERROR("Failed to open loop (%d)", errno); - return -errno; - } - - if (ioctl(device_fd, LOOP_CLR_FD, 0) < 0) { - LOG_ERROR("Failed to destroy loop (%d)", errno); - rc = -errno; - } - - close(device_fd); - return rc; -} - -int devmapper_stop(struct devmapping *dm) -{ - int rc; - - LOG_VOL("devmapper_stop():"); - - if ((rc = destroy_devmapping(dm))) - return rc; - - if (dm->src_type == dmsrc_loopback) { - if ((rc = loopback_stop(dm))) - return rc; - } else if (dm->src_type == dmsrc_partition) { - LOGE("partition maps not yet supported"); - return -ENOSYS; - } - return 0; -} diff --git a/vold/devmapper.h b/vold/devmapper.h deleted file mode 100644 index 3d8cab3..0000000 --- a/vold/devmapper.h +++ /dev/null @@ -1,70 +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 _DEVMAPPER_H -#define _DEVMAPPER_H - -#include <pthread.h> - -#include "vold.h" -#include "blkdev.h" -#include "media.h" - -#define MAX_LOOP 8 - -enum dm_src_type { - dmsrc_unknown, - dmsrc_loopback, - dmsrc_partition, -}; - -struct loop_data { - char *loop_src; - - char *loop_dev; - int loop_no; -}; - -struct part_data { - char part_type; - - char *part_dev; -}; - -struct devmapping { - enum dm_src_type src_type; - union { - struct loop_data loop; - struct part_data part; - } type_data; - - uint32_t size_mb; - char *target; - char *params; - char *tgt_fs; - - unsigned char key[16]; - int dm_no; - - media_t *media; -}; - -struct devmapping *devmapper_init(char *, char *, unsigned int, char *, char *, char *, char *); -int devmapper_start(struct devmapping *); -int devmapper_stop(struct devmapping *); -int devmapper_genesis(struct devmapping *); -#endif diff --git a/vold/diskmbr.h b/vold/diskmbr.h deleted file mode 100644 index 417e7ca..0000000 --- a/vold/diskmbr.h +++ /dev/null @@ -1,75 +0,0 @@ -/*- - * Copyright (c) 1987, 1988, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)disklabel.h 8.2 (Berkeley) 7/10/94 - * $FreeBSD: src/sys/sys/diskmbr.h,v 1.99.2.1 2005/01/31 23:26:56 imp Exp $ - */ - -#ifndef _SYS_DISKMBR_H_ -#define _SYS_DISKMBR_H_ - -#define DOSBBSECTOR 0 /* DOS boot block relative sector number */ -#define DOSPARTOFF 446 -#define DOSPARTSIZE 16 -#define NDOSPART 4 -#define NEXTDOSPART 32 -#define DOSMAGICOFFSET 510 -#define DOSMAGIC 0xAA55 - -#define DOSPTYP_386BSD 0xa5 /* 386BSD partition type */ -#define DOSPTYP_LINSWP 0x82 /* Linux swap partition */ -#define DOSPTYP_LINUX 0x83 /* Linux partition */ -#define DOSPTYP_PMBR 0xee /* GPT Protective MBR */ -#define DOSPTYP_EXT 5 /* DOS extended partition */ -#define DOSPTYP_EXTLBA 15 /* DOS extended partition */ - -struct dos_partition { - unsigned char dp_flag; /* bootstrap flags */ - unsigned char dp_shd; /* starting head */ - unsigned char dp_ssect; /* starting sector */ - unsigned char dp_scyl; /* starting cylinder */ - unsigned char dp_typ; /* partition type */ - unsigned char dp_ehd; /* end head */ - unsigned char dp_esect; /* end sector */ - unsigned char dp_ecyl; /* end cylinder */ - u_int32_t dp_start; /* absolute starting sector number */ - u_int32_t dp_size; /* partition size in sectors */ -}; -#ifdef CTASSERT -CTASSERT(sizeof (struct dos_partition) == DOSPARTSIZE); -#endif - -void dos_partition_dec(void const *pp, struct dos_partition *d); -void dos_partition_enc(void *pp, struct dos_partition *d); - -#define DPSECT(s) ((s) & 0x3f) /* isolate relevant bits of sector */ -#define DPCYL(c, s) ((c) + (((s) & 0xc0)<<2)) /* and those that are cylinder */ - -#define DIOCSMBR _IOW('M', 129, u_char[512]) - -#endif /* !_SYS_DISKMBR_H_ */ diff --git a/vold/format.c b/vold/format.c deleted file mode 100755 index c67b358..0000000 --- a/vold/format.c +++ /dev/null @@ -1,117 +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 <fcntl.h> -#include <errno.h> - -#include <linux/fs.h> - -#include "vold.h" -#include "blkdev.h" -#include "format.h" -#include "diskmbr.h" -#include "logwrapper.h" - -static char MKDOSFS_PATH[] = "/system/bin/newfs_msdos"; -static char MKE2FS_PATH[] = "/system/bin/mke2fs"; - -int format_partition(blkdev_t *part, char *type) -{ - char *devpath; - int rc = -EINVAL; - - devpath = blkdev_get_devpath(part); - - if (!strcmp(type, FORMAT_TYPE_FAT32)) { - char *args[7]; - args[0] = MKDOSFS_PATH; - args[1] = "-F"; - if ((part->nr_sec * 512) <= (unsigned int) (1024*1024*1024*2)) - args[2] = "16"; - else - args[2] = "32"; - - args[3] = "-O"; - args[4] = "android"; - args[5] = devpath; - args[6] = NULL; - rc = logwrap(7, args, 1); - } else { - char *args[7]; - args[0] = MKE2FS_PATH; - args[1] = "-b 4096"; - args[2] = "-m 1"; - args[3] = "-L android"; - args[4] = "-v"; - args[5] = devpath; - args[6] = NULL; - rc = logwrap(6, args, 1); - } - - free(devpath); - - if (rc == 0) { - LOG_VOL("Filesystem formatted OK"); - return 0; - } else { - LOGE("Format failed (unknokwn exit code %d)", rc); - return -EIO; - } - return 0; -} - -int initialize_mbr(blkdev_t *disk) -{ - int fd, rc; - unsigned char block[512]; - struct dos_partition part; - char *devpath; - - devpath = blkdev_get_devpath(disk); - - memset(&part, 0, sizeof(part)); - part.dp_flag = 0x80; - part.dp_typ = 0xc; - part.dp_start = ((1024 * 64) / 512) + 1; - part.dp_size = disk->nr_sec - part.dp_start; - - memset(block, 0, sizeof(block)); - block[0x1fe] = 0x55; - block[0x1ff] = 0xaa; - - dos_partition_enc(block + DOSPARTOFF, &part); - - if ((fd = open(devpath, O_RDWR)) < 0) { - LOGE("Error opening disk file (%s)", strerror(errno)); - return -errno; - } - free(devpath); - - if (write(fd, block, sizeof(block)) < 0) { - LOGE("Error writing MBR (%s)", strerror(errno)); - close(fd); - return -errno; - } - - if (ioctl(fd, BLKRRPART, NULL) < 0) { - LOGE("Error re-reading partition table (%s)", strerror(errno)); - close(fd); - return -errno; - } - close(fd); - return 0; -} diff --git a/vold/format.h b/vold/format.h deleted file mode 100644 index 73cc012..0000000 --- a/vold/format.h +++ /dev/null @@ -1,26 +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 _FORMAT_H -#define _FORMAT_H - -#define FORMAT_TYPE_EXT2 "ext2" -#define FORMAT_TYPE_FAT32 "fat32" - -int format_partition(blkdev_t *part, char *type); -int initialize_mbr(blkdev_t *disk); -#endif diff --git a/vold/geom_mbr_enc.c b/vold/geom_mbr_enc.c deleted file mode 100644 index f1f8339..0000000 --- a/vold/geom_mbr_enc.c +++ /dev/null @@ -1,90 +0,0 @@ -/*- - * Copyright (c) 2003 Poul-Henning Kamp - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* Functions to encode or decode struct dos_partition into a bytestream - * of correct endianess and packing. These functions do no validation - * or sanity checking, they only pack/unpack the fields correctly. - * - * NB! This file must be usable both in kernel and userland. - */ - -#include <sys/types.h> -#include <sys/endian.h> - -#include "diskmbr.h" - -static __inline uint32_t __unused -le32dec(const void *buf) -{ - const uint8_t *p = (const uint8_t *)buf; - - return ((p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0]); -} - -static __inline void -le32enc(void *pp, uint32_t u) -{ - unsigned char *p = (unsigned char *)pp; - - p[0] = u & 0xff; - p[1] = (u >> 8) & 0xff; - p[2] = (u >> 16) & 0xff; - p[3] = (u >> 24) & 0xff; -} - -void -dos_partition_dec(void const *pp, struct dos_partition *d) -{ - unsigned char const *p = pp; - - d->dp_flag = p[0]; - d->dp_shd = p[1]; - d->dp_ssect = p[2]; - d->dp_scyl = p[3]; - d->dp_typ = p[4]; - d->dp_ehd = p[5]; - d->dp_esect = p[6]; - d->dp_ecyl = p[7]; - d->dp_start = le32dec(p + 8); - d->dp_size = le32dec(p + 12); -} - -void -dos_partition_enc(void *pp, struct dos_partition *d) -{ - unsigned char *p = pp; - - p[0] = d->dp_flag; - p[1] = d->dp_shd; - p[2] = d->dp_ssect; - p[3] = d->dp_scyl; - p[4] = d->dp_typ; - p[5] = d->dp_ehd; - p[6] = d->dp_esect; - p[7] = d->dp_ecyl; - le32enc(p + 8, d->dp_start); - le32enc(p + 12, d->dp_size); -} diff --git a/vold/logwrapper.c b/vold/logwrapper.c deleted file mode 100644 index 8da4892..0000000 --- a/vold/logwrapper.c +++ /dev/null @@ -1,167 +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, "%s", &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 (execv(argv_child[0], argv_child)) { - LOG(LOG_ERROR, "logwrapper", - "executing %s failed: %s", argv_child[0], strerror(errno)); - exit(-1); - } -} - -int logwrap(int argc, char* argv[], pid_t *childPid, int background) -{ - 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"); - return -errno; - } - - if (grantpt(parent_ptty) || unlockpt(parent_ptty) || - ((child_devname = (char*)ptsname(parent_ptty)) == 0)) { - LOG(LOG_ERROR, "logwrapper", "Problem with /dev/ptmx"); - return -1; - } - - pid = fork(); - if (pid < 0) { - LOG(LOG_ERROR, "logwrapper", "Failed to fork"); - 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"); - return -errno; - } - - // redirect stdout and stderr - close(parent_ptty); - dup2(child_ptty, 1); - dup2(child_ptty, 2); - close(child_ptty); - - if (background) { - int fd = open("/dev/cpuctl/bg_non_interactive/tasks", O_WRONLY); - - if (fd >=0 ) { - char text[64]; - - sprintf(text, "%d", getpid()); - if (write(fd, text, strlen(text)) < 0) { - LOG(LOG_WARN, "logwrapper", - "Unable to background process (%s)", strerror(errno)); - close(fd); - } - close(fd); - } else { - LOG(LOG_WARN, "logwrapper", - "Unable to background process (%s)", strerror(errno)); - } - } - - child(argc, argv); - } else { - return parent(argv[0], parent_ptty); - } - - return 0; -} diff --git a/vold/logwrapper.h b/vold/logwrapper.h deleted file mode 100644 index bf28aae..0000000 --- a/vold/logwrapper.h +++ /dev/null @@ -1,23 +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 _LOGWRAPPER_H -#define _LOGWRAPPER_H - -#include <stdlib.h> -int logwrap(int argc, char* argv[], int background); -#endif diff --git a/vold/media.c b/vold/media.c deleted file mode 100644 index db42a3e..0000000 --- a/vold/media.c +++ /dev/null @@ -1,163 +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 <stdlib.h> -#include <string.h> -#include <dirent.h> -#include <errno.h> - -#include <sys/types.h> - -#include "vold.h" -#include "media.h" - -static media_list_t *list_root = NULL; - -media_t *media_create(char *devpath, char *name, char *serial, media_type_t type) -{ - media_list_t *list_entry; - media_t *new; - - if (!(new = malloc(sizeof(media_t)))) - return NULL; - - memset(new, 0, sizeof(media_t)); - - if (!(list_entry = malloc(sizeof(media_list_t)))) { - free(new); - return NULL; - } - list_entry->media = new; - list_entry->next = NULL; - - if (!list_root) - list_root = list_entry; - else { - media_list_t *list_scan = list_root; - while(list_scan->next) - list_scan = list_scan->next; - list_scan->next = list_entry; - } - - new->devpath = strdup(devpath); - new->name = strdup(name); - if (!serial) - new->serial = 0; - else - new->serial = strtoul(serial, NULL, 0); - - new->media_type = type; - - return new; -} - -void media_destroy(media_t *media) -{ - media_list_t *list_next; - - if (list_root->media == media) { - list_next = list_root->next; - free(list_root); - list_root = list_next; - } else { - media_list_t *list_scan = list_root; - while (list_scan->next->media != media) - list_scan = list_scan -> next; - list_next = list_scan->next->next; - free(list_scan->next); - list_scan->next = list_next; - } - - free(media->devpath); - free(media->name); - - while(media->devs) - media_remove_blkdev(media, media->devs->dev); - free(media); -} - -media_t *media_lookup_by_path(char *devpath, boolean fuzzy_match) -{ - media_list_t *list_scan = list_root; - - while (list_scan) { - if (fuzzy_match) { - if (!strncmp(list_scan->media->devpath, devpath, strlen(devpath))) - return list_scan->media; - } else { - if (!strcmp(list_scan->media->devpath, devpath)) - return list_scan->media; - } - list_scan = list_scan->next; - } -#if DEBUG_MEDIA - LOG_VOL("media_lookup_by_path(): No media found @ %s", devpath); -#endif - return NULL; -} - -int media_add_blkdev(media_t *card, blkdev_t *dev) -{ - blkdev_list_t *list_entry; - - if (!(list_entry = malloc(sizeof(blkdev_list_t)))) - return -ENOMEM; - - list_entry->next = NULL; - list_entry->dev = dev; - if (!card->devs) - card->devs = list_entry; - else { - blkdev_list_t *scan = card->devs; - - while(scan->next) - scan = scan->next; - - scan->next = list_entry; - } - return 0; -} - -void media_remove_blkdev(media_t *card, blkdev_t *dev) -{ - if (card->devs->dev == dev) - card->devs = card->devs->next; - else { - blkdev_list_t *scan = card->devs; - while (scan->next->dev != dev) - scan = scan -> next; - blkdev_list_t *next = scan->next->next; - free(scan->next); - scan->next = next; - } -} - -media_t *media_lookup_by_dev(blkdev_t *dev) -{ - media_list_t *media_scan = list_root; - - while (media_scan) { - blkdev_list_t *blk_scan = media_scan->media->devs; - while (blk_scan) { - if (blk_scan->dev == dev) - return media_scan->media; - blk_scan = blk_scan->next; - } - media_scan = media_scan->next; - } - return NULL; -} diff --git a/vold/media.h b/vold/media.h deleted file mode 100644 index 6fd8b84..0000000 --- a/vold/media.h +++ /dev/null @@ -1,57 +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 _MEDIA_H -#define _MEDIA_H - -#include <sys/types.h> - -#include "blkdev.h" - -typedef enum media_type { - media_unknown, - media_mmc, - media_devmapper, -} media_type_t; - -/* - * max 8 partitions per card - */ -#define MMC_PARTS_PER_CARD (1<<3) -#define ALIGN_MMC_MINOR(min) (min / MMC_PARTS_PER_CARD * MMC_PARTS_PER_CARD) - -typedef struct media { - char *devpath; - char *name; - uint32_t serial; - media_type_t media_type; - - blkdev_list_t *devs; -} media_t; - -typedef struct media_list { - media_t *media; - struct media_list *next; -} media_list_t; - -media_t *media_create(char *devpath, char *name, char *serial, enum media_type); -media_t *media_lookup_by_path(char *devpath, boolean fuzzy_match); -media_t *media_lookup_by_dev(blkdev_t *dev); -void media_destroy(media_t *media); -int media_add_blkdev(media_t *media, blkdev_t *dev); -void media_remove_blkdev(media_t *media, blkdev_t *dev); -#endif diff --git a/vold/misc.c b/vold/misc.c deleted file mode 100644 index 0f8f61e..0000000 --- a/vold/misc.c +++ /dev/null @@ -1,91 +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 <stdio.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> - -void *read_file(char *filename, ssize_t *_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; -} -char *truncate_sysfs_path(char *path, int num_elements_to_remove, char *buffer, int buffer_size) -{ - int i; - - strncpy(buffer, path, buffer_size); - - for (i = 0; i < num_elements_to_remove; i++) { - char *p = &buffer[strlen(buffer)-1]; - - for (p = &buffer[strlen(buffer) -1]; *p != '/'; p--); - *p = '\0'; - } - - return buffer; -} - -char *read_sysfs_var(char *buffer, size_t maxlen, char *devpath, char *var) -{ - char filename[255]; - char *p; - ssize_t sz; - - snprintf(filename, sizeof(filename), "/sys%s/%s", devpath, var); - p = read_file(filename, &sz); - p[(strlen(p) - 1)] = '\0'; - strncpy(buffer, p, maxlen); - free(p); - return buffer; -} - diff --git a/vold/mmc.c b/vold/mmc.c deleted file mode 100644 index d90845d..0000000 --- a/vold/mmc.c +++ /dev/null @@ -1,301 +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 <stdlib.h> -#include <string.h> -#include <dirent.h> -#include <errno.h> - -#include <sys/types.h> - -#include "vold.h" -#include "mmc.h" -#include "media.h" -#include "diskmbr.h" /* for NDOSPART */ - -#define DEBUG_BOOTSTRAP 0 - -static int mmc_bootstrap_controller(char *sysfs_path); -static int mmc_bootstrap_card(char *sysfs_path); -static int mmc_bootstrap_block(char *devpath); -static int mmc_bootstrap_mmcblk(char *devpath); -static int mmc_bootstrap_mmcblk_partition(char *devpath); - -/* - * Bootstrap our mmc information. - */ -int mmc_bootstrap() -{ - DIR *d; - struct dirent *de; - - if (!(d = opendir(SYSFS_CLASS_MMC_PATH))) { - LOG_ERROR("Unable to open '%s' (%s)", SYSFS_CLASS_MMC_PATH, - strerror(errno)); - return -errno; - } - - while ((de = readdir(d))) { - char tmp[255]; - - if (de->d_name[0] == '.') - continue; - - sprintf(tmp, "%s/%s", SYSFS_CLASS_MMC_PATH, de->d_name); - if (mmc_bootstrap_controller(tmp)) { - LOG_ERROR("Error bootstrapping controller '%s' (%s)", tmp, - strerror(errno)); - } - } - - closedir(d); - - return 0; -} - -static int mmc_bootstrap_controller(char *sysfs_path) -{ - DIR *d; - struct dirent *de; - -#if DEBUG_BOOTSTRAP - LOG_VOL("bootstrap_controller(%s):", sysfs_path); -#endif - if (!(d = opendir(sysfs_path))) { - LOG_ERROR("Unable to open '%s' (%s)", sysfs_path, strerror(errno)); - return -errno; - } - - while ((de = readdir(d))) { - char tmp[255]; - - if (de->d_name[0] == '.') - continue; - - if ((!strcmp(de->d_name, "uevent")) || - (!strcmp(de->d_name, "subsystem")) || - (!strcmp(de->d_name, "device")) || - (!strcmp(de->d_name, "power"))) { - continue; - } - - sprintf(tmp, "%s/%s", sysfs_path, de->d_name); - - if (mmc_bootstrap_card(tmp) < 0) - LOG_ERROR("Error bootstrapping card '%s' (%s)", tmp, strerror(errno)); - } // while - - closedir(d); - return 0; -} - -static int mmc_bootstrap_card(char *sysfs_path) -{ - char saved_cwd[255]; - char new_cwd[255]; - char *devpath; - char *uevent_params[4]; - char *p; - char filename[255]; - char tmp[255]; - ssize_t sz; - -#if DEBUG_BOOTSTRAP - LOG_VOL("bootstrap_card(%s):", sysfs_path); -#endif - - /* - * sysfs_path is based on /sys/class, but we want the actual device class - */ - if (!getcwd(saved_cwd, sizeof(saved_cwd))) { - LOGE("Error getting working dir path"); - return -errno; - } - - if (chdir(sysfs_path) < 0) { - LOGE("Unable to chdir to %s (%s)", sysfs_path, strerror(errno)); - return -errno; - } - - if (!getcwd(new_cwd, sizeof(new_cwd))) { - LOGE("Buffer too small for device path"); - return -errno; - } - - if (chdir(saved_cwd) < 0) { - LOGE("Unable to restore working dir"); - return -errno; - } - - devpath = &new_cwd[4]; // Skip over '/sys' - - /* - * Collect parameters so we can simulate a UEVENT - */ - sprintf(tmp, "DEVPATH=%s", devpath); - uevent_params[0] = (char *) strdup(tmp); - - sprintf(filename, "/sys%s/type", devpath); - p = read_file(filename, &sz); - p[strlen(p) - 1] = '\0'; - sprintf(tmp, "MMC_TYPE=%s", p); - free(p); - uevent_params[1] = (char *) strdup(tmp); - - sprintf(filename, "/sys%s/name", devpath); - p = read_file(filename, &sz); - if (!p) { - LOGE("Unable to read MMC name: %s", filename); - return -errno; - } - p[strlen(p) - 1] = '\0'; - sprintf(tmp, "MMC_NAME=%s", p); - free(p); - uevent_params[2] = (char *) strdup(tmp); - - uevent_params[3] = (char *) NULL; - - if (simulate_uevent("mmc", devpath, "add", uevent_params) < 0) { - LOGE("Error simulating uevent (%s)", strerror(errno)); - return -errno; - } - - /* - * Check for block drivers - */ - char block_devpath[255]; - sprintf(tmp, "%s/block", devpath); - sprintf(filename, "/sys%s/block", devpath); - if (!access(filename, F_OK)) { - if (mmc_bootstrap_block(tmp)) { - LOGE("Error bootstrapping block @ %s", tmp); - } - } - - return 0; -} - -static int mmc_bootstrap_block(char *devpath) -{ - char blockdir_path[255]; - DIR *d; - struct dirent *de; - -#if DEBUG_BOOTSTRAP - LOG_VOL("mmc_bootstrap_block(%s):", devpath); -#endif - - sprintf(blockdir_path, "/sys%s", devpath); - - if (!(d = opendir(blockdir_path))) { - LOGE("Failed to opendir %s", devpath); - return -errno; - } - - while ((de = readdir(d))) { - char tmp[255]; - - if (de->d_name[0] == '.') - continue; - sprintf(tmp, "%s/%s", devpath, de->d_name); - if (mmc_bootstrap_mmcblk(tmp)) - LOGE("Error bootstraping mmcblk @ %s", tmp); - } - closedir(d); - return 0; -} - -static int mmc_bootstrap_mmcblk(char *devpath) -{ - char *mmcblk_devname; - int part_no; - int rc; - -#if DEBUG_BOOTSTRAP - LOG_VOL("mmc_bootstrap_mmcblk(%s):", devpath); -#endif - - if ((rc = mmc_bootstrap_mmcblk_partition(devpath))) { - LOGE("Error bootstrapping mmcblk partition '%s'", devpath); - return rc; - } - - for (mmcblk_devname = &devpath[strlen(devpath)]; - *mmcblk_devname != '/'; mmcblk_devname--); - mmcblk_devname++; - - for (part_no = 1; part_no <= NDOSPART; part_no++) { - char part_file[255]; - sprintf(part_file, "/sys%s/%sp%d", devpath, mmcblk_devname, part_no); - if (!access(part_file, F_OK)) { - char part_devpath[255]; - - sprintf(part_devpath, "%s/%sp%d", devpath, mmcblk_devname, part_no); - if (mmc_bootstrap_mmcblk_partition(part_devpath)) - LOGE("Error bootstrapping mmcblk partition '%s'", part_devpath); - } - } - - return 0; -} - -static int mmc_bootstrap_mmcblk_partition(char *devpath) -{ - char filename[255]; - char *uevent_buffer; - ssize_t sz; - char *uevent_params[5]; - char tmp[255]; - FILE *fp; - char line[255]; - -#if DEBUG_BOOTSTRAP - LOG_VOL("mmc_bootstrap_mmcblk_partition(%s):", devpath); -#endif - - sprintf(tmp, "DEVPATH=%s", devpath); - uevent_params[0] = strdup(tmp); - - sprintf(filename, "/sys%s/uevent", devpath); - if (!(fp = fopen(filename, "r"))) { - LOGE("Unable to open '%s' (%s)", filename, strerror(errno)); - return -errno; - } - - while (fgets(line, sizeof(line), fp)) { - line[strlen(line)-1] = 0; - if (!strncmp(line, "DEVTYPE=", 8)) - uevent_params[1] = strdup(line); - else if (!strncmp(line, "MAJOR=",6)) - uevent_params[2] = strdup(line); - else if (!strncmp(line, "MINOR=",6)) - uevent_params[3] = strdup(line); - } - fclose(fp); - - if (!uevent_params[1] || !uevent_params[2] || !uevent_params[3]) { - LOGE("mmcblk uevent missing required params"); - return -1; - } - uevent_params[4] = '\0'; - - if (simulate_uevent("block", devpath, "add", uevent_params) < 0) { - LOGE("Error simulating uevent (%s)", strerror(errno)); - return -errno; - } - return 0; -} diff --git a/vold/mmc.h b/vold/mmc.h deleted file mode 100644 index 5a5d184..0000000 --- a/vold/mmc.h +++ /dev/null @@ -1,23 +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 _MMC_H -#define _MMC_H - -#define SYSFS_CLASS_MMC_PATH "/sys/class/mmc_host" - -#endif diff --git a/vold/switch.c b/vold/switch.c deleted file mode 100644 index d8dab43..0000000 --- a/vold/switch.c +++ /dev/null @@ -1,124 +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 <stdlib.h> -#include <string.h> -#include <dirent.h> -#include <errno.h> - -#include <sys/types.h> - -#include "vold.h" -#include "switch.h" - -#define DEBUG_BOOTSTRAP 0 - -static int mmc_bootstrap_switch(char *sysfs_path); - -int switch_bootstrap() -{ - DIR *d; - struct dirent *de; - - if (!(d = opendir(SYSFS_CLASS_SWITCH_PATH))) { - LOG_ERROR("Unable to open '%s' (%s)", SYSFS_CLASS_SWITCH_PATH, - strerror(errno)); - return -errno; - } - - while ((de = readdir(d))) { - char tmp[255]; - - if (de->d_name[0] == '.') - continue; - - sprintf(tmp, "%s/%s", SYSFS_CLASS_SWITCH_PATH, de->d_name); - if (mmc_bootstrap_switch(tmp)) { - LOG_ERROR("Error bootstrapping switch '%s' (%s)", tmp, - strerror(errno)); - } - } - - closedir(d); - - return 0; -} - -static int mmc_bootstrap_switch(char *sysfs_path) -{ -#if DEBUG_BOOTSTRAP - LOG_VOL("bootstrap_switch(%s):", sysfs_path); -#endif - - char filename[255]; - char name[255]; - char state[255]; - char tmp[255]; - char *uevent_params[3]; - char devpath[255]; - FILE *fp; - - /* - * Read switch name - */ - sprintf(filename, "%s/name", sysfs_path); - if (!(fp = fopen(filename, "r"))) { - LOGE("Error opening switch name path '%s' (%s)", - sysfs_path, strerror(errno)); - return -errno; - } - if (!fgets(name, sizeof(name), fp)) { - LOGE("Unable to read switch name"); - fclose(fp); - return -EIO; - } - fclose(fp); - - name[strlen(name) -1] = '\0'; - sprintf(devpath, "/devices/virtual/switch/%s", name); - sprintf(tmp, "SWITCH_NAME=%s", name); - uevent_params[0] = (char *) strdup(tmp); - - /* - * Read switch state - */ - sprintf(filename, "%s/state", sysfs_path); - if (!(fp = fopen(filename, "r"))) { - LOGE("Error opening switch state path '%s' (%s)", - sysfs_path, strerror(errno)); - return -errno; - } - if (!fgets(state, sizeof(state), fp)) { - LOGE("Unable to read switch state"); - fclose(fp); - return -EIO; - } - fclose(fp); - - state[strlen(state) -1] = '\0'; - sprintf(tmp, "SWITCH_STATE=%s", state); - uevent_params[1] = (char *) strdup(tmp); - - uevent_params[2] = (char *) NULL; - - if (simulate_uevent("switch", devpath, "add", uevent_params) < 0) { - LOGE("Error simulating uevent (%s)", strerror(errno)); - return -errno; - } - - return 0; -} diff --git a/vold/uevent.c b/vold/uevent.c deleted file mode 100644 index dc15d80..0000000 --- a/vold/uevent.c +++ /dev/null @@ -1,447 +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 <stdlib.h> -#include <errno.h> - -#include <sys/types.h> -#include <sys/socket.h> - -#include "vold.h" -#include "uevent.h" -#include "mmc.h" -#include "blkdev.h" -#include "volmgr.h" -#include "media.h" - -#define DEBUG_UEVENT 0 - -#define UEVENT_PARAMS_MAX 32 - -enum uevent_action { action_add, action_remove, action_change }; - -struct uevent { - char *path; - enum uevent_action action; - char *subsystem; - char *param[UEVENT_PARAMS_MAX]; - unsigned int seqnum; -}; - -struct uevent_dispatch { - char *subsystem; - int (* dispatch) (struct uevent *); -}; - -static void dump_uevent(struct uevent *); -static int dispatch_uevent(struct uevent *event); -static void free_uevent(struct uevent *event); -static char *get_uevent_param(struct uevent *event, char *param_name); - -static int handle_powersupply_event(struct uevent *event); -static int handle_switch_event(struct uevent *); -static int handle_battery_event(struct uevent *); -static int handle_mmc_event(struct uevent *); -static int handle_block_event(struct uevent *); -static int handle_bdi_event(struct uevent *); -static void _cb_blkdev_ok_to_destroy(blkdev_t *dev); - -static struct uevent_dispatch dispatch_table[] = { - { "switch", handle_switch_event }, - { "battery", handle_battery_event }, - { "mmc", handle_mmc_event }, - { "block", handle_block_event }, - { "bdi", handle_bdi_event }, - { "power_supply", handle_powersupply_event }, - { NULL, NULL } -}; - -static boolean low_batt = false; -static boolean door_open = true; - -int process_uevent_message(int socket) -{ - char buffer[64 * 1024]; // Thank god we're not in the kernel :) - int count; - char *s = buffer; - char *end; - struct uevent *event; - int param_idx = 0; - int i; - int first = 1; - int rc = 0; - - if ((count = recv(socket, buffer, sizeof(buffer), 0)) < 0) { - LOGE("Error receiving uevent (%s)", strerror(errno)); - return -errno; - } - - if (!(event = malloc(sizeof(struct uevent)))) { - LOGE("Error allocating memory (%s)", strerror(errno)); - return -errno; - } - - memset(event, 0, sizeof(struct uevent)); - - end = s + count; - while (s < end) { - if (first) { - char *p; - for (p = s; *p != '@'; p++); - p++; - event->path = strdup(p); - first = 0; - } else { - if (!strncmp(s, "ACTION=", strlen("ACTION="))) { - char *a = s + strlen("ACTION="); - - if (!strcmp(a, "add")) - event->action = action_add; - else if (!strcmp(a, "change")) - event->action = action_change; - else if (!strcmp(a, "remove")) - event->action = action_remove; - } else if (!strncmp(s, "SEQNUM=", strlen("SEQNUM="))) - event->seqnum = atoi(s + strlen("SEQNUM=")); - else if (!strncmp(s, "SUBSYSTEM=", strlen("SUBSYSTEM="))) - event->subsystem = strdup(s + strlen("SUBSYSTEM=")); - else - event->param[param_idx++] = strdup(s); - } - s+= strlen(s) + 1; - } - - rc = dispatch_uevent(event); - - free_uevent(event); - return rc; -} - -int simulate_uevent(char *subsys, char *path, char *action, char **params) -{ - struct uevent *event; - char tmp[255]; - int i, rc; - - if (!(event = malloc(sizeof(struct uevent)))) { - LOGE("Error allocating memory (%s)", strerror(errno)); - return -errno; - } - - memset(event, 0, sizeof(struct uevent)); - - event->subsystem = strdup(subsys); - - if (!strcmp(action, "add")) - event->action = action_add; - else if (!strcmp(action, "change")) - event->action = action_change; - else if (!strcmp(action, "remove")) - event->action = action_remove; - else { - LOGE("Invalid action '%s'", action); - return -1; - } - - event->path = strdup(path); - - for (i = 0; i < UEVENT_PARAMS_MAX; i++) { - if (!params[i]) - break; - event->param[i] = strdup(params[i]); - } - - rc = dispatch_uevent(event); - free_uevent(event); - return rc; -} - -static int dispatch_uevent(struct uevent *event) -{ - int i; - -#if DEBUG_UEVENT - dump_uevent(event); -#endif - for (i = 0; dispatch_table[i].subsystem != NULL; i++) { - if (!strcmp(dispatch_table[i].subsystem, event->subsystem)) - return dispatch_table[i].dispatch(event); - } - -#if DEBUG_UEVENT - LOG_VOL("No uevent handlers registered for '%s' subsystem", event->subsystem); -#endif - return 0; -} - -static void dump_uevent(struct uevent *event) -{ - int i; - - LOG_VOL("[UEVENT] Sq: %u S: %s A: %d P: %s", - event->seqnum, event->subsystem, event->action, event->path); - for (i = 0; i < UEVENT_PARAMS_MAX; i++) { - if (!event->param[i]) - break; - LOG_VOL("%s", event->param[i]); - } -} - -static void free_uevent(struct uevent *event) -{ - int i; - free(event->path); - free(event->subsystem); - for (i = 0; i < UEVENT_PARAMS_MAX; i++) { - if (!event->param[i]) - break; - free(event->param[i]); - } - free(event); -} - -static char *get_uevent_param(struct uevent *event, char *param_name) -{ - int i; - - for (i = 0; i < UEVENT_PARAMS_MAX; i++) { - if (!event->param[i]) - break; - if (!strncmp(event->param[i], param_name, strlen(param_name))) - return &event->param[i][strlen(param_name) + 1]; - } - - LOGE("get_uevent_param(): No parameter '%s' found", param_name); - return NULL; -} - -/* - * --------------- - * Uevent Handlers - * --------------- - */ - -static int handle_powersupply_event(struct uevent *event) -{ - char *ps_type = get_uevent_param(event, "POWER_SUPPLY_TYPE"); - - if (!strcasecmp(ps_type, "battery")) { - char *ps_cap = get_uevent_param(event, "POWER_SUPPLY_CAPACITY"); - int capacity = atoi(ps_cap); - - if (capacity < 5) - low_batt = true; - else - low_batt = false; - volmgr_safe_mode(low_batt || door_open); - } - return 0; -} - -static int handle_switch_event(struct uevent *event) -{ - char *name = get_uevent_param(event, "SWITCH_NAME"); - char *state = get_uevent_param(event, "SWITCH_STATE"); - - - if (!strcmp(name, "usb_mass_storage")) { - if (!strcmp(state, "online")) { - ums_hostconnected_set(true); - } else { - ums_hostconnected_set(false); - volmgr_enable_ums(false); - } - } else if (!strcmp(name, "sd-door")) { - if (!strcmp(state, "open")) - door_open = true; - else - door_open = false; - volmgr_safe_mode(low_batt || door_open); - } - - return 0; -} - -static int handle_battery_event(struct uevent *event) -{ - return 0; -} - -static int handle_block_event(struct uevent *event) -{ - char mediapath[255]; - media_t *media; - int n; - int maj, min; - blkdev_t *blkdev; - - /* - * Look for backing media for this block device - */ - if (!strncmp(get_uevent_param(event, "DEVPATH"), - "/devices/virtual/", - strlen("/devices/virtual/"))) { - n = 0; - } else if (!strcmp(get_uevent_param(event, "DEVTYPE"), "disk")) - n = 2; - else if (!strcmp(get_uevent_param(event, "DEVTYPE"), "partition")) - n = 3; - else { - LOGE("Bad blockdev type '%s'", get_uevent_param(event, "DEVTYPE")); - return -EINVAL; - } - - truncate_sysfs_path(event->path, n, mediapath, sizeof(mediapath)); - - if (!(media = media_lookup_by_path(mediapath, false))) { -#if DEBUG_UEVENT - LOG_VOL("No backend media found @ device path '%s'", mediapath); -#endif - return 0; - } - - maj = atoi(get_uevent_param(event, "MAJOR")); - min = atoi(get_uevent_param(event, "MINOR")); - - if (event->action == action_add) { - blkdev_t *disk; - - /* - * If there isn't a disk already its because *we* - * are the disk - */ - if (media->media_type == media_mmc) - disk = blkdev_lookup_by_devno(maj, ALIGN_MMC_MINOR(min)); - else - disk = blkdev_lookup_by_devno(maj, 0); - - if (!(blkdev = blkdev_create(disk, - event->path, - maj, - min, - media, - get_uevent_param(event, "DEVTYPE")))) { - LOGE("Unable to allocate new blkdev (%s)", strerror(errno)); - return -1; - } - - blkdev_refresh(blkdev); - - /* - * Add the blkdev to media - */ - int rc; - if ((rc = media_add_blkdev(media, blkdev)) < 0) { - LOGE("Unable to add blkdev to card (%d)", rc); - return rc; - } - - LOGI("New blkdev %d.%d on media %s, media path %s, Dpp %d", - blkdev->major, blkdev->minor, media->name, mediapath, - blkdev_get_num_pending_partitions(blkdev->disk)); - - if (blkdev_get_num_pending_partitions(blkdev->disk) == 0) { - if ((rc = volmgr_consider_disk(blkdev->disk)) < 0) { - if (rc == -EBUSY) { - LOGI("Volmgr not ready to handle device"); - } else { - LOGE("Volmgr failed to handle device (%d)", rc); - return rc; - } - } - } - } else if (event->action == action_remove) { - if (!(blkdev = blkdev_lookup_by_devno(maj, min))) - return 0; - - LOGI("Destroying blkdev %d.%d @ %s on media %s", blkdev->major, - blkdev->minor, blkdev->devpath, media->name); - volmgr_notify_eject(blkdev, _cb_blkdev_ok_to_destroy); - - } else if (event->action == action_change) { - if (!(blkdev = blkdev_lookup_by_devno(maj, min))) - return 0; - - LOGI("Modified blkdev %d.%d @ %s on media %s", blkdev->major, - blkdev->minor, blkdev->devpath, media->name); - - blkdev_refresh(blkdev); - } else { -#if DEBUG_UEVENT - LOG_VOL("No handler implemented for action %d", event->action); -#endif - } - return 0; -} - -static void _cb_blkdev_ok_to_destroy(blkdev_t *dev) -{ - media_t *media = media_lookup_by_dev(dev); - if (media) - media_remove_blkdev(media, dev); - blkdev_destroy(dev); -} - -static int handle_bdi_event(struct uevent *event) -{ - return 0; -} - -static int handle_mmc_event(struct uevent *event) -{ - if (event->action == action_add) { - media_t *media; - char serial[80]; - char *type; - - /* - * Pull card information from sysfs - */ - type = get_uevent_param(event, "MMC_TYPE"); - if (strcmp(type, "SD") && strcmp(type, "MMC")) - return 0; - - read_sysfs_var(serial, sizeof(serial), event->path, "serial"); - if (!(media = media_create(event->path, - get_uevent_param(event, "MMC_NAME"), - serial, - media_mmc))) { - LOGE("Unable to allocate new media (%s)", strerror(errno)); - return -1; - } - LOGI("New MMC card '%s' (serial %u) added @ %s", media->name, - media->serial, media->devpath); - } else if (event->action == action_remove) { - media_t *media; - - if (!(media = media_lookup_by_path(event->path, false))) { - LOGE("Unable to lookup media '%s'", event->path); - return -1; - } - - LOGI("MMC card '%s' (serial %u) @ %s removed", media->name, - media->serial, media->devpath); - media_destroy(media); - } else { -#if DEBUG_UEVENT - LOG_VOL("No handler implemented for action %d", event->action); -#endif - } - - return 0; -} diff --git a/vold/uevent.h b/vold/uevent.h deleted file mode 100644 index 0e9e671..0000000 --- a/vold/uevent.h +++ /dev/null @@ -1,21 +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 _UEVENT_MSG_H -#define _UEVENT_MSG_H - -#endif diff --git a/vold/ums.c b/vold/ums.c deleted file mode 100644 index 4d0fc25..0000000 --- a/vold/ums.c +++ /dev/null @@ -1,129 +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 <fcntl.h> -#include <errno.h> - -#include "vold.h" -#include "ums.h" - -#define DEBUG_UMS 0 - -static boolean host_connected = false; -static boolean ums_enabled = false; - -int ums_bootstrap(void) -{ - return 0; -} - -void ums_enabled_set(boolean enabled) -{ - ums_enabled = enabled; - send_msg(enabled ? VOLD_EVT_UMS_ENABLED : VOLD_EVT_UMS_DISABLED); -} - -boolean ums_enabled_get() -{ - return ums_enabled; -} - -void ums_hostconnected_set(boolean connected) -{ -#if DEBUG_UMS - LOG_VOL("ums_hostconnected_set(%d):", connected); -#endif - host_connected = connected; - - if (!connected) - ums_enabled_set(false); - send_msg(connected ? VOLD_EVT_UMS_CONNECTED : VOLD_EVT_UMS_DISCONNECTED); -} - -int ums_enable(char *dev_fspath, char *lun_syspath) -{ - LOG_VOL("ums_enable(%s, %s):", dev_fspath, lun_syspath); - - int fd; - char filename[255]; - - sprintf(filename, "/sys/%s/file", lun_syspath); - if ((fd = open(filename, O_WRONLY)) < 0) { - LOGE("Unable to open '%s' (%s)", filename, strerror(errno)); - return -errno; - } - - if (write(fd, dev_fspath, strlen(dev_fspath)) < 0) { - LOGE("Unable to write to ums lunfile (%s)", strerror(errno)); - close(fd); - return -errno; - } - - close(fd); - return 0; -} - -int ums_disable(char *lun_syspath) -{ -#if DEBUG_UMS - LOG_VOL("ums_disable(%s):", lun_syspath); -#endif - - int fd; - char filename[255]; - - sprintf(filename, "/sys/%s/file", lun_syspath); - if ((fd = open(filename, O_WRONLY)) < 0) { - LOGE("Unable to open '%s' (%s)", filename, strerror(errno)); - return -errno; - } - - char ch = 0; - - if (write(fd, &ch, 1) < 0) { - LOGE("Unable to write to ums lunfile (%s)", strerror(errno)); - close(fd); - return -errno; - } - - close(fd); - return 0; -} - -boolean ums_hostconnected_get(void) -{ - return host_connected; -} - -int ums_send_status(void) -{ - int rc; - -#if DEBUG_UMS - LOG_VOL("ums_send_status():"); -#endif - - rc = send_msg(ums_enabled_get() ? VOLD_EVT_UMS_ENABLED : - VOLD_EVT_UMS_DISABLED); - if (rc < 0) - return rc; - - rc = send_msg(ums_hostconnected_get() ? VOLD_EVT_UMS_CONNECTED : - VOLD_EVT_UMS_DISCONNECTED); - - return rc; -} diff --git a/vold/ums.h b/vold/ums.h deleted file mode 100644 index 02cdec3..0000000 --- a/vold/ums.h +++ /dev/null @@ -1,31 +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 _UMS_H -#define _UMS_H - -// these must match the corresponding strings in java/android/android/os/UsbListener.java -#define VOLD_EVT_UMS_ENABLED "ums_enabled" -#define VOLD_EVT_UMS_DISABLED "ums_disabled" -#define VOLD_EVT_UMS_CONNECTED "ums_connected" -#define VOLD_EVT_UMS_DISCONNECTED "ums_disconnected" - - -int ums_send_status(void); -int ums_enable(char *device_file, char *lun_syspath); -int ums_disable(char *lun_syspath); -#endif diff --git a/vold/vold.c b/vold/vold.c deleted file mode 100644 index 11b99a9..0000000 --- a/vold/vold.c +++ /dev/null @@ -1,238 +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 <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <fcntl.h> -#include <pthread.h> - -#include <sys/socket.h> -#include <sys/select.h> -#include <sys/time.h> -#include <sys/types.h> -#include <sys/un.h> - -#include <cutils/config_utils.h> -#include <cutils/cpu_info.h> -#include <cutils/properties.h> -#include <cutils/sockets.h> - -#include <linux/netlink.h> - -#include <private/android_filesystem_config.h> - -#include "vold.h" -#include "volmgr.h" - - -#define VOLD_SOCKET "vold" - -/* - * Globals - */ - -static int ver_major = 2; -static int ver_minor = 0; -static pthread_mutex_t write_mutex = PTHREAD_MUTEX_INITIALIZER; -static int fw_sock = -1; - -int bootstrap = 0; - -int main(int argc, char **argv) -{ - int door_sock = -1; - int uevent_sock = -1; - struct sockaddr_nl nladdr; - int uevent_sz = 64 * 1024; - - LOGI("Android Volume Daemon version %d.%d", ver_major, ver_minor); - - /* - * Create all the various sockets we'll need - */ - - // Socket to listen on for incomming framework connections - if ((door_sock = android_get_control_socket(VOLD_SOCKET)) < 0) { - LOGE("Obtaining file descriptor socket '%s' failed: %s", - VOLD_SOCKET, strerror(errno)); - exit(1); - } - - if (listen(door_sock, 4) < 0) { - LOGE("Unable to listen on fd '%d' for socket '%s': %s", - door_sock, VOLD_SOCKET, strerror(errno)); - exit(1); - } - - mkdir("/dev/block/vold", 0755); - - // Socket to listen on for uevent changes - memset(&nladdr, 0, sizeof(nladdr)); - nladdr.nl_family = AF_NETLINK; - nladdr.nl_pid = getpid(); - nladdr.nl_groups = 0xffffffff; - - if ((uevent_sock = socket(PF_NETLINK, - SOCK_DGRAM,NETLINK_KOBJECT_UEVENT)) < 0) { - LOGE("Unable to create uevent socket: %s", strerror(errno)); - exit(1); - } - - if (setsockopt(uevent_sock, SOL_SOCKET, SO_RCVBUFFORCE, &uevent_sz, - sizeof(uevent_sz)) < 0) { - LOGE("Unable to set uevent socket options: %s", strerror(errno)); - exit(1); - } - - if (bind(uevent_sock, (struct sockaddr *) &nladdr, sizeof(nladdr)) < 0) { - LOGE("Unable to bind uevent socket: %s", strerror(errno)); - exit(1); - } - - /* - * Bootstrap - */ - - bootstrap = 1; - // Volume Manager - volmgr_bootstrap(); - - // SD Card system - mmc_bootstrap(); - - // USB Mass Storage - ums_bootstrap(); - - // Switch - switch_bootstrap(); - - bootstrap = 0; - /* - * Main loop - */ - LOG_VOL("Bootstrapping complete"); - while(1) { - fd_set read_fds; - struct timeval to; - int max = 0; - int rc = 0; - - to.tv_sec = (60 * 60); - to.tv_usec = 0; - - FD_ZERO(&read_fds); - FD_SET(door_sock, &read_fds); - if (door_sock > max) - max = door_sock; - FD_SET(uevent_sock, &read_fds); - if (uevent_sock > max) - max = uevent_sock; - - if (fw_sock != -1) { - FD_SET(fw_sock, &read_fds); - if (fw_sock > max) - max = fw_sock; - } - - if ((rc = select(max + 1, &read_fds, NULL, NULL, &to)) < 0) { - LOGE("select() failed (%s)", strerror(errno)); - sleep(1); - continue; - } - - if (!rc) { - continue; - } - - if (FD_ISSET(door_sock, &read_fds)) { - struct sockaddr addr; - socklen_t alen; - - alen = sizeof(addr); - - if (fw_sock != -1) { - LOGE("Dropping duplicate framework connection"); - int tmp = accept(door_sock, &addr, &alen); - close(tmp); - continue; - } - - if ((fw_sock = accept(door_sock, &addr, &alen)) < 0) { - LOGE("Unable to accept framework connection (%s)", - strerror(errno)); - } - LOG_VOL("Accepted connection from framework"); - if ((rc = volmgr_send_states()) < 0) { - LOGE("Unable to send volmgr status to framework (%d)", rc); - } - } - - if (FD_ISSET(fw_sock, &read_fds)) { - if ((rc = process_framework_command(fw_sock)) < 0) { - if (rc == -ECONNRESET) { - LOGE("Framework disconnected"); - close(fw_sock); - fw_sock = -1; - } else { - LOGE("Error processing framework command (%s)", - strerror(errno)); - } - } - } - - if (FD_ISSET(uevent_sock, &read_fds)) { - if ((rc = process_uevent_message(uevent_sock)) < 0) { - LOGE("Error processing uevent msg (%s)", strerror(errno)); - } - } - } // while - -} - -int send_msg(char* message) -{ - int result = -1; - - pthread_mutex_lock(&write_mutex); - -// LOG_VOL("send_msg(%s):", message); - - if (fw_sock >= 0) - result = write(fw_sock, message, strlen(message) + 1); - - pthread_mutex_unlock(&write_mutex); - - return result; -} - -int send_msg_with_data(char *message, char *data) -{ - int result = -1; - - char* buffer = (char *)alloca(strlen(message) + strlen(data) + 1); - if (!buffer) { - LOGE("alloca failed in send_msg_with_data"); - return -1; - } - - strcpy(buffer, message); - strcat(buffer, data); - return send_msg(buffer); -} diff --git a/vold/vold.h b/vold/vold.h deleted file mode 100644 index abc27a1..0000000 --- a/vold/vold.h +++ /dev/null @@ -1,101 +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 VOLD_H__ -#define VOLD_H__ - -#define LOG_TAG "vold" -#include "cutils/log.h" - -typedef int boolean; -enum { - false = 0, - true = 1 -}; - -#define DEVPATH "/dev/block/" -#define DEVPATHLENGTH 11 - -#define WEXITSTATUS(status) (((status) & 0xff00) >> 8) - -// Set this for logging error messages -#define ENABLE_LOG_ERROR - -// set this to log vold events -#define ENABLE_LOG_VOL - -#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_VOL -#define LOG_VOL(fmt, args...) \ - { LOGD(fmt , ## args); } -#else -#define LOG_VOL(fmt, args...) \ - do { } while (0) -#endif /* ENABLE_LOG_VOL */ - -#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 */ - -/* - * Prototypes - */ - -int process_framework_command(int socket); - -int process_inotify_event(int fd); -int inotify_bootstrap(void); - -int process_uevent_message(int socket); -int simulate_uevent(char *subsystem, char *path, char *action, char **params); - -int mmc_bootstrap(void); -int ums_bootstrap(void); - -int volmgr_bootstrap(void); - -int switch_bootstrap(void); - -void *read_file(char *filename, ssize_t *_size); -char *truncate_sysfs_path(char *path, int num_elements_to_remove, char *buffer, int buffer_size); -char *read_sysfs_var(char *buffer, size_t maxlen, char *devpath, char *var); - -void ums_hostconnected_set(boolean connected); -boolean ums_hostconnected_get(void); - -int send_msg(char *msg); -int send_msg_with_data(char *msg, char *data); -extern int bootstrap; -#endif diff --git a/vold/volmgr.c b/vold/volmgr.c deleted file mode 100644 index a635b8e..0000000 --- a/vold/volmgr.c +++ /dev/null @@ -1,1247 +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 <stdlib.h> -#include <string.h> -#include <errno.h> -#include <dirent.h> -#include <unistd.h> -#include <sched.h> - -#include <sys/mount.h> - -#include <cutils/config_utils.h> -#include <cutils/properties.h> - -#include "vold.h" -#include "volmgr.h" -#include "blkdev.h" -#include "ums.h" -#include "format.h" -#include "devmapper.h" - -#include "volmgr_ext3.h" -#include "volmgr_vfat.h" - -#define DEBUG_VOLMGR 0 - -static volume_t *vol_root = NULL; -static boolean safe_mode = true; - -static struct volmgr_fstable_entry fs_table[] = { -// { "ext3", ext_identify, ext_check, ext_mount , true }, - { "vfat", vfat_identify, vfat_check, vfat_mount , false }, - { NULL, NULL, NULL, NULL , false} -}; - -struct _volume_state_event_map { - volume_state_t state; - char *event; - char *property_val; -}; - -static struct _volume_state_event_map volume_state_strings[] = { - { volstate_unknown, "volstate_unknown:", "unknown" }, - { volstate_nomedia, VOLD_EVT_NOMEDIA, VOLD_ES_PVAL_NOMEDIA }, - { volstate_unmounted, VOLD_EVT_UNMOUNTED, VOLD_ES_PVAL_UNMOUNTED }, - { volstate_checking, VOLD_EVT_CHECKING, VOLD_ES_PVAL_CHECKING }, - { volstate_mounted, VOLD_EVT_MOUNTED, VOLD_ES_PVAL_MOUNTED }, - { volstate_mounted_ro, VOLD_EVT_MOUNTED_RO, VOLD_ES_PVAL_MOUNTED_RO }, - { volstate_badremoval, VOLD_EVT_BADREMOVAL, VOLD_ES_PVAL_BADREMOVAL }, - { volstate_damaged, VOLD_EVT_DAMAGED, VOLD_ES_PVAL_DAMAGED }, - { volstate_nofs, VOLD_EVT_NOFS, VOLD_ES_PVAL_NOFS }, - { volstate_ums, VOLD_EVT_UMS, VOLD_ES_PVAL_UMS }, - { 0, NULL, NULL } -}; - - -static int volmgr_readconfig(char *cfg_path); -static int volmgr_config_volume(cnode *node); -static volume_t *volmgr_lookup_volume_by_mediapath(char *media_path, boolean fuzzy); -static volume_t *volmgr_lookup_volume_by_dev(blkdev_t *dev); -static int _volmgr_start(volume_t *vol, blkdev_t *dev); -static int volmgr_start_fs(struct volmgr_fstable_entry *fs, volume_t *vol, blkdev_t *dev); -static void *volmgr_start_fs_thread(void *arg); -static void volmgr_start_fs_thread_sighandler(int signo); -static void volume_setstate(volume_t *vol, volume_state_t state); -static char *conv_volstate_to_eventstr(volume_state_t state); -static char *conv_volstate_to_propstr(volume_state_t state); -static int volume_send_state(volume_t *vol); -static void _cb_volstopped_for_ums_enable(volume_t *v, void *arg); -static int _volmgr_enable_ums(volume_t *); -static int volmgr_shutdown_volume(volume_t *v, void (* cb) (volume_t *, void *arg), boolean emit_statechange); -static int volmgr_stop_volume(volume_t *v, void (*cb) (volume_t *, void *), void *arg, boolean emit_statechange); -static void _cb_volume_stopped_for_eject(volume_t *v, void *arg); -static void _cb_volume_stopped_for_shutdown(volume_t *v, void *arg); -static int _volmgr_consider_disk_and_vol(volume_t *vol, blkdev_t *dev); -static void volmgr_uncage_reaper(volume_t *vol, void (* cb) (volume_t *, void *arg), void *arg); -static void volmgr_reaper_thread_sighandler(int signo); -static void volmgr_add_mediapath_to_volume(volume_t *v, char *media_path); -static int volmgr_send_eject_request(volume_t *v); -static volume_t *volmgr_lookup_volume_by_mountpoint(char *mount_point, boolean leave_locked); - -static boolean _mountpoint_mounted(char *mp) -{ - char device[256]; - char mount_path[256]; - char rest[256]; - FILE *fp; - char line[1024]; - - if (!(fp = fopen("/proc/mounts", "r"))) { - LOGE("Error opening /proc/mounts (%s)", strerror(errno)); - return false; - } - - while(fgets(line, sizeof(line), fp)) { - line[strlen(line)-1] = '\0'; - sscanf(line, "%255s %255s %255s\n", device, mount_path, rest); - if (!strcmp(mount_path, mp)) { - fclose(fp); - return true; - } - - } - - fclose(fp); - return false; -} - -/* - * Public functions - */ - -int volmgr_set_volume_key(char *mount_point, unsigned char *key) -{ - volume_t *v = volmgr_lookup_volume_by_mountpoint(mount_point, true); - - if (!v) - return -ENOENT; - - if (v->media_type != media_devmapper) { - LOGE("Cannot set key on a non devmapper volume"); - pthread_mutex_unlock(&v->lock); - return -EINVAL; - } - - memcpy(v->dm->key, key, sizeof(v->dm->key)); - pthread_mutex_unlock(&v->lock); - return 0; -} - -int volmgr_format_volume(char *mount_point) -{ - int rc; - volume_t *v; - - LOG_VOL("volmgr_format_volume(%s):", mount_point); - - v = volmgr_lookup_volume_by_mountpoint(mount_point, true); - - if (!v) - return -ENOENT; - - if (v->state == volstate_mounted || - v->state == volstate_mounted_ro || - v->state == volstate_ums || - v->state == volstate_checking) { - LOGE("Can't format '%s', currently in state %d", mount_point, v->state); - pthread_mutex_unlock(&v->lock); - return -EBUSY; - } else if (v->state == volstate_nomedia && - v->media_type != media_devmapper) { - LOGE("Can't format '%s', (no media)", mount_point); - pthread_mutex_unlock(&v->lock); - return -ENOMEDIUM; - } - - // XXX:Reject if the underlying source media is not present - - if (v->media_type == media_devmapper) { - if ((rc = devmapper_genesis(v->dm)) < 0) { - LOGE("devmapper genesis failed for %s (%d)", mount_point, rc); - pthread_mutex_unlock(&v->lock); - return rc; - } - } else { - if ((rc = initialize_mbr(v->dev->disk)) < 0) { - LOGE("MBR init failed for %s (%d)", mount_point, rc); - pthread_mutex_unlock(&v->lock); - return rc; - } - } - - volume_setstate(v, volstate_formatting); - pthread_mutex_unlock(&v->lock); - return rc; -} - -int volmgr_bootstrap(void) -{ - int rc; - - if ((rc = volmgr_readconfig("/system/etc/vold.conf")) < 0) { - LOGE("Unable to process config"); - return rc; - } - - /* - * Check to see if any of our volumes is mounted - */ - volume_t *v = vol_root; - while (v) { - if (_mountpoint_mounted(v->mount_point)) { - LOGW("Volume '%s' already mounted at startup", v->mount_point); - v->state = volstate_mounted; - } - v = v->next; - } - - return 0; -} - -int volmgr_safe_mode(boolean enable) -{ - if (enable == safe_mode) - return 0; - - safe_mode = enable; - - volume_t *v = vol_root; - int rc; - - while (v) { - pthread_mutex_lock(&v->lock); - if (v->state == volstate_mounted && v->fs) { - rc = v->fs->mount_fn(v->dev, v, safe_mode); - if (!rc) { - LOGI("Safe mode %s on %s", (enable ? "enabled" : "disabled"), v->mount_point); - } else { - LOGE("Failed to %s safe-mode on %s (%s)", - (enable ? "enable" : "disable" ), v->mount_point, strerror(-rc)); - } - } - - pthread_mutex_unlock(&v->lock); - v = v->next; - } - - return 0; -} - -int volmgr_send_states(void) -{ - volume_t *vol_scan = vol_root; - int rc; - - while (vol_scan) { - pthread_mutex_lock(&vol_scan->lock); - if ((rc = volume_send_state(vol_scan)) < 0) { - LOGE("Error sending state to framework (%d)", rc); - } - pthread_mutex_unlock(&vol_scan->lock); - vol_scan = vol_scan->next; - break; // XXX: - } - - return 0; -} - -/* - * Called when a block device is ready to be - * evaluated by the volume manager. - */ -int volmgr_consider_disk(blkdev_t *dev) -{ - volume_t *vol; - - if (!(vol = volmgr_lookup_volume_by_mediapath(dev->media->devpath, true))) - return 0; - - pthread_mutex_lock(&vol->lock); - - if (vol->state == volstate_mounted) { - LOGE("Volume %s already mounted (did we just crash?)", vol->mount_point); - pthread_mutex_unlock(&vol->lock); - return 0; - } - - int rc = _volmgr_consider_disk_and_vol(vol, dev); - pthread_mutex_unlock(&vol->lock); - return rc; -} - -int volmgr_start_volume_by_mountpoint(char *mount_point) -{ - volume_t *v; - - v = volmgr_lookup_volume_by_mountpoint(mount_point, true); - if (!v) - return -ENOENT; - - if (v->media_type == media_devmapper) { - if (devmapper_start(v->dm) < 0) { - LOGE("volmgr failed to start devmapper volume '%s'", - v->mount_point); - } - } else if (v->media_type == media_mmc) { - if (!v->dev) { - LOGE("Cannot start volume '%s' (volume is not bound)", mount_point); - pthread_mutex_unlock(&v->lock); - return -ENOENT; - } - - if (_volmgr_consider_disk_and_vol(v, v->dev->disk) < 0) { - LOGE("volmgr failed to start volume '%s'", v->mount_point); - } - } - - pthread_mutex_unlock(&v->lock); - return 0; -} - -static void _cb_volstopped_for_devmapper_teardown(volume_t *v, void *arg) -{ - devmapper_stop(v->dm); - volume_setstate(v, volstate_nomedia); - pthread_mutex_unlock(&v->lock); -} - -int volmgr_stop_volume_by_mountpoint(char *mount_point) -{ - int rc; - volume_t *v; - - v = volmgr_lookup_volume_by_mountpoint(mount_point, true); - if (!v) - return -ENOENT; - - if (v->state == volstate_mounted) - volmgr_send_eject_request(v); - - if (v->media_type == media_devmapper) - rc = volmgr_shutdown_volume(v, _cb_volstopped_for_devmapper_teardown, false); - else - rc = volmgr_shutdown_volume(v, NULL, true); - - /* - * If shutdown returns -EINPROGRESS, - * do *not* release the lock as - * it is now owned by the reaper thread - */ - if (rc != -EINPROGRESS) { - if (rc) - LOGE("unable to shutdown volume '%s'", v->mount_point); - pthread_mutex_unlock(&v->lock); - } - return 0; -} - -int volmgr_notify_eject(blkdev_t *dev, void (* cb) (blkdev_t *)) -{ - LOG_VOL("Volmgr notified of %d:%d eject", dev->major, dev->minor); - - volume_t *v; - int rc; - - // XXX: Partitioning support is going to need us to stop *all* - // devices in this volume - if (!(v = volmgr_lookup_volume_by_dev(dev))) { - if (cb) - cb(dev); - return 0; - } - - pthread_mutex_lock(&v->lock); - - volume_state_t old_state = v->state; - - if (v->state == volstate_mounted || - v->state == volstate_ums || - v->state == volstate_checking) { - - volume_setstate(v, volstate_badremoval); - - /* - * Stop any devmapper volumes which - * are using us as a source - * XXX: We may need to enforce stricter - * order here - */ - volume_t *dmvol = vol_root; - while (dmvol) { - if ((dmvol->media_type == media_devmapper) && - (dmvol->dm->src_type == dmsrc_loopback) && - (!strncmp(dmvol->dm->type_data.loop.loop_src, - v->mount_point, strlen(v->mount_point)))) { - - pthread_mutex_lock(&dmvol->lock); - if (dmvol->state != volstate_nomedia) { - rc = volmgr_shutdown_volume(dmvol, _cb_volstopped_for_devmapper_teardown, false); - if (rc != -EINPROGRESS) { - if (rc) - LOGE("unable to shutdown volume '%s'", v->mount_point); - pthread_mutex_unlock(&dmvol->lock); - } - } else - pthread_mutex_unlock(&dmvol->lock); - } - dmvol = dmvol->next; - } - - } else if (v->state == volstate_formatting) { - /* - * The device is being ejected due to - * kernel disk revalidation. - */ - LOG_VOL("Volmgr ignoring eject of %d:%d (volume formatting)", - dev->major, dev->minor); - if (cb) - cb(dev); - pthread_mutex_unlock(&v->lock); - return 0; - } else - volume_setstate(v, volstate_nomedia); - - if (old_state == volstate_ums) { - ums_disable(v->ums_path); - pthread_mutex_unlock(&v->lock); - } else { - int rc = volmgr_stop_volume(v, _cb_volume_stopped_for_eject, cb, false); - if (rc != -EINPROGRESS) { - if (rc) - LOGE("unable to shutdown volume '%s'", v->mount_point); - pthread_mutex_unlock(&v->lock); - } - } - return 0; -} - -static void _cb_volume_stopped_for_eject(volume_t *v, void *arg) -{ - void (* eject_cb) (blkdev_t *) = arg; - -#if DEBUG_VOLMGR - LOG_VOL("Volume %s has been stopped for eject", v->mount_point); -#endif - - if (eject_cb) - eject_cb(v->dev); - v->dev = NULL; // Clear dev because its being ejected -} - -/* - * Instructs the volume manager to enable or disable USB mass storage - * on any volumes configured to use it. - */ -int volmgr_enable_ums(boolean enable) -{ - volume_t *v = vol_root; - - while(v) { - if (v->ums_path) { - int rc; - - if (enable) { - pthread_mutex_lock(&v->lock); - if (v->state == volstate_mounted) - volmgr_send_eject_request(v); - else if (v->state == volstate_ums || v->state == volstate_nomedia) { - pthread_mutex_unlock(&v->lock); - goto next_vol; - } - - // Stop the volume, and enable UMS in the callback - rc = volmgr_shutdown_volume(v, _cb_volstopped_for_ums_enable, false); - if (rc != -EINPROGRESS) { - if (rc) - LOGE("unable to shutdown volume '%s'", v->mount_point); - pthread_mutex_unlock(&v->lock); - } - } else { - // Disable UMS - pthread_mutex_lock(&v->lock); - if (v->state != volstate_ums) { - pthread_mutex_unlock(&v->lock); - goto next_vol; - } - - if ((rc = ums_disable(v->ums_path)) < 0) { - LOGE("unable to disable ums on '%s'", v->mount_point); - pthread_mutex_unlock(&v->lock); - continue; - } - - LOG_VOL("Kick-starting volume %d:%d after UMS disable", - v->dev->disk->major, v->dev->disk->minor); - // Start volume - if ((rc = _volmgr_consider_disk_and_vol(v, v->dev->disk)) < 0) { - LOGE("volmgr failed to consider disk %d:%d", - v->dev->disk->major, v->dev->disk->minor); - } - pthread_mutex_unlock(&v->lock); - } - } - next_vol: - v = v->next; - } - return 0; -} - -/* - * Static functions - */ - -static int volmgr_send_eject_request(volume_t *v) -{ - return send_msg_with_data(VOLD_EVT_EJECTING, v->mount_point); -} - -// vol->lock must be held! -static int _volmgr_consider_disk_and_vol(volume_t *vol, blkdev_t *dev) -{ - int rc = 0; - -#if DEBUG_VOLMGR - LOG_VOL("volmgr_consider_disk_and_vol(%s, %d:%d):", vol->mount_point, - dev->major, dev->minor); -#endif - - if (vol->state == volstate_unknown || - vol->state == volstate_mounted || - vol->state == volstate_mounted_ro) { - LOGE("Cannot consider volume '%s' because it is in state '%d", - vol->mount_point, vol->state); - return -EADDRINUSE; - } - - if (vol->state == volstate_formatting) { - LOG_VOL("Evaluating dev '%s' for formattable filesystems for '%s'", - dev->devpath, vol->mount_point); - /* - * Since we only support creating 1 partition (right now), - * we can just lookup the target by devno - */ - blkdev_t *part; - if (vol->media_type == media_mmc) - part = blkdev_lookup_by_devno(dev->major, ALIGN_MMC_MINOR(dev->minor) + 1); - else - part = blkdev_lookup_by_devno(dev->major, 1); - if (!part) { - if (vol->media_type == media_mmc) - part = blkdev_lookup_by_devno(dev->major, ALIGN_MMC_MINOR(dev->minor)); - else - part = blkdev_lookup_by_devno(dev->major, 0); - if (!part) { - LOGE("Unable to find device to format"); - return -ENODEV; - } - } - - if ((rc = format_partition(part, - vol->media_type == media_devmapper ? - FORMAT_TYPE_EXT2 : FORMAT_TYPE_FAT32)) < 0) { - LOGE("format failed (%d)", rc); - return rc; - } - - } - - LOGI("Evaluating dev '%s' for mountable filesystems for '%s'", - dev->devpath, vol->mount_point); - - if (dev->nr_parts == 0) { - rc = _volmgr_start(vol, dev); -#if DEBUG_VOLMGR - LOG_VOL("_volmgr_start(%s, %d:%d) rc = %d", vol->mount_point, - dev->major, dev->minor, rc); -#endif - } else { - /* - * Device has multiple partitions - * This is where interesting partition policies could be implemented. - * For now just try them in sequence until one succeeds - */ - - rc = -ENODEV; - int i; - for (i = 0; i < dev->nr_parts; i++) { - blkdev_t *part; - if (vol->media_type == media_mmc) - part = blkdev_lookup_by_devno(dev->major, ALIGN_MMC_MINOR(dev->minor) + (i+1)); - else - part = blkdev_lookup_by_devno(dev->major, (i+1)); - if (!part) { - LOGE("Error - unable to lookup partition for blkdev %d:%d", - dev->major, dev->minor); - continue; - } - rc = _volmgr_start(vol, part); -#if DEBUG_VOLMGR - LOG_VOL("_volmgr_start(%s, %d:%d) rc = %d", - vol->mount_point, part->major, part->minor, rc); -#endif - if (!rc || rc == -EBUSY) - break; - } - - if (rc == -ENODEV) { - // Assert to make sure each partition had a backing blkdev - LOGE("Internal consistency error"); - return 0; - } - } - - if (rc == -ENODATA) { - LOGE("Device %d:%d contains no usable filesystems", - dev->major, dev->minor); - rc = 0; - } - - return rc; -} - -static void volmgr_reaper_thread_sighandler(int signo) -{ - LOGE("Volume reaper thread got signal %d", signo); -} - -static void __reaper_cleanup(void *arg) -{ - volume_t *vol = (volume_t *) arg; - - if (vol->worker_args.reaper_args.cb) - vol->worker_args.reaper_args.cb(vol, vol->worker_args.reaper_args.cb_arg); - - vol->worker_running = false; - - // Wake up anyone that was waiting on this thread - pthread_mutex_unlock(&vol->worker_sem); - - // Unlock the volume - pthread_mutex_unlock(&vol->lock); -} - -static void *volmgr_reaper_thread(void *arg) -{ - volume_t *vol = (volume_t *) arg; - - pthread_cleanup_push(__reaper_cleanup, arg); - - vol->worker_running = true; - vol->worker_pid = getpid(); - - struct sigaction actions; - - memset(&actions, 0, sizeof(actions)); - sigemptyset(&actions.sa_mask); - actions.sa_flags = 0; - actions.sa_handler = volmgr_reaper_thread_sighandler; - sigaction(SIGUSR1, &actions, NULL); - - LOGW("Reaper here - working on %s", vol->mount_point); - - boolean send_sig_kill = false; - int i, rc; - - for (i = 0; i < 10; i++) { - errno = 0; - rc = umount(vol->mount_point); - LOGW("volmngr reaper umount(%s) attempt %d (%s)", - vol->mount_point, i + 1, strerror(errno)); - if (!rc) - break; - if (rc && (errno == EINVAL || errno == ENOENT)) { - rc = 0; - break; - } - sleep(1); - if (i >= 4) { - KillProcessesWithOpenFiles(vol->mount_point, send_sig_kill, NULL, 0); - if (!send_sig_kill) - send_sig_kill = true; - } - } - - if (!rc) { - LOGI("Reaper sucessfully unmounted %s", vol->mount_point); - vol->fs = NULL; - volume_setstate(vol, volstate_unmounted); - } else { - LOGE("Unable to unmount!! (%d)", rc); - } - - out: - pthread_cleanup_pop(1); - pthread_exit(NULL); - return NULL; -} - -// vol->lock must be held! -static void volmgr_uncage_reaper(volume_t *vol, void (* cb) (volume_t *, void *arg), void *arg) -{ - - if (vol->worker_running) { - LOGE("Worker thread is currently running.. waiting.."); - pthread_mutex_lock(&vol->worker_sem); - LOGI("Worker thread now available"); - } - - vol->worker_args.reaper_args.cb = cb; - vol->worker_args.reaper_args.cb_arg = arg; - - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - - pthread_create(&vol->worker_thread, &attr, volmgr_reaper_thread, vol); -} - -static int volmgr_stop_volume(volume_t *v, void (*cb) (volume_t *, void *), void *arg, boolean emit_statechange) -{ - int i, rc; - - if (v->state == volstate_mounted || v->state == volstate_badremoval) { - // Try to unmount right away (5 retries) - for (i = 0; i < 5; i++) { - rc = umount(v->mount_point); - if (!rc) - break; - - if (rc && (errno == EINVAL || errno == ENOENT)) { - rc = 0; - break; - } - - LOGI("volmngr quick stop umount(%s) attempt %d (%s)", - v->mount_point, i + 1, strerror(errno)); - - if (i == 0) - usleep(1000 * 250); // First failure, sleep for 250 ms - else - sched_yield(); - } - - if (!rc) { - LOGI("volmgr_stop_volume(%s): Volume unmounted sucessfully", - v->mount_point); - if (emit_statechange) - volume_setstate(v, volstate_unmounted); - v->fs = NULL; - goto out_cb_immed; - } - - /* - * Since the volume is still in use, dispatch the stopping to - * a thread - */ - LOGW("Volume %s is busy (%d) - uncaging the reaper", v->mount_point, rc); - volmgr_uncage_reaper(v, cb, arg); - return -EINPROGRESS; - } else if (v->state == volstate_checking) { - volume_setstate(v, volstate_unmounted); - if (v->worker_running) { - LOG_VOL("Cancelling worker thread"); - pthread_kill(v->worker_thread, SIGUSR1); - } else - LOGE("Strange... we were in checking state but worker thread wasn't running.."); - goto out_cb_immed; - } - - out_cb_immed: - if (cb) - cb(v, arg); - return 0; -} - - -/* - * Gracefully stop a volume - * v->lock must be held! - * if we return -EINPROGRESS, do NOT release the lock as the reaper - * is using the volume - */ -static int volmgr_shutdown_volume(volume_t *v, void (* cb) (volume_t *, void *), boolean emit_statechange) -{ - return volmgr_stop_volume(v, cb, NULL, emit_statechange); -} - -static void _cb_volume_stopped_for_shutdown(volume_t *v, void *arg) -{ - void (* shutdown_cb) (volume_t *) = arg; - -#if DEBUG_VOLMGR - LOG_VOL("Volume %s has been stopped for shutdown", v->mount_point); -#endif - shutdown_cb(v); -} - - -/* - * Called when a volume is sucessfully unmounted for UMS enable - */ -static void _cb_volstopped_for_ums_enable(volume_t *v, void *arg) -{ - int rc; - char *devdir_path; - -#if DEBUG_VOLMGR - LOG_VOL("_cb_volstopped_for_ums_enable(%s):", v->mount_point); -#endif - devdir_path = blkdev_get_devpath(v->dev->disk); - - if ((rc = ums_enable(devdir_path, v->ums_path)) < 0) { - free(devdir_path); - LOGE("Error enabling ums (%d)", rc); - return; - } - free(devdir_path); - volume_setstate(v, volstate_ums); - pthread_mutex_unlock(&v->lock); -} - -static int volmgr_readconfig(char *cfg_path) -{ - cnode *root = config_node("", ""); - cnode *node; - - config_load_file(root, cfg_path); - node = root->first_child; - - while (node) { - if (!strncmp(node->name, "volume_", 7)) - volmgr_config_volume(node); - else - LOGE("Skipping unknown configuration node '%s'", node->name); - node = node->next; - } - return 0; -} - -static void volmgr_add_mediapath_to_volume(volume_t *v, char *media_path) -{ - int i; - -#if DEBUG_VOLMGR - LOG_VOL("volmgr_add_mediapath_to_volume(%p, %s):", v, media_path); -#endif - for (i = 0; i < VOLMGR_MAX_MEDIAPATHS_PER_VOLUME; i++) { - if (!v->media_paths[i]) { - v->media_paths[i] = strdup(media_path); - return; - } - } - LOGE("Unable to add media path '%s' to volume (out of media slots)", media_path); -} - -static int volmgr_config_volume(cnode *node) -{ - volume_t *new; - int rc = 0, i; - - char *dm_src, *dm_src_type, *dm_tgt, *dm_param, *dm_tgtfs; - uint32_t dm_size_mb = 0; - - dm_src = dm_src_type = dm_tgt = dm_param = dm_tgtfs = NULL; -#if DEBUG_VOLMGR - LOG_VOL("volmgr_configure_volume(%s):", node->name); -#endif - if (!(new = malloc(sizeof(volume_t)))) - return -ENOMEM; - memset(new, 0, sizeof(volume_t)); - - new->state = volstate_nomedia; - pthread_mutex_init(&new->lock, NULL); - pthread_mutex_init(&new->worker_sem, NULL); - - cnode *child = node->first_child; - - while (child) { - if (!strcmp(child->name, "media_path")) - volmgr_add_mediapath_to_volume(new, child->value); - else if (!strcmp(child->name, "emu_media_path")) - volmgr_add_mediapath_to_volume(new, child->value); - else if (!strcmp(child->name, "media_type")) { - if (!strcmp(child->value, "mmc")) - new->media_type = media_mmc; - else if (!strcmp(child->value, "devmapper")) - new->media_type = media_devmapper; - else { - LOGE("Invalid media type '%s'", child->value); - rc = -EINVAL; - goto out_free; - } - } else if (!strcmp(child->name, "mount_point")) - new->mount_point = strdup(child->value); - else if (!strcmp(child->name, "ums_path")) - new->ums_path = strdup(child->value); - else if (!strcmp(child->name, "dm_src")) - dm_src = strdup(child->value); - else if (!strcmp(child->name, "dm_src_type")) - dm_src_type = strdup(child->value); - else if (!strcmp(child->name, "dm_src_size_mb")) - dm_size_mb = atoi(child->value); - else if (!strcmp(child->name, "dm_target")) - dm_tgt = strdup(child->value); - else if (!strcmp(child->name, "dm_target_params")) - dm_param = strdup(child->value); - else if (!strcmp(child->name, "dm_target_fs")) - dm_tgtfs = strdup(child->value); - else - LOGE("Ignoring unknown config entry '%s'", child->name); - child = child->next; - } - - if (new->media_type == media_mmc) { - if (!new->media_paths[0] || !new->mount_point || new->media_type == media_unknown) { - LOGE("Required configuration parameter missing for mmc volume"); - rc = -EINVAL; - goto out_free; - } - } else if (new->media_type == media_devmapper) { - if (!dm_src || !dm_src_type || !dm_tgt || - !dm_param || !dm_tgtfs || !dm_size_mb) { - LOGE("Required configuration parameter missing for devmapper volume"); - rc = -EINVAL; - goto out_free; - } - - char dm_mediapath[255]; - if (!(new->dm = devmapper_init(dm_src, dm_src_type, dm_size_mb, - dm_tgt, dm_param, dm_tgtfs, dm_mediapath))) { - LOGE("Unable to initialize devmapping"); - goto out_free; - } - LOG_VOL("media path for devmapper volume = '%s'", dm_mediapath); - volmgr_add_mediapath_to_volume(new, dm_mediapath); - } - - if (!vol_root) - vol_root = new; - else { - volume_t *scan = vol_root; - while (scan->next) - scan = scan->next; - scan->next = new; - } - - if (dm_src) - free(dm_src); - if (dm_src_type) - free(dm_src_type); - if (dm_tgt) - free(dm_tgt); - if (dm_param) - free(dm_param); - if (dm_tgtfs) - free(dm_tgtfs); - - return rc; - - out_free: - - if (dm_src) - free(dm_src); - if (dm_src_type) - free(dm_src_type); - if (dm_tgt) - free(dm_tgt); - if (dm_param) - free(dm_param); - if (dm_tgtfs) - free(dm_tgtfs); - - - for (i = 0; i < VOLMGR_MAX_MEDIAPATHS_PER_VOLUME; i++) { - if (new->media_paths[i]) - free(new->media_paths[i]); - } - if (new->mount_point) - free(new->mount_point); - if (new->ums_path) - free(new->ums_path); - return rc; -} - -static volume_t *volmgr_lookup_volume_by_dev(blkdev_t *dev) -{ - volume_t *scan = vol_root; - while(scan) { - if (scan->dev == dev) - return scan; - scan = scan->next; - } - return NULL; -} - -static volume_t *volmgr_lookup_volume_by_mountpoint(char *mount_point, boolean leave_locked) -{ - volume_t *v = vol_root; - - while(v) { - pthread_mutex_lock(&v->lock); - if (!strcmp(v->mount_point, mount_point)) { - if (!leave_locked) - pthread_mutex_unlock(&v->lock); - return v; - } - pthread_mutex_unlock(&v->lock); - v = v->next; - } - return NULL; -} - -static volume_t *volmgr_lookup_volume_by_mediapath(char *media_path, boolean fuzzy) -{ - volume_t *scan = vol_root; - int i; - - while (scan) { - - for (i = 0; i < VOLMGR_MAX_MEDIAPATHS_PER_VOLUME; i++) { - if (!scan->media_paths[i]) - continue; - - if (fuzzy && !strncmp(media_path, scan->media_paths[i], strlen(scan->media_paths[i]))) - return scan; - else if (!fuzzy && !strcmp(media_path, scan->media_paths[i])) - return scan; - } - - scan = scan->next; - } - return NULL; -} - -/* - * Attempt to bring a volume online - * Returns: 0 on success, errno on failure, with the following exceptions: - * - ENODATA - Unsupported filesystem type / blank - * vol->lock MUST be held! - */ -static int _volmgr_start(volume_t *vol, blkdev_t *dev) -{ - struct volmgr_fstable_entry *fs; - int rc = ENODATA; - -#if DEBUG_VOLMGR - LOG_VOL("_volmgr_start(%s, %d:%d):", vol->mount_point, - dev->major, dev->minor); -#endif - - if (vol->state == volstate_mounted) { - LOGE("Unable to start volume '%s' (already mounted)", vol->mount_point); - return -EBUSY; - } - - for (fs = fs_table; fs->name; fs++) { - if (!fs->identify_fn(dev)) - break; - } - - if (!fs->name) { - LOGE("No supported filesystems on %d:%d", dev->major, dev->minor); - volume_setstate(vol, volstate_nofs); - return -ENODATA; - } - - return volmgr_start_fs(fs, vol, dev); -} - -// vol->lock MUST be held! -static int volmgr_start_fs(struct volmgr_fstable_entry *fs, volume_t *vol, blkdev_t *dev) -{ - /* - * Spawn a thread to do the actual checking / mounting in - */ - - if (vol->worker_running) { - LOGE("Worker thread is currently running.. waiting.."); - pthread_mutex_lock(&vol->worker_sem); - LOGI("Worker thread now available"); - } - - vol->dev = dev; - - if (bootstrap) { - LOGI("Aborting start of %s (bootstrap = %d)\n", vol->mount_point, - bootstrap); - vol->state = volstate_unmounted; - return -EBUSY; - } - - vol->worker_args.start_args.fs = fs; - vol->worker_args.start_args.dev = dev; - - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - - pthread_create(&vol->worker_thread, &attr, volmgr_start_fs_thread, vol); - - return 0; -} - -static void __start_fs_thread_lock_cleanup(void *arg) -{ - volume_t *vol = (volume_t *) arg; - -#if DEBUG_VOLMGR - LOG_VOL("__start_fs_thread_lock_cleanup(%s):", vol->mount_point); -#endif - - vol->worker_running = false; - - // Wake up anyone that was waiting on this thread - pthread_mutex_unlock(&vol->worker_sem); - - // Unlock the volume - pthread_mutex_unlock(&vol->lock); -} - -static void *volmgr_start_fs_thread(void *arg) -{ - volume_t *vol = (volume_t *) arg; - - pthread_cleanup_push(__start_fs_thread_lock_cleanup, arg); - pthread_mutex_lock(&vol->lock); - - vol->worker_running = true; - vol->worker_pid = getpid(); - - struct sigaction actions; - - memset(&actions, 0, sizeof(actions)); - sigemptyset(&actions.sa_mask); - actions.sa_flags = 0; - actions.sa_handler = volmgr_start_fs_thread_sighandler; - sigaction(SIGUSR1, &actions, NULL); - - struct volmgr_fstable_entry *fs = vol->worker_args.start_args.fs; - blkdev_t *dev = vol->worker_args.start_args.dev; - int rc; - -#if DEBUG_VOLMGR - LOG_VOL("Worker thread pid %d starting %s fs %d:%d on %s", getpid(), - fs->name, dev->major, dev->minor, vol->mount_point); -#endif - - if (fs->check_fn) { -#if DEBUG_VOLMGR - LOG_VOL("Starting %s filesystem check on %d:%d", fs->name, - dev->major, dev->minor); -#endif - volume_setstate(vol, volstate_checking); - pthread_mutex_unlock(&vol->lock); - rc = fs->check_fn(dev); - pthread_mutex_lock(&vol->lock); - if (vol->state != volstate_checking) { - LOGE("filesystem check aborted"); - goto out; - } - - if (rc < 0) { - LOGE("%s filesystem check failed on %d:%d (%s)", fs->name, - dev->major, dev->minor, strerror(-rc)); - if (rc == -ENODATA) { - volume_setstate(vol, volstate_nofs); - goto out; - } - goto out_unmountable; - } -#if DEBUG_VOLMGR - LOGI("%s filesystem check of %d:%d OK", fs->name, - dev->major, dev->minor); -#endif - } - - rc = fs->mount_fn(dev, vol, safe_mode); - if (!rc) { - LOGI("Sucessfully mounted %s filesystem %d:%d on %s (safe-mode %s)", - fs->name, dev->major, dev->minor, vol->mount_point, - (safe_mode ? "on" : "off")); - vol->fs = fs; - volume_setstate(vol, volstate_mounted); - goto out; - } - - LOGE("%s filesystem mount of %d:%d failed (%d)", fs->name, dev->major, - dev->minor, rc); - - out_unmountable: - volume_setstate(vol, volstate_damaged); - out: - pthread_cleanup_pop(1); - pthread_exit(NULL); - return NULL; -} - -static void volmgr_start_fs_thread_sighandler(int signo) -{ - LOGE("Volume startup thread got signal %d", signo); -} - -static void volume_setstate(volume_t *vol, volume_state_t state) -{ - if (state == vol->state) - return; - -#if DEBUG_VOLMGR - LOG_VOL("Volume %s state change from %d -> %d", vol->mount_point, vol->state, state); -#endif - - vol->state = state; - - char *prop_val = conv_volstate_to_propstr(vol->state); - - if (prop_val) { - property_set(PROP_EXTERNAL_STORAGE_STATE, prop_val); - volume_send_state(vol); - } -} - -static int volume_send_state(volume_t *vol) -{ - char *event = conv_volstate_to_eventstr(vol->state); - - return send_msg_with_data(event, vol->mount_point); -} - -static char *conv_volstate_to_eventstr(volume_state_t state) -{ - int i; - - for (i = 0; volume_state_strings[i].event != NULL; i++) { - if (volume_state_strings[i].state == state) - break; - } - - return volume_state_strings[i].event; -} - -static char *conv_volstate_to_propstr(volume_state_t state) -{ - int i; - - for (i = 0; volume_state_strings[i].event != NULL; i++) { - if (volume_state_strings[i].state == state) - break; - } - - return volume_state_strings[i].property_val; -} - diff --git a/vold/volmgr.h b/vold/volmgr.h deleted file mode 100644 index 2c7ec50..0000000 --- a/vold/volmgr.h +++ /dev/null @@ -1,135 +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 _VOLMGR_H -#define _VOLMGR_H - -#include <pthread.h> - -#include "vold.h" -#include "blkdev.h" -#include "media.h" -#include "devmapper.h" - -#define PROP_EXTERNAL_STORAGE_STATE "EXTERNAL_STORAGE_STATE" - -// these must match the corresponding states in the MediaState enum. -// A path to the volume mount point follows the colon -typedef enum volume_state { - volstate_unknown, - - volstate_nomedia, -#define VOLD_EVT_NOMEDIA "volume_nomedia:" -#define VOLD_ES_PVAL_NOMEDIA "removed" - - volstate_unmounted, -#define VOLD_EVT_UNMOUNTED "volume_unmounted:" -#define VOLD_ES_PVAL_UNMOUNTED "unmounted" - - volstate_checking, -#define VOLD_EVT_CHECKING "volume_checking:" -#define VOLD_ES_PVAL_CHECKING "checking" - - volstate_mounted, -#define VOLD_EVT_MOUNTED "volume_mounted:" -#define VOLD_ES_PVAL_MOUNTED "mounted" - - volstate_mounted_ro, -#define VOLD_EVT_MOUNTED_RO "volume_mounted_ro:" -#define VOLD_ES_PVAL_MOUNTED_RO "mounted_ro" - - volstate_badremoval, -#define VOLD_EVT_BADREMOVAL "volume_badremoval:" -#define VOLD_ES_PVAL_BADREMOVAL "bad_removal" - - volstate_damaged, -#define VOLD_EVT_DAMAGED "volume_damaged:" -#define VOLD_ES_PVAL_DAMAGED "unmountable" - - volstate_nofs, -#define VOLD_EVT_NOFS "volume_nofs:" -#define VOLD_ES_PVAL_NOFS "nofs" - - volstate_ums, -#define VOLD_EVT_UMS "volume_ums:" -#define VOLD_ES_PVAL_UMS "shared" - - volstate_ejecting, -#define VOLD_EVT_EJECTING "volume_ejecting:" -#define VOLD_ES_PVAL_EJECTING "ejecting" - - volstate_formatting, -} volume_state_t; - -struct volume; - -struct volmgr_fstable_entry { - char *name; - int (*identify_fn) (blkdev_t *dev); - int (*check_fn) (blkdev_t *dev); - int (*mount_fn) (blkdev_t *dev, struct volume *vol, boolean safe_mode); - boolean case_sensitive_paths; -}; - -struct volmgr_start_args { - struct volmgr_fstable_entry *fs; - blkdev_t *dev; -}; - -struct volmgr_reaper_args { - void (*cb) (struct volume *, void *); - void *cb_arg; -}; - -#define VOLMGR_MAX_MEDIAPATHS_PER_VOLUME 8 - -typedef struct volume { - char *media_paths[VOLMGR_MAX_MEDIAPATHS_PER_VOLUME]; - - media_type_t media_type; - char *mount_point; - char *ums_path; - struct devmapping *dm; - - pthread_mutex_t lock; - volume_state_t state; - blkdev_t *dev; - pid_t worker_pid; - pthread_t worker_thread; - union { - struct volmgr_start_args start_args; - struct volmgr_reaper_args reaper_args; - } worker_args; - boolean worker_running; - pthread_mutex_t worker_sem; - - struct volmgr_fstable_entry *fs; - - struct volume *next; -} volume_t; - -int volmgr_consider_disk(blkdev_t *dev); -int volmgr_notify_eject(blkdev_t *dev, void (* cb) (blkdev_t *)); -int volmgr_send_states(void); -int volmgr_enable_ums(boolean enable); -int volmgr_stop_volume_by_mountpoint(char *mount_point); -int volmgr_start_volume_by_mountpoint(char *mount_point); -int volmgr_safe_mode(boolean enable); -int volmgr_format_volume(char *mount_point); -int volmgr_set_volume_key(char *mount_point, unsigned char *key); -void KillProcessesWithOpenFiles(const char* mountPoint, boolean sigkill, int *excluded, int num_excluded); -#endif diff --git a/vold/volmgr_ext3.c b/vold/volmgr_ext3.c deleted file mode 100644 index fe3b2bb..0000000 --- a/vold/volmgr_ext3.c +++ /dev/null @@ -1,184 +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 <fcntl.h> -#include <errno.h> - -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/mount.h> - -#include <linux/ext2_fs.h> -#include <linux/ext3_fs.h> - -#include "vold.h" -#include "volmgr.h" -#include "volmgr_ext3.h" -#include "logwrapper.h" - - -#define EXT_DEBUG 0 - -static char E2FSCK_PATH[] = "/system/bin/e2fsck"; - -int ext_identify(blkdev_t *dev) -{ - int rc = -1; - int fd; - struct ext3_super_block sb; - char *devpath; - -#if EXT_DEBUG - LOG_VOL("ext_identify(%d:%d):", dev-major, dev->minor); -#endif - - devpath = blkdev_get_devpath(dev); - - if ((fd = open(devpath, O_RDWR)) < 0) { - LOGE("Unable to open device '%s' (%s)", devpath, - strerror(errno)); - free(devpath); - return -errno; - } - - if (lseek(fd, 1024, SEEK_SET) < 0) { - LOGE("Unable to lseek to get superblock (%s)", strerror(errno)); - rc = -errno; - goto out; - } - - if (read(fd, &sb, sizeof(sb)) != sizeof(sb)) { - LOGE("Unable to read superblock (%s)", strerror(errno)); - rc = -errno; - goto out; - } - - if (sb.s_magic == EXT2_SUPER_MAGIC || - sb.s_magic == EXT3_SUPER_MAGIC) - rc = 0; - else - rc = -ENODATA; - - out: -#if EXT_DEBUG - LOG_VOL("ext_identify(%s): rc = %d", devpath, rc); -#endif - free(devpath); - close(fd); - return rc; -} - -int ext_check(blkdev_t *dev) -{ - char *devpath; - -#if EXT_DEBUG - LOG_VOL("ext_check(%s):", dev->dev_fspath); -#endif - - devpath = blkdev_get_devpath(dev); - - if (access(E2FSCK_PATH, X_OK)) { - LOGE("ext_check(%s): %s not found (skipping checks)", - devpath, E2FSCK_PATH); - free(devpath); - return 0; - } - - char *args[5]; - - args[0] = E2FSCK_PATH; - args[1] = "-v"; - args[2] = "-p"; - args[3] = devpath; - args[4] = NULL; - - int rc = logwrap(4, args, 1); - - if (rc == 0) { - LOG_VOL("filesystem '%s' had no errors", devpath); - } else if (rc == 1) { - LOG_VOL("filesystem '%s' had corrected errors", devpath); - rc = 0; - } else if (rc == 2) { - LOGE("VOL volume '%s' had corrected errors (system should be rebooted)", devpath); - rc = -EIO; - } else if (rc == 4) { - LOGE("VOL volume '%s' had uncorrectable errors", devpath); - rc = -EIO; - } else if (rc == 8) { - LOGE("Operational error while checking volume '%s'", devpath); - rc = -EIO; - } else { - LOGE("Unknown e2fsck exit code (%d)", rc); - rc = -EIO; - } - free(devpath); - return rc; -} - -int ext_mount(blkdev_t *dev, volume_t *vol, boolean safe_mode) -{ -#if EXT_DEBUG - LOG_VOL("ext_mount(%s, %s, %d):", dev->dev_fspath, vol->mount_point, safe_mode); -#endif - - char *fs[] = { "ext3", "ext2", NULL }; - char *devpath; - - devpath = blkdev_get_devpath(dev); - - int flags, rc = 0; - - flags = MS_NODEV | MS_NOEXEC | MS_NOSUID | MS_NOATIME | MS_NODIRATIME; - - if (safe_mode) - flags |= MS_SYNCHRONOUS; - - if (vol->state == volstate_mounted) { - LOG_VOL("Remounting %s on %s, safe mode %d", devpath, - vol->mount_point, safe_mode); - flags |= MS_REMOUNT; - } - - char **f; - for (f = fs; *f != NULL; f++) { - rc = mount(devpath, vol->mount_point, *f, flags, NULL); - if (rc && errno == EROFS) { - LOGE("ext_mount(%s, %s): Read only filesystem - retrying mount RO", - devpath, vol->mount_point); - flags |= MS_RDONLY; - rc = mount(devpath, vol->mount_point, *f, flags, NULL); - } -#if EXT_DEBUG - LOG_VOL("ext_mount(%s, %s): %s mount rc = %d", devpath, *f, - vol->mount_point, rc); -#endif - if (!rc) - break; - } - free(devpath); - - // Chmod the mount point so that its a free-for-all. - // (required for consistency with VFAT.. sigh) - if (chmod(vol->mount_point, 0777) < 0) { - LOGE("Failed to chmod %s (%s)", vol->mount_point, strerror(errno)); - return -errno; - } - - return rc; -} diff --git a/vold/volmgr_ext3.h b/vold/volmgr_ext3.h deleted file mode 100644 index bfe882a..0000000 --- a/vold/volmgr_ext3.h +++ /dev/null @@ -1,27 +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 _VOLMGR_EXT3_H -#define _VOLMGR_EXT3_H - -#include "volmgr.h" -#include "blkdev.h" - -int ext_identify(blkdev_t *blkdev); -int ext_check(blkdev_t *blkdev); -int ext_mount(blkdev_t *blkdev, volume_t *vol, boolean safe_mode); -#endif diff --git a/vold/volmgr_vfat.c b/vold/volmgr_vfat.c deleted file mode 100644 index 4c695e4..0000000 --- a/vold/volmgr_vfat.c +++ /dev/null @@ -1,165 +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 <errno.h> - -#include <sys/mount.h> -#include <cutils/properties.h> - -#include "vold.h" -#include "volmgr.h" -#include "volmgr_vfat.h" -#include "logwrapper.h" - -#define VFAT_DEBUG 0 - -static char FSCK_MSDOS_PATH[] = "/system/bin/fsck_msdos"; - -int vfat_identify(blkdev_t *dev) -{ -#if VFAT_DEBUG - LOG_VOL("vfat_identify(%d:%d):", dev->major, dev->minor); -#endif - return 0; // XXX: Implement -} - -int vfat_check(blkdev_t *dev) -{ - int rc; - boolean rw = true; - -#if VFAT_DEBUG - LOG_VOL("vfat_check(%d:%d):", dev->major, dev->minor); -#endif - - if (access(FSCK_MSDOS_PATH, X_OK)) { - LOGE("vfat_check(%d:%d): %s not found (skipping checks)", - dev->major, dev->minor, FSCK_MSDOS_PATH); - return 0; - } - - int pass = 1; - do { - char *args[5]; - args[0] = FSCK_MSDOS_PATH; - args[1] = "-p"; - args[2] = "-f"; - args[3] = blkdev_get_devpath(dev); - args[4] = NULL; - rc = logwrap(4, args, 1); - free(args[3]); - - if (rc == 0) { - LOG_VOL("Filesystem check completed OK"); - return 0; - } else if (rc == 2) { - LOG_VOL("Filesystem check failed (not a FAT filesystem)"); - return -ENODATA; - } else if (rc == 4) { - if (pass++ <= 3) { - LOG_VOL("Filesystem modified - rechecking (pass %d)", - pass); - continue; - } else { - LOG_VOL("Failing check after too many rechecks"); - return -EIO; - } - } else if (rc == -11) { - LOG_VOL("Filesystem check crashed"); - return -EIO; - } else { - LOG_VOL("Filesystem check failed (unknown exit code %d)", rc); - return -EIO; - } - } while (0); - return 0; -} - -int vfat_mount(blkdev_t *dev, volume_t *vol, boolean safe_mode) -{ - int flags, rc; - char *devpath; - - devpath = blkdev_get_devpath(dev); - -#if VFAT_DEBUG - LOG_VOL("vfat_mount(%d:%d, %s, %d):", dev->major, dev->minor, vol->mount_point, safe_mode); -#endif - - flags = MS_NODEV | MS_NOEXEC | MS_NOSUID | MS_DIRSYNC; - - if (vol->state == volstate_mounted) { - LOG_VOL("Remounting %d:%d on %s, safe mode %d", dev->major, - dev->minor, vol->mount_point, safe_mode); - flags |= MS_REMOUNT; - } - - /* - * Note: This is a temporary hack. If the sampling profiler is enabled, - * we make the SD card world-writable so any process can write snapshots. - * - * TODO: Remove this code once we have a drop box in system_server. - */ - char value[PROPERTY_VALUE_MAX]; - property_get("persist.sampling_profiler", value, ""); - if (value[0] == '1') { - LOGW("The SD card is world-writable because the" - " 'persist.sampling_profiler' system property is set to '1'."); - rc = mount(devpath, vol->mount_point, "vfat", flags, - "utf8,uid=1000,gid=1015,fmask=000,dmask=000,shortname=mixed"); - } else { - /* - * The mount masks restrict access so that: - * 1. The 'system' user cannot access the SD card at all - - * (protects system_server from grabbing file references) - * 2. Group users can RWX - * 3. Others can only RX - */ - rc = mount(devpath, vol->mount_point, "vfat", flags, - "utf8,uid=1000,gid=1015,fmask=702,dmask=702,shortname=mixed"); - } - - if (rc && errno == EROFS) { - LOGE("vfat_mount(%d:%d, %s): Read only filesystem - retrying mount RO", - dev->major, dev->minor, vol->mount_point); - flags |= MS_RDONLY; - rc = mount(devpath, vol->mount_point, "vfat", flags, - "utf8,uid=1000,gid=1015,fmask=702,dmask=702,shortname=mixed"); - } - - if (rc == 0) { - char *lost_path; - asprintf(&lost_path, "%s/LOST.DIR", vol->mount_point); - if (access(lost_path, F_OK)) { - /* - * Create a LOST.DIR in the root so we have somewhere to put - * lost cluster chains (fsck_msdos doesn't currently do this) - */ - if (mkdir(lost_path, 0755)) { - LOGE("Unable to create LOST.DIR (%s)", strerror(errno)); - } - } - free(lost_path); - } - -#if VFAT_DEBUG - LOG_VOL("vfat_mount(%s, %d:%d): mount rc = %d", dev->major,k dev->minor, - vol->mount_point, rc); -#endif - free (devpath); - return rc; -} |
