Merge "Fix ADB daemon file descriptor leak"
diff --git a/CleanSpec.mk b/CleanSpec.mk
new file mode 100644
index 0000000..b84e1b65
--- /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 @@
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 := \
diff --git a/adb/adb.c b/adb/adb.c
index b1a0e62..95dc001 100644
--- a/adb/adb.c
+++ b/adb/adb.c
@@ -901,9 +901,10 @@
** 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 @@
" 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 @@
" 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 @@
{
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 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/adb/sockets.c b/adb/sockets.c
index 9f1b598..43925e4 100644
--- a/adb/sockets.c
+++ b/adb/sockets.c
@@ -65,8 +65,11 @@
asocket *result = NULL;
adb_mutex_lock(&socket_list_lock);
- for(s = local_socket_list.next; s != &local_socket_list && !result; s = s->next) {
- if(s->id == id) result = s;
+ for (s = local_socket_list.next; s != &local_socket_list; s = s->next) {
+ if (s->id == id) {
+ result = s;
+ break;
+ }
}
adb_mutex_unlock(&socket_list_lock);
@@ -366,7 +369,7 @@
asocket *create_local_socket(int fd)
{
asocket *s = calloc(1, sizeof(asocket));
- if(s == 0) fatal("cannot allocate socket");
+ if (s == NULL) fatal("cannot allocate socket");
install_local_socket(s);
s->fd = fd;
s->enqueue = local_socket_enqueue;
@@ -482,7 +485,7 @@
asocket *s = calloc(1, sizeof(aremotesocket));
adisconnect* dis = &((aremotesocket*)s)->disconnect;
- if(s == 0) fatal("cannot allocate socket");
+ if (s == NULL) fatal("cannot allocate socket");
s->id = id;
s->enqueue = remote_socket_enqueue;
s->ready = remote_socket_ready;
@@ -761,8 +764,7 @@
{
D("Creating smart socket \n");
asocket *s = calloc(1, sizeof(asocket));
- if(s == 0) fatal("cannot allocate socket");
- s->id = 0;
+ if (s == NULL) fatal("cannot allocate socket");
s->enqueue = smart_socket_enqueue;
s->ready = smart_socket_ready;
s->close = smart_socket_close;
diff --git a/adb/usb_vendors.c b/adb/usb_vendors.c
index 6d85fb1..db8b018 100644
--- a/adb/usb_vendors.c
+++ b/adb/usb_vendors.c
@@ -69,6 +69,8 @@
#define VENDOR_ID_PANTECH 0x10A9
// Qualcomm's USB Vendor ID
#define VENDOR_ID_QUALCOMM 0x05c6
+// On-The-Go-Video's USB Vendor ID
+#define VENDOR_ID_OTGV 0x2257
/** built-in vendor list */
@@ -90,6 +92,7 @@
VENDOR_ID_KYOCERA,
VENDOR_ID_PANTECH,
VENDOR_ID_QUALCOMM,
+ VENDOR_ID_OTGV,
};
#define BUILT_IN_VENDOR_COUNT (sizeof(builtInVendorIds)/sizeof(builtInVendorIds[0]))
@@ -151,7 +154,7 @@
/* builds the path to the adb vendor id file. returns 0 if success */
int build_path(char* buff, size_t len, const char* format, const char* home)
{
- if (snprintf(buff, len, format, home, ANDROID_PATH, ANDROID_ADB_INI) >= len) {
+ if (snprintf(buff, len, format, home, ANDROID_PATH, ANDROID_ADB_INI) >= (signed)len) {
return 1;
}
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_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 @@
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_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 @@
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 @@
_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 @@
_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 @@
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 @@
(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 @@
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 @@
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 @@
const char *msg;
int (*func)(Action *a, int status, char *resp);
+
+ double start;
};
static Action *action_list = 0;
@@ -76,7 +86,9 @@
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 @@
action_last = a;
a->op = op;
a->func = cb_default;
+
+ a->start = -1;
+
return a;
}
@@ -166,7 +181,9 @@
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 @@
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 @@
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 @@
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 @@
{
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 @@
" -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 @@
}
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 wants_reboot_bootloader = 0;
void *data;
unsigned sz;
+ unsigned page_size = 2048;
skip(1);
if (argc == 0) {
@@ -556,6 +562,8 @@
return 0;
}
+ serial = getenv("ANDROID_SERIAL");
+
while (argc > 0) {
if(!strcmp(*argv, "-w")) {
wants_wipe = 1;
@@ -564,6 +572,11 @@
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 @@
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 @@
} 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 @@
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 @@
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 @@
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 @@
DIR *busdir, *devdir;
struct dirent *de;
int fd;
+ int writable;
busdir = opendir(base);
if(busdir == 0) return 0;
@@ -219,13 +222,20 @@
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 @@
{
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 @@
// 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 @@
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 @@
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..c7434ca 100644
--- a/include/arch/target_linux-x86/AndroidConfig.h
+++ b/include/arch/target_linux-x86/AndroidConfig.h
@@ -220,7 +220,7 @@
/*
* Define if we have Linux's dbus
*/
-#define HAVE_DBUS 1
+/* #define HAVE_DBUS 1 */
/*
* Define if tm struct has tm_gmtoff field
@@ -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/include/cutils/iosched_policy.h b/include/cutils/iosched_policy.h
new file mode 100644
index 0000000..07c5d1f
--- /dev/null
+++ b/include/cutils/iosched_policy.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __CUTILS_IOSCHED_POLICY_H
+#define __CUTILS_IOSCHED_POLICY_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);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CUTILS_IOSCHED_POLICY_H */
diff --git a/include/cutils/log.h b/include/cutils/log.h
index ec3cac8..f602017 100644
--- a/include/cutils/log.h
+++ b/include/cutils/log.h
@@ -196,6 +196,91 @@
#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
+
+
+
// ---------------------------------------------------------------------
/*
@@ -206,11 +291,11 @@
*/
#define LOG_ALWAYS_FATAL_IF(cond, ...) \
( (CONDITION(cond)) \
- ? ((void)android_printAssert(#cond, LOG_TAG, __VA_ARGS__)) \
+ ? ((void)android_printAssert(#cond, LOG_TAG, ## __VA_ARGS__)) \
: (void)0 )
#define LOG_ALWAYS_FATAL(...) \
- ( ((void)android_printAssert(NULL, LOG_TAG, __VA_ARGS__)) )
+ ( ((void)android_printAssert(NULL, LOG_TAG, ## __VA_ARGS__)) )
/*
* Versions of LOG_ALWAYS_FATAL_IF and LOG_ALWAYS_FATAL that
@@ -223,7 +308,7 @@
#else
-#define LOG_FATAL_IF(cond, ...) LOG_ALWAYS_FATAL_IF(cond, __VA_ARGS__)
+#define LOG_FATAL_IF(cond, ...) LOG_ALWAYS_FATAL_IF(cond, ## __VA_ARGS__)
#define LOG_FATAL(...) LOG_ALWAYS_FATAL(__VA_ARGS__)
#endif
@@ -232,7 +317,7 @@
* Assertion that generates a log message when the assertion fails.
* Stripped out of release builds. Uses the current LOG_TAG.
*/
-#define LOG_ASSERT(cond, ...) LOG_FATAL_IF(!(cond), __VA_ARGS__)
+#define LOG_ASSERT(cond, ...) LOG_FATAL_IF(!(cond), ## __VA_ARGS__)
//#define LOG_ASSERT(cond) LOG_FATAL_IF(!(cond), "Assertion failed: " #cond)
// ---------------------------------------------------------------------
@@ -318,8 +403,24 @@
#define android_vprintLog(prio, cond, tag, fmt...) \
__android_log_vprint(prio, tag, fmt)
+/* XXX Macros to work around syntax errors in places where format string
+ * arg is not passed to LOG_ASSERT, LOG_ALWAYS_FATAL or LOG_ALWAYS_FATAL_IF
+ * (happens only in debug builds).
+ */
+
+/* Returns 2nd arg. Used to substitute default value if caller's vararg list
+ * is empty.
+ */
+#define __android_second(dummy, second, ...) second
+
+/* If passed multiple args, returns ',' followed by all but 1st arg, otherwise
+ * returns nothing.
+ */
+#define __android_rest(first, ...) , ## __VA_ARGS__
+
#define android_printAssert(cond, tag, fmt...) \
- __android_log_assert(cond, tag, fmt)
+ __android_log_assert(cond, tag, \
+ __android_second(0, ## fmt, NULL) __android_rest(fmt))
#define android_writeLog(prio, tag, text) \
__android_log_write(prio, tag, text)
@@ -328,7 +429,7 @@
__android_log_bwrite(tag, payload, len)
#define android_btWriteLog(tag, type, payload, len) \
__android_log_btwrite(tag, type, payload, len)
-
+
// TODO: remove these prototypes and their users
#define android_testLog(prio, tag) (1)
#define android_writevLog(vec,num) do{}while(0)
@@ -338,6 +439,21 @@
#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 @@
#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 @@
* 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_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
old mode 100755
new mode 100644
similarity index 63%
rename from include/cutils/adb_networking.h
rename to include/cutils/open_memstream.h
index 409d577..b7998be
--- 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/netutils/dhcp.h b/include/netutils/dhcp.h
new file mode 100644
index 0000000..96798c5
--- /dev/null
+++ b/include/netutils/dhcp.h
@@ -0,0 +1,40 @@
+/*
+ * 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 _NETUTILS_DHCP_H_
+#define _NETUTILS_DHCP_H_
+
+#include <sys/cdefs.h>
+#include <arpa/inet.h>
+
+__BEGIN_DECLS
+
+extern int do_dhcp(char *iname);
+extern int dhcp_do_request(const char *ifname,
+ in_addr_t *ipaddr,
+ in_addr_t *gateway,
+ in_addr_t *mask,
+ in_addr_t *dns1,
+ in_addr_t *dns2,
+ in_addr_t *server,
+ uint32_t *lease);
+extern int dhcp_stop(const char *ifname);
+extern int dhcp_release_lease(const char *ifname);
+extern char *dhcp_get_errmsg();
+
+__END_DECLS
+
+#endif /* _NETUTILS_DHCP_H_ */
diff --git a/include/netutils/ifc.h b/include/netutils/ifc.h
new file mode 100644
index 0000000..2e502ab
--- /dev/null
+++ b/include/netutils/ifc.h
@@ -0,0 +1,59 @@
+/*
+ * 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 _NETUTILS_IFC_H_
+#define _NETUTILS_IFC_H_
+
+#include <sys/cdefs.h>
+#include <arpa/inet.h>
+
+__BEGIN_DECLS
+
+extern int ifc_init(void);
+extern void ifc_close(void);
+
+extern int ifc_get_ifindex(const char *name, int *if_indexp);
+extern int ifc_get_hwaddr(const char *name, void *ptr);
+
+extern int ifc_up(const char *name);
+extern int ifc_down(const char *name);
+
+extern int ifc_enable(const char *ifname);
+extern int ifc_disable(const char *ifname);
+
+extern int ifc_reset_connections(const char *ifname);
+
+extern int ifc_set_addr(const char *name, in_addr_t addr);
+extern int ifc_set_mask(const char *name, in_addr_t mask);
+extern int ifc_set_hwaddr(const char *name, const void *ptr);
+
+extern int ifc_add_host_route(const char *name, in_addr_t addr);
+extern int ifc_remove_host_routes(const char *name);
+extern int ifc_get_default_route(const char *ifname);
+extern int ifc_set_default_route(const char *ifname, in_addr_t gateway);
+extern int ifc_create_default_route(const char *name, in_addr_t addr);
+extern int ifc_remove_default_route(const char *ifname);
+
+extern int ifc_get_info(const char *name, in_addr_t *addr, in_addr_t *mask,
+ in_addr_t *flags);
+
+extern int ifc_configure(const char *ifname, in_addr_t address,
+ in_addr_t netmask, in_addr_t gateway,
+ in_addr_t dns1, in_addr_t dns2);
+
+__END_DECLS
+
+#endif /* _NETUTILS_IFC_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 @@
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 @@
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 @@
{ 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 @@
/* 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 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 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 @@
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 @@
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..0667593 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 @@
}
}
+ 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();
@@ -649,8 +657,9 @@
if (x) {
x += 2;
n = 0;
- while (*x && !isspace(*x)) {
- hardware[n++] = tolower(*x);
+ while (*x && *x != '\n') {
+ if (!isspace(*x))
+ hardware[n++] = tolower(*x);
x++;
if (n == 31) break;
}
@@ -767,21 +776,31 @@
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 +872,7 @@
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 @@
#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 @@
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 @@
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 @@
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 @@
return;
}
+ svc->ioprio_class = IoSchedClass_NONE;
+
kw = lookup_keyword(args[0]);
switch (kw) {
case K_capability:
@@ -636,6 +641,28 @@
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 @@
{ "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 @@
include $(BUILD_SHARED_LIBRARY)
-# Shared library for host
+# Static library for host
# ========================================================
include $(CLEAR_VARS)
@@ -23,7 +23,7 @@
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 @@
* Pointer indirection ('*') is supported.
- * Square brackets can be used for pointer arithmetic.
+ * Square brackets are supported.
* '=' and <op>= are supported.
@@ -37,11 +37,14 @@
+ 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 @@
- 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 @@
~Vector() {
if (mpBase) {
- for(size_t i = 0; i < mUsed; i++) {
- mpBase[mUsed].~E();
- }
+ clear();
free(mpBase);
}
}
@@ -110,10 +108,20 @@
* 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 (! varArgs && pArgList) {
+ error("Expected more argument(s). Saw %d", argCount);
}
- if (accept(',')) {
- // fine
- } else if ( tok != ')') {
- error("Expected ',' or ')'");
- }
- argCount += 1;
+ pGen->endFunctionCallArguments(pDecl, a, l);
+ skip(')');
+ pGen->callIndirect(l, pDecl);
+ pGen->adjustStackAfterCall(pDecl, l, true);
+ } else {
+ error("Expected a function value to left of '('.");
}
- 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 {
break;
}
@@ -4957,11 +5013,11 @@
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 @@
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 @@
}
}
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 @@
}
next();
while (tok != '}' && tok != EOF)
- block(l, false);
+ block(breakLabel, continueAddress, false);
skip('}');
if (! outermostFunctionBlock) {
mLocals.popLevel();
@@ -5035,7 +5091,17 @@
}
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 @@
}
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 @@
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;
+ }
}
- next();
+ }
+
+ 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");
+ }
+ }
+ }
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 @@
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 @@
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 @@
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 @@
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 @@
/* 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 @@
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 @@
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 @@
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 @@
next();
}
skip(';');
- pBaseType = acceptPrimitiveType();
+ pBaseType = acceptPrimitiveType(true);
}
}
@@ -5622,8 +5779,12 @@
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 @@
void globalDeclarations() {
mpCurrentSymbolStack = &mGlobals;
while (tok != EOF) {
- Type* pBaseType = expectPrimitiveType();
+ Type* pBaseType = expectPrimitiveType(true);
if (!pBaseType) {
break;
}
@@ -5687,7 +5848,6 @@
skip(';');
continue;
}
-
if (! isDefined(pDecl->id)) {
addGlobalSymbol(pDecl);
}
@@ -5698,19 +5858,23 @@
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 @@
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 @@
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_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 @@
disassem.cpp
LOCAL_SHARED_LIBRARIES := \
- libacc
+ libacc \
+ libdl
LOCAL_CFLAGS := -O0 -g
@@ -41,8 +46,11 @@
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 @@
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 @@
gUseArm = True
gUseX86 = True
gRunOTCCOutput = True
+gCompileOTCCANSI = True
def parseArgv():
@@ -59,7 +60,12 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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,10 +134,73 @@
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;
+ unsigned int pagesize;
+ mstate m;
+
+ init_mparams();
+ pagesize = PAGESIZE;
+ 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);
+
+ /* Make the first page read/write. dlmalloc needs to use that page.
+ */
+ if (mprotect(base, starting_capacity, PROT_READ | PROT_WRITE) < 0) {
+ goto error;
+ }
+
+ /* Create the mspace, pointing to the memory given.
+ */
+ 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 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) {
+ /* mprotect() requires page-aligned arguments, but it's possible
+ * for cs->brk not to be page-aligned at this point.
+ */
+ char *prot_brk = (char *)ALIGN_UP(cs->brk, pagesize);
+ 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;
+ cs->magic = CONTIG_STATE_MAGIC;
+
+ return (mspace)m;
+
+error:
+ 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;
@@ -173,47 +236,12 @@
*/
assert(((uintptr_t)base & (pagesize-1)) == 0);
- /* Reserve some space for the information that our MORECORE needs.
- */
- cs = base;
-
- /* Create the mspace, pointing to the memory we just reserved.
- */
- m = create_mspace_with_base(base + sizeof(*cs), starting_capacity, locked);
- if (m == (mspace)0)
- goto error;
-
- /* Make sure that m is in the same page as cs.
- */
- assert(((uintptr_t)m & (uintptr_t)~(pagesize-1)) == (uintptr_t)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) {
- /* mprotect() requires page-aligned arguments, but it's possible
- * 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)
- goto error;
+ m = create_contiguous_mspace_with_base(starting_capacity, max_capacity,
+ locked, base);
+ if (m == 0) {
+ munmap(base, max_capacity);
}
-
- cs->m = m;
- cs->magic = CONTIG_STATE_MAGIC;
-
- return (mspace)m;
-
-error:
- munmap(base, max_capacity);
- return (mspace)0;
+ return m;
}
mspace create_contiguous_mspace(size_t 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 @@
{
#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 @@
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 set_sched_policy(int tid, SchedPolicy policy)
{
- initialize();
+ pthread_once(&the_once, __initialize);
#if POLICY_DEBUG
char statfile[64];
@@ -195,22 +247,16 @@
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 @@
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..c887955
--- /dev/null
+++ b/libdiskconfig/Android.mk
@@ -0,0 +1,27 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+ifneq ($(TARGET_SIMULATOR),true)
+
+commonSources := \
+ diskconfig.c \
+ diskutils.c \
+ write_lst.c \
+ config_mbr.c
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := $(commonSources)
+LOCAL_MODULE := libdiskconfig
+LOCAL_SYSTEM_SHARED_LIBRARIES := libcutils liblog libc
+include $(BUILD_SHARED_LIBRARY)
+
+ifeq ($(HOST_OS),linux)
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := $(commonSources)
+LOCAL_MODULE := libdiskconfig_host
+LOCAL_SYSTEM_SHARED_LIBRARIES := libcutils
+LOCAL_CFLAGS := -O2 -g -W -Wall -Werror -D_LARGEFILE64_SOURCE
+include $(BUILD_HOST_STATIC_LIBRARY)
+endif # HOST_OS == linux
+
+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/libdiskconfig/dump_diskconfig.c b/libdiskconfig/dump_diskconfig.c
new file mode 100644
index 0000000..fff19f5
--- /dev/null
+++ b/libdiskconfig/dump_diskconfig.c
@@ -0,0 +1,42 @@
+/* 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
+ *
+ * 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 "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;
+
+ dump_disk_config(dinfo);
+
+ return 0;
+}
+
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..a0a753b 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
@@ -63,7 +56,7 @@
* the simulator rather than a desktop tool and want to use the device.
*/
static enum {
- kLogUninitialized, kLogNotAvailable, kLogAvailable
+ kLogUninitialized, kLogNotAvailable, kLogAvailable
} g_log_status = kLogUninitialized;
int __android_log_dev_available(void)
{
@@ -110,6 +103,7 @@
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 @@
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,9 +159,37 @@
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];
+ char buf[LOG_BUF_SIZE];
vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
@@ -173,7 +199,7 @@
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,16 +208,39 @@
return __android_log_write(prio, tag, buf);
}
-void __android_log_assert(const char *cond, const char *tag,
- const char *fmt, ...)
+int __android_log_buf_print(int bufID, 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);
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, ...)
+{
+ char buf[LOG_BUF_SIZE];
+
+ if (fmt) {
+ va_list ap;
+ va_start(ap, fmt);
+ vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
+ va_end(ap);
+ } else {
+ /* Msg not provided, log condition. N.B. Do not use cond directly as
+ * format string as it could contain spurious '%' syntax (e.g.
+ * "%d" in "blocks%devs == 0").
+ */
+ if (cond)
+ snprintf(buf, LOG_BUF_SIZE, "Assertion failed: %s", cond);
+ else
+ strcpy(buf, "Unspecified assertion failed");
+ }
+
__android_log_write(ANDROID_LOG_FATAL, tag, buf);
__builtin_trap(); /* trap so we have a chance to debug the situation */
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 @@
* Returns count bytes written
*/
-int android_log_filterAndPrintLogLine(
+int android_log_printLogLine(
AndroidLogFormat *p_format,
int fd,
const AndroidLogEntry *entry)
@@ -860,11 +860,6 @@
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 @@
// 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 @@
// 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 bad2e2f..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 */
@@ -114,6 +115,14 @@
}
}
+static const char *ipaddr_to_string(in_addr_t addr)
+{
+ struct in_addr in_addr;
+
+ in_addr.s_addr = addr;
+ return inet_ntoa(in_addr);
+}
+
/*
* Start the dhcp client daemon, and wait for it to finish
* configuring the interface.
@@ -129,6 +138,7 @@
{
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";
@@ -139,7 +149,13 @@
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;
@@ -157,7 +173,13 @@
return -1;
}
if (strcmp(prop_value, "ok") == 0) {
+ char dns_prop_name[PROPERTY_KEY_MAX];
fill_ip_info(interface, ipaddr, gateway, mask, dns1, dns2, server, lease);
+ /* copy the dhcp.XXX.dns properties to net.XXX.dns */
+ snprintf(dns_prop_name, sizeof(dns_prop_name), "net.%s.dns1", interface);
+ property_set(dns_prop_name, *dns1 ? ipaddr_to_string(*dns1) : "");
+ snprintf(dns_prop_name, sizeof(dns_prop_name), "net.%s.dns2", interface);
+ property_set(dns_prop_name, *dns2 ? ipaddr_to_string(*dns2) : "");
return 0;
} else {
snprintf(errmsg, sizeof(errmsg), "DHCP result was %s", prop_value);
diff --git a/libnetutils/dhcpclient.c b/libnetutils/dhcpclient.c
index 45e392a..b247016 100644
--- a/libnetutils/dhcpclient.c
+++ b/libnetutils/dhcpclient.c
@@ -36,8 +36,8 @@
#include <dirent.h>
+#include <netutils/ifc.h>
#include "dhcpmsg.h"
-#include "ifc_utils.h"
#include "packet.h"
#define VERBOSE 2
@@ -85,16 +85,12 @@
// exit(1);
}
-const char *ipaddr(uint32_t addr)
+const char *ipaddr(in_addr_t addr)
{
- static char buf[32];
+ struct in_addr in_addr;
- sprintf(buf,"%d.%d.%d.%d",
- addr & 255,
- ((addr >> 8) & 255),
- ((addr >> 16) & 255),
- (addr >> 24));
- return buf;
+ in_addr.s_addr = addr;
+ return inet_ntoa(in_addr);
}
typedef struct dhcp_info dhcp_info;
@@ -128,31 +124,11 @@
*lease = last_good_info.lease;
}
-static int ifc_configure(const char *ifname, dhcp_info *info)
+static int dhcp_configure(const char *ifname, dhcp_info *info)
{
- char dns_prop_name[PROPERTY_KEY_MAX];
-
- if (ifc_set_addr(ifname, info->ipaddr)) {
- printerr("failed to set ipaddr %s: %s\n", ipaddr(info->ipaddr), strerror(errno));
- return -1;
- }
- if (ifc_set_mask(ifname, info->netmask)) {
- printerr("failed to set netmask %s: %s\n", ipaddr(info->netmask), strerror(errno));
- return -1;
- }
- if (ifc_create_default_route(ifname, info->gateway)) {
- printerr("failed to set default route %s: %s\n", ipaddr(info->gateway), strerror(errno));
- return -1;
- }
-
- snprintf(dns_prop_name, sizeof(dns_prop_name), "net.%s.dns1", ifname);
- property_set(dns_prop_name, info->dns1 ? ipaddr(info->dns1) : "");
- snprintf(dns_prop_name, sizeof(dns_prop_name), "net.%s.dns2", ifname);
- property_set(dns_prop_name, info->dns2 ? ipaddr(info->dns2) : "");
-
last_good_info = *info;
-
- return 0;
+ return ifc_configure(ifname, info->ipaddr, info->netmask, info->gateway,
+ info->dns1, info->dns2);
}
static const char *dhcp_type_to_name(uint32_t type)
@@ -449,7 +425,7 @@
printerr("timed out\n");
if ( info.type == DHCPOFFER ) {
printerr("no acknowledgement from DHCP server\nconfiguring %s with offered parameters\n", ifname);
- return ifc_configure(ifname, &info);
+ return dhcp_configure(ifname, &info);
}
errno = ETIME;
close(s);
@@ -530,7 +506,7 @@
if (info.type == DHCPACK) {
printerr("configuring %s\n", ifname);
close(s);
- return ifc_configure(ifname, &info);
+ return dhcp_configure(ifname, &info);
} else if (info.type == DHCPNAK) {
printerr("configuration request denied\n");
close(s);
diff --git a/libnetutils/ifc_utils.c b/libnetutils/ifc_utils.c
index bde336f..296d617 100644
--- a/libnetutils/ifc_utils.c
+++ b/libnetutils/ifc_utils.c
@@ -27,6 +27,8 @@
#include <arpa/inet.h>
#include <linux/if.h>
+#include <linux/if_ether.h>
+#include <linux/if_arp.h>
#include <linux/sockios.h>
#include <linux/route.h>
#include <linux/wireless.h>
@@ -45,7 +47,7 @@
static int ifc_ctl_sock = -1;
void printerr(char *fmt, ...);
-static const char *ipaddr_to_string(uint32_t addr)
+static const char *ipaddr_to_string(in_addr_t addr)
{
struct in_addr in_addr;
@@ -88,7 +90,7 @@
r = ioctl(ifc_ctl_sock, SIOCGIFHWADDR, &ifr);
if(r < 0) return -1;
- memcpy(ptr, &ifr.ifr_hwaddr.sa_data, 6);
+ memcpy(ptr, &ifr.ifr_hwaddr.sa_data, ETH_ALEN);
return 0;
}
@@ -143,6 +145,17 @@
return ioctl(ifc_ctl_sock, SIOCSIFADDR, &ifr);
}
+int ifc_set_hwaddr(const char *name, const void *ptr)
+{
+ int r;
+ struct ifreq ifr;
+ ifc_init_ifr(name, &ifr);
+
+ ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
+ memcpy(&ifr.ifr_hwaddr.sa_data, ptr, ETH_ALEN);
+ return ioctl(ifc_ctl_sock, SIOCSIFHWADDR, &ifr);
+}
+
int ifc_set_mask(const char *name, in_addr_t mask)
{
struct ifreq ifr;
@@ -429,9 +442,9 @@
ifc_close();
- snprintf(dns_prop_name, sizeof(dns_prop_name), "dhcp.%s.dns1", ifname);
+ snprintf(dns_prop_name, sizeof(dns_prop_name), "net.%s.dns1", ifname);
property_set(dns_prop_name, dns1 ? ipaddr_to_string(dns1) : "");
- snprintf(dns_prop_name, sizeof(dns_prop_name), "dhcp.%s.dns2", ifname);
+ snprintf(dns_prop_name, sizeof(dns_prop_name), "net.%s.dns2", ifname);
property_set(dns_prop_name, dns2 ? ipaddr_to_string(dns2) : "");
return 0;
diff --git a/libnetutils/ifc_utils.h b/libnetutils/ifc_utils.h
deleted file mode 100644
index 49b8747..0000000
--- a/libnetutils/ifc_utils.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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 _IFC_UTILS_H_
-#define _IFC_UTILS_H_
-
-int ifc_init(void);
-
-int ifc_get_ifindex(const char *name, int *if_indexp);
-int ifc_get_hwaddr(const char *name, void *ptr);
-
-int ifc_up(const char *name);
-int ifc_down(const char *name);
-
-int ifc_set_addr(const char *name, unsigned addr);
-int ifc_set_mask(const char *name, unsigned mask);
-
-int ifc_create_default_route(const char *name, unsigned addr);
-
-int ifc_get_info(const char *name, unsigned *addr, unsigned *mask, unsigned *flags);
-
-#endif
diff --git a/libpixelflinger/codeflinger/ARMAssembler.cpp b/libpixelflinger/codeflinger/ARMAssembler.cpp
index d3720c3..fa9f1ad 100644
--- a/libpixelflinger/codeflinger/ARMAssembler.cpp
+++ b/libpixelflinger/codeflinger/ARMAssembler.cpp
@@ -433,6 +433,16 @@
{
*mPC++ = (cc<<28) | 0x6CF0070 | (Rd<<12) | ((rotate >> 3) << 10) | Rm;
}
+#if 0
+#pragma mark -
+#pragma mark Bit manipulation (ARMv7+ only)...
+#endif
+
+// Bit manipulation (ARMv7+ only)...
+void ARMAssembler::UBFX(int cc, int Rd, int Rn, int lsb, int width)
+{
+ *mPC++ = (cc<<28) | 0x7E00000 | ((width-1)<<16) | (Rd<<12) | (lsb<<7) | 0x50 | Rn;
+}
}; // namespace android
diff --git a/libpixelflinger/codeflinger/ARMAssembler.h b/libpixelflinger/codeflinger/ARMAssembler.h
index a667cb5..e7f038a 100644
--- a/libpixelflinger/codeflinger/ARMAssembler.h
+++ b/libpixelflinger/codeflinger/ARMAssembler.h
@@ -124,6 +124,7 @@
virtual void SMLAW(int cc, int y,
int Rd, int Rm, int Rs, int Rn);
virtual void UXTB16(int cc, int Rd, int Rm, int rotate);
+ virtual void UBFX(int cc, int Rd, int Rn, int lsb, int width);
private:
ARMAssembler(const ARMAssembler& rhs);
diff --git a/libpixelflinger/codeflinger/ARMAssemblerInterface.h b/libpixelflinger/codeflinger/ARMAssemblerInterface.h
index ff6af2a..796342a 100644
--- a/libpixelflinger/codeflinger/ARMAssemblerInterface.h
+++ b/libpixelflinger/codeflinger/ARMAssemblerInterface.h
@@ -206,6 +206,9 @@
// byte/half word extract...
virtual void UXTB16(int cc, int Rd, int Rm, int rotate) = 0;
+ // bit manipulation...
+ virtual void UBFX(int cc, int Rd, int Rn, int lsb, int width) = 0;
+
// -----------------------------------------------------------------------
// convenience...
// -----------------------------------------------------------------------
diff --git a/libpixelflinger/codeflinger/ARMAssemblerProxy.cpp b/libpixelflinger/codeflinger/ARMAssemblerProxy.cpp
index 7c422db..c57d7da 100644
--- a/libpixelflinger/codeflinger/ARMAssemblerProxy.cpp
+++ b/libpixelflinger/codeflinger/ARMAssemblerProxy.cpp
@@ -199,5 +199,9 @@
mTarget->UXTB16(cc, Rd, Rm, rotate);
}
+void ARMAssemblerProxy::UBFX(int cc, int Rd, int Rn, int lsb, int width) {
+ mTarget->UBFX(cc, Rd, Rn, lsb, width);
+}
+
}; // namespace android
diff --git a/libpixelflinger/codeflinger/ARMAssemblerProxy.h b/libpixelflinger/codeflinger/ARMAssemblerProxy.h
index 9134cce..8c7f270 100644
--- a/libpixelflinger/codeflinger/ARMAssemblerProxy.h
+++ b/libpixelflinger/codeflinger/ARMAssemblerProxy.h
@@ -115,6 +115,7 @@
int Rd, int Rm, int Rs, int Rn);
virtual void UXTB16(int cc, int Rd, int Rm, int rotate);
+ virtual void UBFX(int cc, int Rd, int Rn, int lsb, int width);
private:
ARMAssemblerInterface* mTarget;
diff --git a/libpixelflinger/codeflinger/disassem.c b/libpixelflinger/codeflinger/disassem.c
index c17f3ec..aeb8034 100644
--- a/libpixelflinger/codeflinger/disassem.c
+++ b/libpixelflinger/codeflinger/disassem.c
@@ -81,6 +81,8 @@
* g - 2nd fp operand (register) (bits 16-18)
* h - 3rd fp operand (register/immediate) (bits 0-4)
* j - xtb rotate literal (bits 10-11)
+ * i - bfx lsb literal (bits 7-11)
+ * w - bfx width literal (bits 16-20)
* b - branch address
* t - thumb branch address (bits 24, 0-23)
* k - breakpoint comment (bits 0-3, 8-19)
@@ -124,6 +126,7 @@
{ 0x0fe000f0, 0x00a00090, "umlal", "Sdnms" },
{ 0x0fe000f0, 0x00e00090, "smlal", "Sdnms" },
{ 0x0fff03f0, 0x06cf0070, "uxtb16", "dmj" },
+ { 0x0fe00070, 0x07e00050, "ubfx", "dmiw" },
{ 0x0d700000, 0x04200000, "strt", "daW" },
{ 0x0d700000, 0x04300000, "ldrt", "daW" },
{ 0x0d700000, 0x04600000, "strbt", "daW" },
@@ -412,6 +415,14 @@
case 'j':
di->di_printf("ror #%d", ((insn >> 10) & 3) << 3);
break;
+ /* i - bfx lsb literal (bits 7-11) */
+ case 'i':
+ di->di_printf("#%d", (insn >> 7) & 31);
+ break;
+ /* w - bfx width literal (bits 16-20) */
+ case 'w':
+ di->di_printf("#%d", 1 + ((insn >> 16) & 31));
+ break;
/* b - branch address */
case 'b':
branch = ((insn << 2) & 0x03ffffff);
diff --git a/libpixelflinger/codeflinger/load_store.cpp b/libpixelflinger/codeflinger/load_store.cpp
index 93c5825..ed20a00 100644
--- a/libpixelflinger/codeflinger/load_store.cpp
+++ b/libpixelflinger/codeflinger/load_store.cpp
@@ -18,9 +18,12 @@
#include <assert.h>
#include <stdio.h>
#include <cutils/log.h>
-
#include "codeflinger/GGLAssembler.h"
+#ifdef __ARM_ARCH__
+#include <machine/cpu-features.h>
+#endif
+
namespace android {
// ----------------------------------------------------------------------------
@@ -110,6 +113,20 @@
assert(maskLen<=8);
assert(h);
+#if __ARM_ARCH__ >= 7
+ const int mask = (1<<maskLen)-1;
+ if ((h == bits) && !l && (s != d.reg)) {
+ MOV(AL, 0, d.reg, s); // component = packed;
+ } else if ((h == bits) && l) {
+ MOV(AL, 0, d.reg, reg_imm(s, LSR, l)); // component = packed >> l;
+ } else if (!l && isValidImmediate(mask)) {
+ AND(AL, 0, d.reg, s, imm(mask)); // component = packed & mask;
+ } else if (!l && isValidImmediate(~mask)) {
+ BIC(AL, 0, d.reg, s, imm(~mask)); // component = packed & mask;
+ } else {
+ UBFX(AL, d.reg, s, l, maskLen); // component = (packed & mask) >> l;
+ }
+#else
if (h != bits) {
const int mask = ((1<<maskLen)-1) << l;
if (isValidImmediate(mask)) {
@@ -132,6 +149,7 @@
if (s != d.reg) {
MOV(AL, 0, d.reg, s);
}
+#endif
d.s = maskLen;
}
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 @@
{ 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 @@
{ 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 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
}
}
+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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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_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 @@
} 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 @@
} 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 @@
return;
}
-static void readLogLines(int logfd)
+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;
+ }
+ }
+}
+
+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);
+ }
+ }
+ }
+}
+
+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) {
- unsigned char buf[LOGGER_ENTRY_MAX_LEN + 1] __attribute__((aligned(4)));
- struct logger_entry *entry = (struct logger_entry *) buf;
- int ret;
+ 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);
- 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);
+ 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);
+ }
+
+ entry->entry.msg[entry->entry.len] = '\0';
+
+ dev->enqueue(entry);
+ ++queued_lines;
+ }
+ }
+
+ 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;
+ }
+ }
}
- else if (!ret) {
- fprintf(stderr, "read: Unexpected EOF!\n");
- exit(EXIT_FAILURE);
- }
-
- /* NOTE: driver guarantees we read exactly one full entry */
-
- entry->msg[entry->len] = '\0';
-
- if (g_printBinary) {
- printBinary(entry);
- } else {
- (void) processBuffer(entry);
- }
+next:
+ ;
}
}
@@ -228,6 +400,7 @@
" 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 @@
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 @@
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 @@
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 @@
}
}
+ 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 @@
}
}
- 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 (clearLog) {
+ int ret;
+ ret = android::clearLog(dev->fd);
+ if (ret) {
+ 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);
+ }
+
+ dev = dev->next;
}
if (getLogSize) {
- int size, readable;
-
- size = android::getLogSize(logfd);
- if (size < 0) {
- perror("ioctl");
- exit(EXIT_FAILURE);
- }
-
- readable = android::getLogReadableSize(logfd);
- if (readable < 0) {
- perror("ioctl");
- exit(EXIT_FAILURE);
- }
-
- 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);
+ return 0;
+ }
+ if (clearLog) {
return 0;
}
@@ -559,10 +774,10 @@
//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/netcfg/netcfg.c b/netcfg/netcfg.c
index fc9cf48..9cd883a 100644
--- a/netcfg/netcfg.c
+++ b/netcfg/netcfg.c
@@ -19,17 +19,13 @@
#include <stdlib.h>
#include <errno.h>
#include <dirent.h>
+#include <netinet/ether.h>
+
+#include <netutils/ifc.h>
+#include <netutils/dhcp.h>
static int verbose = 0;
-int ifc_init();
-void ifc_close();
-int ifc_up(char *iname);
-int ifc_down(char *iname);
-int ifc_remove_host_routes(char *iname);
-int ifc_remove_default_route(char *iname);
-int ifc_get_info(const char *name, unsigned *addr, unsigned *mask, unsigned *flags);
-int do_dhcp(char *iname);
void die(const char *reason)
{
@@ -37,16 +33,12 @@
exit(1);
}
-const char *ipaddr(unsigned addr)
+const char *ipaddr(in_addr_t addr)
{
- static char buf[32];
-
- sprintf(buf,"%d.%d.%d.%d",
- addr & 255,
- ((addr >> 8) & 255),
- ((addr >> 16) & 255),
- (addr >> 24));
- return buf;
+ struct in_addr in_addr;
+
+ in_addr.s_addr = addr;
+ return inet_ntoa(in_addr);
}
void usage(void)
@@ -86,6 +78,15 @@
return 0;
}
+int set_hwaddr(const char *name, const char *asc) {
+ struct ether_addr *addr = ether_aton(asc);
+ if (!addr) {
+ printf("Failed to parse '%s'\n", asc);
+ return -1;
+ }
+ return ifc_set_hwaddr(name, addr->ether_addr_octet);
+}
+
struct
{
const char *name;
@@ -97,6 +98,7 @@
{ "down", 1, ifc_down },
{ "flhosts", 1, ifc_remove_host_routes },
{ "deldefault", 1, ifc_remove_default_route },
+ { "hwaddr", 2, set_hwaddr },
{ 0, 0, 0 },
};
diff --git a/nexus/DhcpClient.cpp b/nexus/DhcpClient.cpp
index a5654d2..713059d 100644
--- a/nexus/DhcpClient.cpp
+++ b/nexus/DhcpClient.cpp
@@ -27,35 +27,15 @@
#include <sysutils/ServiceManager.h>
+#include <netutils/ifc.h>
+#include <netutils/dhcp.h>
+
#include "DhcpClient.h"
#include "DhcpState.h"
#include "DhcpListener.h"
#include "IDhcpEventHandlers.h"
#include "Controller.h"
-extern "C" {
-int ifc_disable(const char *ifname);
-int ifc_add_host_route(const char *ifname, uint32_t addr);
-int ifc_remove_host_routes(const char *ifname);
-int ifc_set_default_route(const char *ifname, uint32_t gateway);
-int ifc_get_default_route(const char *ifname);
-int ifc_remove_default_route(const char *ifname);
-int ifc_reset_connections(const char *ifname);
-int ifc_configure(const char *ifname, in_addr_t ipaddr, in_addr_t netmask, in_addr_t gateway, in_addr_t dns1, in_addr_t dns2);
-
-int dhcp_do_request(const char *ifname,
- in_addr_t *ipaddr,
- in_addr_t *gateway,
- in_addr_t *mask,
- in_addr_t *dns1,
- in_addr_t *dns2,
- in_addr_t *server,
- uint32_t *lease);
-int dhcp_stop(const char *ifname);
-int dhcp_release_lease(const char *ifname);
-char *dhcp_get_errmsg();
-}
-
DhcpClient::DhcpClient(IDhcpEventHandlers *handlers) :
mState(DhcpState::INIT), mHandlers(handlers) {
mServiceManager = new ServiceManager();
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index 3bb2262..9a56bfd 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -7,8 +7,8 @@
etc/dbus.conf \
etc/hosts
-ifeq ($(TARGET_PRODUCT),generic)
-copy_from += etc/vold.conf
+ifeq ($(TARGET_PRODUCT),full)
+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 @@
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 @@
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 @@
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 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 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 @@
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 @@
iftop \
id \
uptime \
- vmstat
+ vmstat \
+ nandread \
+ ionice
LOCAL_SRC_FILES:= \
toolbox.c \
diff --git a/toolbox/chmod.c b/toolbox/chmod.c
index 31a53bf..2a524e9 100644
--- a/toolbox/chmod.c
+++ b/toolbox/chmod.c
@@ -4,17 +4,74 @@
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>
+#include <sys/limits.h>
+#include <sys/stat.h>
#include <unistd.h>
#include <time.h>
+void recurse_chmod(char* path, int mode)
+{
+ struct dirent *dp;
+ DIR *dir = opendir(path);
+ if (dir == NULL) {
+ // not a directory, carry on
+ return;
+ }
+ char *subpath = malloc(sizeof(char)*PATH_MAX);
+ int pathlen = strlen(path);
+
+ while ((dp = readdir(dir)) != NULL) {
+ if (strcmp(dp->d_name, ".") == 0 ||
+ strcmp(dp->d_name, "..") == 0) continue;
+
+ if (strlen(dp->d_name) + pathlen + 2/*NUL and slash*/ > PATH_MAX) {
+ fprintf(stderr, "Invalid path specified: too long\n");
+ exit(1);
+ }
+
+ strcpy(subpath, path);
+ strcat(subpath, "/");
+ strcat(subpath, dp->d_name);
+
+ if (chmod(subpath, mode) < 0) {
+ fprintf(stderr, "Unable to chmod %s: %s\n", subpath, strerror(errno));
+ exit(1);
+ }
+
+ recurse_chmod(subpath, mode);
+ }
+ free(subpath);
+ closedir(dir);
+}
+
+static int usage()
+{
+ fprintf(stderr, "Usage: chmod [OPTION] <MODE> <FILE>\n");
+ fprintf(stderr, " -R, --recursive change files and directories recursively\n");
+ fprintf(stderr, " --help display this help and exit\n");
+
+ return 10;
+}
+
int chmod_main(int argc, char **argv)
{
int i;
- if (argc < 3) {
- fprintf(stderr, "Usage: chmod <MODE> <FILE>\n");
- return 10;
+ if (argc < 3 || strcmp(argv[1], "--help") == 0) {
+ return usage();
+ }
+
+ int recursive = (strcmp(argv[1], "-R") == 0 ||
+ strcmp(argv[1], "--recursive") == 0) ? 1 : 0;
+
+ if (recursive && argc < 4) {
+ return usage();
+ }
+
+ if (recursive) {
+ argc--;
+ argv++;
}
int mode = 0;
@@ -29,11 +86,15 @@
}
s++;
}
+
for (i = 2; i < argc; i++) {
if (chmod(argv[i], mode) < 0) {
fprintf(stderr, "Unable to chmod %s: %s\n", argv[i], strerror(errno));
return 10;
}
+ if (recursive) {
+ recurse_chmod(argv[i], mode);
+ }
}
return 0;
}
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 @@
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 @@
return 0;
}
-
diff --git a/toolbox/insmod.c b/toolbox/insmod.c
index 44b9847..756a64b 100644
--- a/toolbox/insmod.c
+++ b/toolbox/insmod.c
@@ -77,7 +77,6 @@
memcpy(ptr, argv[i], len);
ptr += len;
*ptr++ = ' ';
- *ptr++ = '\0';
}
*(ptr - 1) = '\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 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;
+}
+
+static int listfile_size(const char *path, const char *filename, int flags)
{
struct stat s;
- if (lstat(path, &s) < 0)
+ 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 @@
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 @@
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/mkdir.c b/toolbox/mkdir.c
index 121adab..656970a 100644
--- a/toolbox/mkdir.c
+++ b/toolbox/mkdir.c
@@ -2,10 +2,14 @@
#include <unistd.h>
#include <string.h>
#include <errno.h>
+#include <sys/limits.h>
+#include <sys/stat.h>
static int usage()
{
- fprintf(stderr,"mkdir <target>\n");
+ fprintf(stderr,"mkdir [OPTION] <target>\n");
+ fprintf(stderr," --help display usage and exit\n");
+ fprintf(stderr," -p, --parents create parent directories as needed\n");
return -1;
}
@@ -13,15 +17,60 @@
{
int symbolic = 0;
int ret;
- if(argc < 2) return usage();
+ if(argc < 2 || strcmp(argv[1], "--help") == 0) {
+ return usage();
+ }
+
+ int recursive = (strcmp(argv[1], "-p") == 0 ||
+ strcmp(argv[1], "--parents") == 0) ? 1 : 0;
+
+ if(recursive && argc < 3) {
+ // -p specified without a path
+ return usage();
+ }
+
+ if(recursive) {
+ argc--;
+ argv++;
+ }
+
+ char currpath[PATH_MAX], *pathpiece;
+ struct stat st;
while(argc > 1) {
argc--;
argv++;
- ret = mkdir(argv[0], 0777);
- if(ret < 0) {
- fprintf(stderr, "mkdir failed for %s, %s\n", argv[0], strerror(errno));
- return ret;
+ if(recursive) {
+ // reset path
+ strcpy(currpath, "");
+ // create the pieces of the path along the way
+ pathpiece = strtok(argv[0], "/");
+ if(argv[0][0] == '/') {
+ // prepend / if needed
+ strcat(currpath, "/");
+ }
+ while(pathpiece != NULL) {
+ if(strlen(currpath) + strlen(pathpiece) + 2/*NUL and slash*/ > PATH_MAX) {
+ fprintf(stderr, "Invalid path specified: too long\n");
+ return 1;
+ }
+ strcat(currpath, pathpiece);
+ strcat(currpath, "/");
+ if(stat(currpath, &st) != 0) {
+ ret = mkdir(currpath, 0777);
+ if(ret < 0) {
+ fprintf(stderr, "mkdir failed for %s, %s\n", currpath, strerror(errno));
+ return ret;
+ }
+ }
+ pathpiece = strtok(NULL, "/");
+ }
+ } else {
+ ret = mkdir(argv[0], 0777);
+ if(ret < 0) {
+ fprintf(stderr, "mkdir failed for %s, %s\n", argv[0], strerror(errno));
+ return ret;
+ }
}
}
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 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 @@
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 @@
}
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 @@
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/switch.h b/vold/switch.h
deleted file mode 100644
index 6729f2d..0000000
--- a/vold/switch.h
+++ /dev/null
@@ -1,25 +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 _SWITCH_H
-#define _SWITCH_H
-
-#include "vold.h"
-
-#define SYSFS_CLASS_SWITCH_PATH "/sys/class/switch"
-
-#endif
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;
-}
diff --git a/vold/volmgr_vfat.h b/vold/volmgr_vfat.h
deleted file mode 100644
index d9cf04d..0000000
--- a/vold/volmgr_vfat.h
+++ /dev/null
@@ -1,29 +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_VFAT_H
-#define _VOLMGR_VFAT_H
-
-#include "volmgr.h"
-#include "blkdev.h"
-
-
-
-int vfat_identify(blkdev_t *blkdev);
-int vfat_check(blkdev_t *blkdev);
-int vfat_mount(blkdev_t *blkdev, volume_t *vol, boolean safe_mode);
-#endif