auto import from //branches/cupcake/...@130745

This commit is contained in:
The Android Open Source Project 2009-02-10 15:44:07 -08:00
parent dcf3ce247e
commit 13f797da7f
36 changed files with 1560 additions and 701 deletions

View File

@ -292,7 +292,8 @@ static int find_usb_device(const char *base,
}
}
register_device_callback(devname, local_ep_in, local_ep_out, i, serial, zero_mask);
register_device_callback(devname, local_ep_in, local_ep_out,
interface->bInterfaceNumber, serial, zero_mask);
found_device = 1;
break;

View File

@ -195,7 +195,7 @@ void usage(void)
"\n"
"commands:\n"
" update <filename> reflash device from update.zip\n"
" flashall 'flash boot' + 'flash system'\n"
" flashall flash boot + recovery + system\n"
" flash <partition> [ <filename> ] write a file to a flash partition\n"
" erase <partition> erase a flash partition\n"
" getvar <variable> display a bootloader variable\n"
@ -588,6 +588,9 @@ int main(int argc, char **argv)
} else if(!strcmp(*argv, "reboot-bootloader")) {
wants_reboot_bootloader = 1;
skip(1);
} else if (!strcmp(*argv, "continue")) {
fb_queue_command("continue", "resuming boot");
skip(1);
} else if(!strcmp(*argv, "boot")) {
char *kname = 0;
char *rname = 0;

View File

@ -42,8 +42,10 @@ enum GGLPixelFormat {
// 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 = 0x14,
GGL_PIXEL_FORMAT_YCbCr_420_P = 0x15,
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/special formats
GGL_PIXEL_FORMAT_Z_16 = 0x18,
@ -60,7 +62,10 @@ enum GGLFormatComponents {
GGL_RGBA = 0x1908,
GGL_LUMINANCE = 0x1909,
GGL_LUMINANCE_ALPHA = 0x190A,
GGL_Y_CB_CR = 0x8000,
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 {

View File

@ -40,12 +40,12 @@ static GGLFormat const gPixelFormatInfos[] =
{ 0, 0, {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 0 }, // PIXEL_FORMAT_NONE
{ 0, 0, {{ 0, 0, 0, 0, 0, 0, 0, 0 }}, 0 }, // PIXEL_FORMAT_NONE
{ 1, 16, {{ 0, 8, 0, 8, 0, 8, 0, 0 }}, GGL_Y_CB_CR },// PIXEL_FORMAT_YCbCr_422_SP
{ 1, 12, {{ 0, 8, 0, 8, 0, 8, 0, 0 }}, GGL_Y_CB_CR },// PIXEL_FORMAT_YCbCr_420_SP
{ 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
{ 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

View File

@ -58,6 +58,9 @@
# 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
#
@ -295,19 +298,28 @@
# PDP Setup failures
50105 pdp_setup_fail (cause|1|5), (cid|1|5), (network_type|1|5)
# Call drops
# 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
# 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)
# 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)
@ -315,3 +327,4 @@
# 0 for screen off, 1 for screen on, 2 for key-guard done
70000 screen_toggled (screen_state|1|5)

View File

@ -18,4 +18,5 @@ LOCAL_CFLAGS := -DCREATE_MOUNT_POINTS=0
LOCAL_SHARED_LIBRARIES := libcutils
include $(BUILD_EXECUTABLE)
# disabled - we are using vold now instead
# include $(BUILD_EXECUTABLE)

View File

@ -4,7 +4,6 @@ include $(CLEAR_VARS)
# files that live under /system/etc/...
copy_from := \
etc/mountd.conf \
etc/dbus.conf \
etc/init.goldfish.sh \
etc/hosts

View File

@ -41,6 +41,7 @@ TOOLS := \
printenv \
smd \
chmod \
chown \
mkdosfs \
netstat \
ioctl \

62
toolbox/chown.c Normal file
View File

@ -0,0 +1,62 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>
#include <pwd.h>
#include <grp.h>
#include <unistd.h>
#include <time.h>
int chown_main(int argc, char **argv)
{
int i;
if (argc < 3) {
fprintf(stderr, "Usage: chown <USER>[.GROUP] <FILE1> [FILE2] ...\n");
return 10;
}
// Copy argv[1] to 'user' so we can truncate it at the period
// if a group id specified.
char user[32];
char *group = NULL;
strncpy(user, argv[1], sizeof(user));
if ((group = strchr(user, '.')) != NULL) {
*group++ = '\0';
}
// Lookup uid (and gid if specified)
struct passwd *pw;
struct group *grp = NULL;
uid_t uid;
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;
}
uid = pw->pw_uid;
if (group != NULL) {
grp = getgrnam(group);
if (grp == NULL) {
fprintf(stderr, "No such group '%s'\n", group);
return 10;
}
gid = grp->gr_gid;
}
for (i = 2; i < argc; i++) {
if (chown(argv[i], uid, gid) < 0) {
fprintf(stderr, "Unable to chmod %s: %s\n", argv[i], strerror(errno));
return 10;
}
}
return 0;
}

View File

@ -45,10 +45,12 @@ bail:
return buffer;
}
#define min(x,y) ((x) < (y) ? (x) : (y))
int insmod_main(int argc, char **argv)
{
void *file;
ssize_t size;
ssize_t size = 0;
char opts[1024];
int ret;
/* make sure we've got an argument */
@ -64,9 +66,24 @@ int insmod_main(int argc, char **argv)
return -1;
}
opts[0] = '\0';
if (argc > 2) {
int i, len;
char *end = opts + sizeof(opts) - 1;
char *ptr = opts;
for (i = 2; (i < argc) && (ptr < end); i++) {
len = min(strlen(argv[i]), end - ptr);
memcpy(ptr, argv[i], len);
ptr += len;
*ptr++ = ' ';
*ptr++ = '\0';
}
*(ptr - 1) = '\0';
}
/* pass it to the kernel */
/* XXX options */
ret = init_module(file, size, "");
ret = init_module(file, size, opts);
if (ret != 0) {
fprintf(stderr,
"insmod: init_module '%s' failed (%s)\n",

View File

@ -1,7 +1,3 @@
BUILD_VOLD := false
ifeq ($(BUILD_VOLD),true)
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
@ -10,7 +6,6 @@ LOCAL_SRC_FILES:= \
vold.c \
cmd_dispatch.c \
uevent.c \
inotify.c \
mmc.c \
misc.c \
blkdev.c \
@ -22,6 +17,9 @@ LOCAL_SRC_FILES:= \
volmgr_ext3.c \
logwrapper.c \
ProcessKiller.c\
switch.c \
format.c \
devmapper.c
LOCAL_MODULE:= vold
@ -32,5 +30,3 @@ LOCAL_CFLAGS :=
LOCAL_SHARED_LIBRARIES := libcutils
include $(BUILD_EXECUTABLE)
endif

View File

@ -27,6 +27,7 @@
#include <sys/mman.h>
#include <linux/fs.h>
#include <linux/msdos_fs.h>
#include "vold.h"
#include "blkdev.h"
@ -37,74 +38,37 @@
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, char *dev_fspath);
static void blkdev_dev_fspath_set(blkdev_t *blk, char *dev_fspath);
int minor, char *type, struct media *media);
int blkdev_handle_devicefile_removed(blkdev_t *blk, char *dev_fspath)
static int fat_valid_media(unsigned char media)
{
return 0xf8 <= media || media == 0xf0;
}
char *blkdev_get_devpath(blkdev_t *blk)
{
#if DEBUG_BLKDEV
LOG_VOL("blkdev_handle_devicefile_removed(%s):\n", dev_fspath);
#endif
blkdev_dev_fspath_set(blk, NULL);
return 0;
char *dp = malloc(256);
sprintf(dp, "%s/vold/%d:%d", DEVPATH, blk->major, blk->minor);
return dp;
}
int blkdev_handle_devicefile_created(blkdev_t *blk, char *dev_fspath)
int blkdev_refresh(blkdev_t *blk)
{
int rc = 0;
blkdev_t *disk;
#if DEBUG_BLKDEV
LOG_VOL("blkdev_handle_devicefile_created(%s):\n", dev_fspath);
#endif
int fd = 0;
char *devpath = NULL;
unsigned char *block = NULL;
int i, rc;
if (!blk) {
/*
* This device does not yet have a backing blkdev associated with it.
* Create a new one in the pending state and fill in the information
* we have.
*/
struct stat sbuf;
if (stat(dev_fspath, &sbuf) < 0) {
LOGE("Unable to stat device '%s' (%s)\n", dev_fspath, strerror(errno));
return -errno;
}
int major = (sbuf.st_rdev & 0xfff00) >> 8;
int minor = (sbuf.st_rdev & 0xff) | ((sbuf.st_rdev >> 12) & 0xfff00);
disk = blkdev_lookup_by_devno(major, 0);
if (!disk) {
/*
* If there isn't a disk associated with this device, then
* its not what we're looking for
*/
#if DEBUG_BLKDEV
LOG_VOL("Ignoring device file '%s' (no disk found)\n", dev_fspath);
#endif
return 0;
}
if (!(blk = blkdev_create_pending_partition(disk, dev_fspath, major,
minor, disk->media))) {
LOGE("Unable to create pending blkdev\n");
return -1;
}
} else
blkdev_dev_fspath_set(blk, dev_fspath);
if (!(block = malloc(512)))
goto out;
/*
* If we're a disk, then read the partition table. Otherwise we're
* a partition so get the partition type
* Get the device size
*/
disk = blk->disk;
devpath = blkdev_get_devpath(blk);
int fd;
if ((fd = open(disk->dev_fspath, O_RDWR)) < 0) {
LOGE("Unable to open device '%s' (%s)\n", disk->dev_fspath, strerror(errno));
if ((fd = open(devpath, O_RDONLY)) < 0) {
LOGE("Unable to open device '%s' (%s)\n", devpath, strerror(errno));
return -errno;
}
@ -112,77 +76,101 @@ int blkdev_handle_devicefile_created(blkdev_t *blk, char *dev_fspath)
LOGE("Unable to get device size (%m)\n");
return -errno;
}
close(fd);
free(devpath);
#if DEBUG_BLKDEV
LOG_VOL("New device '%s' size = %u sectors\n", dev_fspath, blk->nr_sec);
#endif
void *raw_pt;
unsigned char *chr_pt;
int i;
raw_pt = chr_pt = mmap(NULL, 512, PROT_READ, MAP_PRIVATE, fd, 0);
if (raw_pt == MAP_FAILED) {
LOGE("Unable to mmap device paritition table (%m)\n");
goto out_nommap;
/*
* 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)\n", 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)\n",
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 ((chr_pt[0x1fe] != 0x55) && (chr_pt[0x1ff] != 0xAA)) {
LOG_VOL("Disk '%s' does not contain a partition table\n", dev_fspath);
if ((block[0x1fe] != 0x55) || (block[0x1ff] != 0xAA)) {
LOG_VOL("Disk %d:%d does not contain a partition table\n",
blk->major, blk->minor);
goto out;
}
for (i = 0; i < 4; i++) {
struct dos_partition part;
dos_partition_dec(raw_pt + DOSPARTOFF + i * sizeof(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)) {
LOG_VOL("Detected FAT filesystem in partition table\n");
break;
} else {
LOG_VOL("Partition table looks corrupt\n");
break;
}
}
if (part.dp_size != 0 && part.dp_typ != 0)
blk->nr_parts++;
}
LOG_VOL("Disk device '%s' (blkdev %s) contains %d partitions\n",
dev_fspath, blk->devpath, blk->nr_parts);
} else if (blk->type == blkdev_partition) {
struct dos_partition part;
int part_no = blk->minor -1;
dos_partition_dec(raw_pt + DOSPARTOFF + part_no * sizeof(struct dos_partition), &part);
if (!part.dp_typ)
LOG_VOL("Warning - Partition device '%s' (blkdev %s) has no partition type set\n",
dev_fspath, blk->devpath);
dos_partition_dec(block + DOSPARTOFF + part_no * sizeof(struct dos_partition), &part);
blk->part_type = part.dp_typ;
LOG_VOL("Partition device '%s' (blkdev %s) partition type 0x%x\n",
dev_fspath, blk->devpath, blk->part_type);
} else {
LOGE("Bad blkdev type '%d'\n", blk->type);
rc = -EINVAL;
goto out;
}
out:
munmap(raw_pt, 512);
out_nommap:
close(fd);
return rc;
}
blkdev_t *blkdev_create_pending_partition(blkdev_t *disk, char *dev_fspath, int major,
int minor, struct media *media)
{
return _blkdev_create(disk, NULL, major, minor, "partition", media, dev_fspath);
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,
((blk->nr_sec * 512) / 1024) / 1024);
if (blk->type == blkdev_disk)
sprintf(tmp2, " %d partitions\n", blk->nr_parts);
else
sprintf(tmp2, " type 0x%x\n", blk->part_type);
strcat(tmp, tmp2);
LOG_VOL(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, NULL);
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, char *dev_fspath)
int minor, char *type, struct media *media)
{
blkdev_t *new;
struct blkdev_list *list_entry;
@ -218,8 +206,6 @@ static blkdev_t *_blkdev_create(blkdev_t *disk, char *devpath, int major,
new->major = major;
new->minor = minor;
new->media = media;
if (dev_fspath)
new->dev_fspath = strdup(dev_fspath);
new->nr_sec = 0xffffffff;
if (disk)
@ -227,6 +213,17 @@ static blkdev_t *_blkdev_create(blkdev_t *disk, char *devpath, int major,
else
new->disk = new; // Note the self disk pointer
/* Create device nodes */
char nodepath[255];
mode_t mode = 0666 | 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)\n",
nodepath, strerror(errno));
}
if (!strcmp(type, "disk"))
new->type = blkdev_disk;
else if (!strcmp(type, "partition"))
@ -258,8 +255,11 @@ void blkdev_destroy(blkdev_t *blkdev)
if (blkdev->devpath)
free(blkdev->devpath);
if (blkdev->dev_fspath)
free(blkdev->dev_fspath);
char nodepath[255];
sprintf(nodepath, "%s/vold/%d:%d", DEVPATH, blkdev->major, blkdev->minor);
unlink(nodepath);
free(blkdev);
}
@ -272,9 +272,6 @@ blkdev_t *blkdev_lookup_by_path(char *devpath)
return list_scan->dev;
list_scan = list_scan->next;
}
#if DEBUG_BLKDEV
LOG_VOL("blkdev_lookup_by_path(): No blkdev found @ %s\n", devpath);
#endif
return NULL;
}
@ -288,32 +285,12 @@ blkdev_t *blkdev_lookup_by_devno(int maj, int min)
return list_scan->dev;
list_scan = list_scan->next;
}
#if DEBUG_BLKDEV
LOG_VOL("blkdev_lookup_by_devno(): No blkdev found for %d.%d\n", maj, min);
#endif
return NULL;
}
blkdev_t *blkdev_lookup_by_dev_fspath(char *dev_fspath)
{
struct blkdev_list *list_scan = list_root;
while (list_scan) {
if (list_scan->dev->dev_fspath) {
if (!strcmp(list_scan->dev->dev_fspath, dev_fspath))
return list_scan->dev;
}
list_scan = list_scan->next;
}
// LOG_VOL("blkdev_lookup_by_devno(): No blkdev found for %d.%d\n", maj, min);
return NULL;
}
/*
* Given a disk device, return the number of partitions yet to be
* processed.
* Given a disk device, return the number of partitions which
* have yet to be processed.
*/
int blkdev_get_num_pending_partitions(blkdev_t *blk)
{
@ -330,25 +307,13 @@ int blkdev_get_num_pending_partitions(blkdev_t *blk)
if (list_scan->dev->major != blk->major)
goto next;
if (list_scan->dev->nr_sec != 0xffffffff)
if (list_scan->dev->nr_sec != 0xffffffff &&
list_scan->dev->devpath) {
num--;
}
next:
list_scan = list_scan->next;
}
return num;
}
void blkdev_devpath_set(blkdev_t *blk, char *devpath)
{
blk->devpath = strdup(devpath);
}
static void blkdev_dev_fspath_set(blkdev_t *blk, char *dev_fspath)
{
if (dev_fspath)
blk->dev_fspath = strdup(dev_fspath);
else {
free(blk->dev_fspath);
blk->dev_fspath = NULL;
}
}

View File

@ -41,7 +41,6 @@ struct blkdev {
int major;
int minor;
char *dev_fspath;
};
struct blkdev_list {
@ -56,11 +55,10 @@ blkdev_t *blkdev_create(blkdev_t *disk, char *devpath, int major, int minor, str
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);
blkdev_t *blkdev_lookup_by_dev_fspath(char *dev_fspath);
char *blkdev_get_devpath(blkdev_t *blk);
void blkdev_destroy(blkdev_t *blk);
int blkdev_handle_devicefile_created(blkdev_t *blk, char *dev_fspath);
int blkdev_handle_devicefile_removed(blkdev_t *blk, char *dev_fspath);
int blkdev_get_num_pending_partitions(blkdev_t *blk);
void blkdev_devpath_set(blkdev_t *blk, char *dev_fspath);
int blkdev_refresh(blkdev_t *blk);
#endif

View File

@ -33,13 +33,15 @@ 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_MOUNT_VOLUME, do_mount_volume },
{ VOLD_CMD_EJECT_MEDIA, do_eject_media },
{ VOLD_CMD_FORMAT_MEDIA, do_format_media },
{ NULL, NULL }
};
@ -51,7 +53,8 @@ int process_framework_command(int socket)
if ((rc = read(socket, buffer, sizeof(buffer) -1)) < 0) {
LOGE("Unable to read framework command (%s)\n", strerror(errno));
return -errno;
}
} else if (!rc)
return -ECONNRESET;
int start = 0;
int i;
@ -101,6 +104,11 @@ 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:")]);

View File

@ -26,5 +26,6 @@
// 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

168
vold/devmapper.c Normal file
View File

@ -0,0 +1,168 @@
/*
* 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 <cutils/config_utils.h>
#include <cutils/properties.h>
#include "vold.h"
#include "devmapper.h"
#define DEBUG_DEVMAPPER 1
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)\n", 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)\n", filename,
strerror(errno));
return -errno;
}
}
if (i == MAX_LOOP) {
LOGE("Out of loop devices\n");
return -ENOSPC;
}
int file_fd;
if ((file_fd = open(dm->type_data.loop.loop_src, O_RDWR)) < 0) {
LOGE("Unable to open %s (%s)\n", 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)\n", 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\n", 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
*/
return 0;
}
struct devmapping *devmapper_init(char *src, char *src_type, uint32_t size_mb,
char *target, char *params, char *tgt_fs)
{
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);
return dm;
out_free:
return NULL;
}

64
vold/devmapper.h Normal file
View File

@ -0,0 +1,64 @@
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _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;
};
struct devmapping *devmapper_init(char *, char *, unsigned int, char *, char *, char*);
int devmapper_start(struct devmapping *);
int devmapper_stop(struct devmapping *);
#endif

100
vold/format.c Executable file
View File

@ -0,0 +1,100 @@
/*
* 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/mkdosfs";
int format_partition(blkdev_t *part)
{
char *devpath;
char *args[7];
devpath = blkdev_get_devpath(part);
args[0] = MKDOSFS_PATH;
args[1] = "-F 32";
args[2] = "-c 32";
args[3] = "-n 2";
args[4] = "-O android";
args[5] = devpath;
args[6] = NULL;
int rc = logwrap(6, args);
free(devpath);
if (rc == 0) {
LOG_VOL("Filesystem formatted OK\n");
return 0;
} else {
LOGE("Format failed (unknokwn exit code %d)\n", 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)\n", strerror(errno));
return -errno;
}
free(devpath);
if (write(fd, block, sizeof(block)) < 0) {
LOGE("Error writing MBR (%s)\n", strerror(errno));
close(fd);
return -errno;
}
if (ioctl(fd, BLKRRPART, NULL) < 0) {
LOGE("Error re-reading partition table (%s)\n", strerror(errno));
close(fd);
return -errno;
}
close(fd);
return 0;
}

23
vold/format.h Normal file
View File

@ -0,0 +1,23 @@
/*
* 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
int format_partition(blkdev_t *part);
int initialize_mbr(blkdev_t *disk);
#endif

View File

@ -44,6 +44,17 @@ le32dec(const void *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)
{
@ -60,3 +71,20 @@ dos_partition_dec(void const *pp, struct dos_partition *d)
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);
}

View File

@ -1,270 +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 <sys/types.h>
#include <sys/inotify.h>
#include <sys/stat.h>
#include "vold.h"
#include "inotify.h"
#include "blkdev.h"
#include "volmgr.h"
#define DEBUG_INOTIFY 0
static int handle_inotify_event(struct inotify_event *evt);
int process_inotify_event(int fd)
{
char buffer[512];
int len;
int offset = 0;
if ((len = read(fd, buffer, sizeof(buffer))) < 0) {
LOGE("Unable to read inotify event (%m)\n");
return -errno;
}
while (len >= (int) sizeof(struct inotify_event)) {
struct inotify_event *evt = (struct inotify_event *) &buffer[offset];
if (handle_inotify_event(evt) < 0)
LOGE("Error handling inotify event (%m)\n");
len -= sizeof(struct inotify_event) + evt->len;
offset += sizeof(struct inotify_event) + evt->len;
}
return 0;
}
struct blk_dev_entry {
int minor;
char *name;
struct blk_dev_entry *next;
};
int inotify_bootstrap(void)
{
DIR *d;
struct dirent *de;
if (!(d = opendir(DEVPATH))) {
LOGE("Unable to open directory '%s' (%m)\n", DEVPATH);
return -errno;
}
struct blk_dev_entry *blkdevs[255];
memset(blkdevs, 0, sizeof(blkdevs));
while((de = readdir(d))) {
char filename[255];
struct stat sbuf;
if (de->d_name[0] == '.')
continue;
sprintf(filename, "%s/%s", DEVPATH, de->d_name);
if (stat(filename, &sbuf) < 0) {
LOGE("Unable to stat '%s' (%m)\n", filename);
continue;
}
if (!S_ISBLK(sbuf.st_mode))
continue;
int major = (sbuf.st_rdev & 0xfff00) >> 8;
int minor = (sbuf.st_rdev & 0xff) | ((sbuf.st_rdev >> 12) & 0xfff00);
struct blk_dev_entry *entry;
if (!(entry = malloc(sizeof(struct blk_dev_entry)))) {
LOGE("Out of memory\n");
break;
}
entry->minor = minor;
entry->name = strdup(de->d_name);
entry->next = NULL;
if (!blkdevs[major])
blkdevs[major] = entry;
else {
struct blk_dev_entry *scan = blkdevs[major];
/*
* Insert the entry in minor number ascending order
*/
while(scan) {
if (minor < scan->minor) {
entry->next = scan;
if (scan == blkdevs[major])
blkdevs[major] = entry;
else
scan->next = entry;
break;
}
scan = scan->next;
}
if (!scan) {
scan = blkdevs[major];
while(scan->next)
scan = scan->next;
scan->next = entry;
}
}
}
closedir(d);
int i = 0;
for (i = 0; i < 255; i++) {
if (!blkdevs[i])
continue;
struct blk_dev_entry *scan = blkdevs[i];
while(scan) {
struct inotify_event *evt;
int len;
len = sizeof(struct inotify_event) + strlen(scan->name);
if (!(evt = malloc(len))) {
LOGE("Out of memory\n");
break;
}
memset(evt, 0, len);
strcpy(evt->name, scan->name);
evt->mask = IN_CREATE;
if (handle_inotify_event(evt) < 0)
LOGE("Error handling bootstrapped inotify event (%m)\n");
free(evt);
scan = scan->next;
}
}
for (i = 0; i < 255; i++) {
if (!blkdevs[i])
continue;
if (!blkdevs[i]->next) {
free(blkdevs[i]->name);
free(blkdevs[i]);
blkdevs[i] = NULL;
continue;
}
struct blk_dev_entry *scan = blkdevs[i];
while(scan) {
struct blk_dev_entry *next = scan->next->next;
free(scan->next->name);
free(scan->next);
scan->next = next;
scan = next;
}
} // for
return 0;
}
static int handle_inotify_event(struct inotify_event *evt)
{
char filename[255];
int rc;
#if DEBUG_INOTIFY
LOG_VOL("Inotify '%s' %s\n", evt->name, (evt->mask == IN_CREATE ? "created" : "deleted"));
#endif
sprintf(filename, "%s%s", DEVPATH, evt->name);
if (evt->mask == IN_CREATE) {
struct stat sbuf;
if (stat(filename, &sbuf) < 0) {
LOGE("Unable to stat '%s' (%m)\n", filename);
return -errno;
}
if (!S_ISBLK(sbuf.st_mode)) {
#if DEBUG_INOTIFY
LOG_VOL("Ignoring inotify on '%s' (not a block device)\n", evt->name);
#endif
return 0;
}
int major = (sbuf.st_rdev & 0xfff00) >> 8;
int minor = (sbuf.st_rdev & 0xff) | ((sbuf.st_rdev >> 12) & 0xfff00);
blkdev_t *blkdev = blkdev_lookup_by_devno(major, minor);
if ((rc = blkdev_handle_devicefile_created(blkdev, filename)) < 0) {
LOGE("Error handling device file '%s' creation (%s)\n", filename, strerror(rc));
return rc;
}
if (!blkdev) {
#if DEBUG_INOTIFY
LOG_VOL("No backing blkdev for '%s' available (yet) - pending volmgr dispatch\n", filename);
#endif
return 0;
}
#if DEBUG_INOTIFY
LOG_VOL("NUM_PENDING_PARTITIONS = %d\n", blkdev_get_num_pending_partitions(blkdev));
#endif
if (blkdev_get_num_pending_partitions(blkdev->disk) == 0) {
if ((rc = volmgr_consider_disk(blkdev->disk)) < 0) {
LOGE("Error from volmgr - %d\n", rc);
return rc;
}
}
} else {
blkdev_t *blkdev;
if (!(blkdev = blkdev_lookup_by_dev_fspath(filename))) {
#if DEBUG_INOTIFY
LOG_VOL("Ignoring removal of '%s' (no backend blkdev)\n", filename);
#endif
return 0;
}
if ((rc = blkdev_handle_devicefile_removed(blkdev, filename)) < 0) {
LOGE("Error handling device file '%s' removal (%s)\n", filename, strerror(rc));
return rc;
}
}
return 0;
}

View File

@ -85,8 +85,8 @@ void media_destroy(media_t *media)
free(media->devpath);
free(media->name);
if (media->devs)
LOGE("media_destroy(): media still has blkdevs associated with it! Possible leak\n");
while(media->devs)
media_remove_blkdev(media, media->devs->dev);
free(media);
}

View File

@ -25,7 +25,7 @@
typedef enum media_type {
media_unknown,
media_mmc,
media_dm
media_devmapper,
} media_type_t;
typedef struct media {

View File

@ -118,7 +118,7 @@ static int mmc_bootstrap_card(char *sysfs_path)
* sysfs_path is based on /sys/class, but we want the actual device class
*/
if (!getcwd(saved_cwd, sizeof(saved_cwd))) {
LOGE("Buffer too small for working dir path\n");
LOGE("Error getting working dir path\n");
return -errno;
}

121
vold/switch.c Normal file
View File

@ -0,0 +1,121 @@
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <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' (%m)\n", SYSFS_CLASS_SWITCH_PATH);
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' (%m)\n", tmp);
}
closedir(d);
return 0;
}
static int mmc_bootstrap_switch(char *sysfs_path)
{
#if DEBUG_BOOTSTRAP
LOG_VOL("bootstrap_switch(%s):\n", 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)\n",
sysfs_path, strerror(errno));
return -errno;
}
if (!fgets(name, sizeof(name), fp)) {
LOGE("Unable to read switch name\n");
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)\n",
sysfs_path, strerror(errno));
return -errno;
}
if (!fgets(state, sizeof(state), fp)) {
LOGE("Unable to read switch state\n");
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)\n", strerror(errno));
return -errno;
}
return 0;
}

View File

@ -15,8 +15,11 @@
* limitations under the License.
*/
#ifndef _INOTIFY_EVT_H
#define _INOTIFY_EVT_H
#ifndef _SWITCH_H
#define _SWITCH_H
#include "vold.h"
#define SYSFS_CLASS_SWITCH_PATH "/sys/class/switch"
#endif

View File

@ -71,6 +71,9 @@ static struct uevent_dispatch dispatch_table[] = {
{ NULL, NULL }
};
static boolean low_batt = false;
static boolean door_open = false;
int process_uevent_message(int socket)
{
char buffer[64 * 1024]; // Thank god we're not in the kernel :)
@ -120,7 +123,7 @@ int process_uevent_message(int socket)
else
event->param[param_idx++] = strdup(s);
}
s+= (strlen(s) + 1);
s+= strlen(s) + 1;
}
rc = dispatch_uevent(event);
@ -172,6 +175,9 @@ 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);
@ -232,7 +238,19 @@ static char *get_uevent_param(struct uevent *event, char *param_name)
static int handle_powersupply_event(struct uevent *event)
{
dump_uevent(event);
char *ps_type = get_uevent_param(event, "POWER_SUPPLY_TYPE");
char *ps_cap = get_uevent_param(event, "POWER_SUPPLY_CAPACITY");
if (!strcasecmp(ps_type, "battery")) {
int capacity = atoi(ps_cap);
if (capacity < 5)
low_batt = true;
else
low_batt = false;
LOG_VOL("handle_powersupply_event(): low_batt = %d, door_open = %d\n", low_batt, door_open);
volmgr_safe_mode(low_batt || door_open);
}
return 0;
}
@ -241,12 +259,21 @@ 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;
LOG_VOL("handle_powersupply_event(): low_batt = %d, door_open = %d\n", low_batt, door_open);
volmgr_safe_mode(low_batt || door_open);
} else
LOG_VOL("handle_switch_event(): Ignoring switch '%s'\n", name);
@ -255,7 +282,6 @@ static int handle_switch_event(struct uevent *event)
static int handle_battery_event(struct uevent *event)
{
dump_uevent(event);
return 0;
}
@ -293,7 +319,6 @@ static int handle_block_event(struct uevent *event)
if (event->action == action_add) {
blkdev_t *disk;
boolean pending = false;
/*
* If there isn't a disk already its because *we*
@ -301,26 +326,18 @@ static int handle_block_event(struct uevent *event)
*/
disk = blkdev_lookup_by_devno(maj, 0);
/*
* It is possible that there is already a blkdev
* for this device (created by blkdev_create_pending_partition())
*/
if ((blkdev = blkdev_lookup_by_devno(maj, min))) {
blkdev_devpath_set(blkdev, event->path);
pending = true;
} else {
if (!(blkdev = blkdev_create(disk,
event->path,
maj,
min,
media,
get_uevent_param(event, "DEVTYPE")))) {
LOGE("Unable to allocate new blkdev (%m)\n");
return -1;
}
if (!(blkdev = blkdev_create(disk,
event->path,
maj,
min,
media,
get_uevent_param(event, "DEVTYPE")))) {
LOGE("Unable to allocate new blkdev (%m)\n");
return -1;
}
blkdev_refresh(blkdev);
/*
* Add the blkdev to media
*/
@ -330,39 +347,33 @@ static int handle_block_event(struct uevent *event)
return rc;
}
LOG_VOL("New blkdev %d.%d on media %s, media path %s\n", blkdev->major, blkdev->minor, media->name, mediapath);
LOG_VOL("New blkdev %d.%d on media %s, media path %s, Dpp %d\n",
blkdev->major, blkdev->minor, media->name, mediapath,
blkdev_get_num_pending_partitions(blkdev->disk));
if (pending) {
/*
* This blkdev already has its dev_fspath set so
* if all partitions are read, pass it off to
* the volume manager
*/
LOG_VOL("Pending disk '%d.%d' has %d pending partitions\n",
blkdev->disk->major, blkdev->disk->minor,
blkdev_get_num_pending_partitions(blkdev->disk));
if (blkdev_get_num_pending_partitions(blkdev->disk) == 0) {
if ((rc = volmgr_consider_disk(blkdev->disk)) < 0) {
LOGE("Volmgr failed to handle pending device (%d)\n", rc);
return rc;
}
if (blkdev_get_num_pending_partitions(blkdev->disk) == 0) {
if ((rc = volmgr_consider_disk(blkdev->disk)) < 0) {
LOGE("Volmgr failed to handle device (%d)\n", rc);
return rc;
}
}
} else if (event->action == action_remove) {
int rc;
if (!(blkdev = blkdev_lookup_by_devno(maj, min))) {
#if DEBUG_UEVENT
LOG_VOL("We aren't handling blkdev @ %s\n", event->path);
#endif
if (!(blkdev = blkdev_lookup_by_devno(maj, min)))
return 0;
}
LOG_VOL("Destroying blkdev %d.%d @ %s on media %s\n", blkdev->major, blkdev->minor, blkdev->devpath, media->name);
if ((rc = volmgr_notify_eject(blkdev, _cb_blkdev_ok_to_destroy)) < 0)
LOGE("Error notifying volmgr of eject\n");
} else {
LOG_VOL("Destroying blkdev %d.%d @ %s on media %s\n", 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;
LOG_VOL("Modified blkdev %d.%d @ %s on media %s\n", blkdev->major,
blkdev->minor, blkdev->devpath, media->name);
blkdev_refresh(blkdev);
} else {
#if DEBUG_UEVENT
LOG_VOL("No handler implemented for action %d\n", event->action);
#endif
@ -417,9 +428,6 @@ static int handle_mmc_event(struct uevent *event)
LOG_VOL("MMC card '%s' (serial %u) @ %s removed\n", media->name,
media->serial, media->devpath);
/*
* If this media is still mounted, then we have an unsafe removal
*/
media_destroy(media);
} else {
#if DEBUG_UEVENT

View File

@ -21,6 +21,8 @@
#include "vold.h"
#include "ums.h"
#define DEBUG_UMS 0
static boolean host_connected = false;
static boolean ums_enabled = false;
@ -42,7 +44,9 @@ boolean ums_enabled_get()
void ums_hostconnected_set(boolean connected)
{
#if DEBUG_UMS
LOG_VOL("ums_hostconnected_set(%d):\n", connected);
#endif
host_connected = connected;
if (!connected)
@ -75,7 +79,9 @@ int ums_enable(char *dev_fspath, char *lun_syspath)
int ums_disable(char *lun_syspath)
{
#if DEBUG_UMS
LOG_VOL("ums_disable(%s):\n", lun_syspath);
#endif
int fd;
char filename[255];
@ -107,7 +113,9 @@ int ums_send_status(void)
{
int rc;
#if DEBUG_UMS
LOG_VOL("ums_send_status():\n");
#endif
rc = send_msg(ums_enabled_get() ? VOLD_EVT_UMS_ENABLED :
VOLD_EVT_UMS_DISABLED);

View File

@ -27,7 +27,6 @@
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/inotify.h>
#include <sys/un.h>
#include <cutils/config_utils.h>
@ -57,7 +56,6 @@ static int fw_sock = -1;
int main(int argc, char **argv)
{
int door_sock = -1;
int inotify_sock = -1;
int uevent_sock = -1;
struct sockaddr_nl nladdr;
int uevent_sz = 64 * 1024;
@ -81,18 +79,7 @@ int main(int argc, char **argv)
exit(1);
}
// Socket to listen on for changes to /dev/block
if ((inotify_sock = inotify_init()) < 0) {
LOGE("Unable to initialize inotify interface (%s)\n", strerror(errno));
exit(1);
}
fcntl(inotify_sock, F_SETFL, O_NONBLOCK | fcntl(inotify_sock, F_GETFL));
if (inotify_add_watch(inotify_sock, DEVPATH, IN_CREATE | IN_DELETE) < 0) {
LOGE("Unable to add inotify watch (%s)\n", strerror(errno));
exit(1);
}
mkdir("/dev/block/vold", 0755);
// Socket to listen on for uevent changes
memset(&nladdr, 0, sizeof(nladdr));
@ -121,22 +108,22 @@ int main(int argc, char **argv)
* Bootstrap
*/
// Volume Manager
volmgr_bootstrap();
// SD Card system
mmc_bootstrap();
// USB Mass Storage
ums_bootstrap();
// Volume Manager
volmgr_bootstrap();
// Block device system
inotify_bootstrap();
// Switch
switch_bootstrap();
/*
* Main loop
*/
LOG_VOL("Bootstrapping complete\n");
while(1) {
fd_set read_fds;
struct timeval to;
@ -146,12 +133,10 @@ int main(int argc, char **argv)
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(inotify_sock, &read_fds);
if (inotify_sock > max)
max = inotify_sock;
FD_SET(uevent_sock, &read_fds);
if (uevent_sock > max)
max = uevent_sock;
@ -178,6 +163,13 @@ int main(int argc, char **argv)
alen = sizeof(addr);
if (fw_sock != -1) {
LOGE("Dropping duplicate framework connection\n");
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)\n",
strerror(errno));
@ -201,19 +193,11 @@ int main(int argc, char **argv)
}
}
if (FD_ISSET(inotify_sock, &read_fds)) {
if ((rc = process_inotify_event(inotify_sock)) < 0) {
LOGE("Error processing inotify msg (%s)\n", strerror(errno));
}
}
if (FD_ISSET(uevent_sock, &read_fds)) {
if ((rc = process_uevent_message(uevent_sock)) < 0) {
LOGE("Error processing uevent msg (%s)\n", strerror(errno));
}
}
} // while
}

View File

@ -86,6 +86,8 @@ 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);
char *read_sysfs_var(char *buffer, size_t maxlen, char *devpath, char *var);

File diff suppressed because it is too large Load Diff

View File

@ -23,6 +23,7 @@
#include "vold.h"
#include "blkdev.h"
#include "media.h"
#include "devmapper.h"
#define PROP_EXTERNAL_STORAGE_STATE "EXTERNAL_STORAGE_STATE"
@ -70,15 +71,18 @@ typedef enum volume_state {
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);
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 {
@ -86,21 +90,38 @@ struct volmgr_start_args {
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_path;
media_type_t media_type;
char *mount_point;
char *ums_path;
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;
struct volmgr_start_args worker_args;
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;
unsigned char *key;
unsigned int keysize;
struct volume *next;
} volume_t;
@ -110,6 +131,8 @@ 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, unsigned int keysize);
void KillProcessesWithOpenFiles(const char* mountPoint, boolean sigkill, int *excluded, int num_excluded);
#endif

View File

@ -15,34 +15,170 @@
* 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 EXT3_DEBUG 0
int ext3_identify(blkdev_t *dev)
#define EXT_DEBUG 0
static char E2FSCK_PATH[] = "/system/bin/e2fsck";
int ext_identify(blkdev_t *dev)
{
#if EXT3_DEBUG
LOG_VOL("ext3_identify(%s):\n", dev->dev_fspath);
int rc = -1;
int fd;
struct ext3_super_block sb;
char *devpath;
#if EXT_DEBUG
LOG_VOL("ext_identify(%d:%d):\n", dev-major, dev->minor);
#endif
return -ENOSYS;
devpath = blkdev_get_devpath(dev);
if ((fd = open(devpath, O_RDWR)) < 0) {
LOGE("Unable to open device '%s' (%s)\n", devpath,
strerror(errno));
free(devpath);
return -errno;
}
if (lseek(fd, 1024, SEEK_SET) < 0) {
LOGE("Unable to lseek to get superblock (%s)\n", strerror(errno));
rc = -errno;
goto out;
}
if (read(fd, &sb, sizeof(sb)) != sizeof(sb)) {
LOGE("Unable to read superblock (%s)\n", 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\n", devpath, rc);
#endif
free(devpath);
close(fd);
return rc;
}
int ext3_check(blkdev_t *dev)
int ext_check(blkdev_t *dev)
{
#if EXT3_DEBUG
LOG_VOL("ext3_check(%s):\n", dev->dev_fspath);
char *devpath;
#if EXT_DEBUG
LOG_VOL("ext_check(%s):\n", dev->dev_fspath);
#endif
return -ENOSYS;
devpath = blkdev_get_devpath(dev);
if (access(E2FSCK_PATH, X_OK)) {
LOGE("ext_check(%s): %s not found (skipping checks)\n",
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);
if (rc == 0) {
LOG_VOL("filesystem '%s' had no errors\n", devpath);
} else if (rc == 1) {
LOG_VOL("filesystem '%s' had corrected errors\n", devpath);
rc = 0;
} else if (rc == 2) {
LOGE("VOL volume '%s' had corrected errors (system should be rebooted)\n", devpath);
rc = -EIO;
} else if (rc == 4) {
LOGE("VOL volume '%s' had uncorrectable errors\n", devpath);
rc = -EIO;
} else if (rc == 8) {
LOGE("Operational error while checking volume '%s'\n", devpath);
rc = -EIO;
} else {
LOGE("Unknown e2fsck exit code (%d)\n", rc);
rc = -EIO;
}
free(devpath);
return rc;
}
int ext3_mount(blkdev_t *dev, volume_t *vol)
int ext_mount(blkdev_t *dev, volume_t *vol, boolean safe_mode)
{
#if EXT3_DEBUG
LOG_VOL("ext3_mount(%s, %s):\n", dev->dev_fspath, vol->mount_point);
#if EXT_DEBUG
LOG_VOL("ext_mount(%s, %s, %d):\n", dev->dev_fspath, vol->mount_point, safe_mode);
#endif
return -ENOSYS;
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\n", 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\n",
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\n", 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)\n", vol->mount_point, strerror(errno));
return -errno;
}
return rc;
}

View File

@ -21,9 +21,7 @@
#include "volmgr.h"
#include "blkdev.h"
int ext3_identify(blkdev_t *blkdev);
int ext3_check(blkdev_t *blkdev);
int ext3_mount(blkdev_t *blkdev, volume_t *vol);
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

View File

@ -31,7 +31,7 @@ static char FSCK_MSDOS_PATH[] = "/system/bin/dosfsck";
int vfat_identify(blkdev_t *dev)
{
#if VFAT_DEBUG
LOG_VOL("vfat_identify(%s):\n", dev->dev_fspath);
LOG_VOL("vfat_identify(%d:%d):\n", dev->major, dev->minor);
#endif
return 0; // XXX: Implement
}
@ -41,12 +41,12 @@ int vfat_check(blkdev_t *dev)
int rc;
#if VFAT_DEBUG
LOG_VOL("vfat_check(%s):\n", dev->dev_fspath);
LOG_VOL("vfat_check(%d:%d):\n", dev->major, dev->minor);
#endif
if (access(FSCK_MSDOS_PATH, X_OK)) {
LOGE("vfat_check(%s): %s not found (skipping checks)\n",
FSCK_MSDOS_PATH, dev->dev_fspath);
LOGE("vfat_check(%d:%d): %s not found (skipping checks)\n",
dev->major, dev->minor, FSCK_MSDOS_PATH);
return 0;
}
@ -57,18 +57,20 @@ int vfat_check(blkdev_t *dev)
args[2] = "-V";
args[3] = "-w";
args[4] = "-p";
args[5] = dev->dev_fspath;
args[5] = blkdev_get_devpath(dev);
args[6] = NULL;
rc = logwrap(6, args);
free(args[5]);
#else
char *args[6];
args[0] = FSCK_MSDOS_PATH;
args[1] = "-v";
args[2] = "-w";
args[3] = "-p";
args[4] = dev->dev_fspath;
args[4] = blkdev_get_devpath(dev);
args[5] = NULL;
rc = logwrap(5, args);
free(args[4]);
#endif
if (rc == 0) {
@ -82,6 +84,9 @@ int vfat_check(blkdev_t *dev)
return -EIO;
} else if (rc == 4) {
LOG_VOL("Filesystem check completed (errors fixed)\n");
} else if (rc == 8) {
LOG_VOL("Filesystem check failed (not a FAT filesystem)\n");
return -ENODATA;
} else {
LOG_VOL("Filesystem check failed (unknown exit code %d)\n", rc);
return -EIO;
@ -89,29 +94,42 @@ int vfat_check(blkdev_t *dev)
return 0;
}
int vfat_mount(blkdev_t *dev, volume_t *vol)
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(%s, %s):\n", dev->dev_fspath, vol->mount_point);
LOG_VOL("vfat_mount(%d:%d, %s, %d):\n", dev->major, dev->minor, vol->mount_point, safe_mode);
#endif
flags = MS_NODEV | MS_NOEXEC | MS_NOSUID | MS_DIRSYNC;
rc = mount(dev->dev_fspath, vol->mount_point, "vfat", flags,
if (safe_mode)
flags |= MS_SYNCHRONOUS;
if (vol->state == volstate_mounted) {
LOG_VOL("Remounting %d:%d on %s, safe mode %d\n", dev->major,
dev->minor, vol->mount_point, safe_mode);
flags |= MS_REMOUNT;
}
rc = mount(devpath, vol->mount_point, "vfat", flags,
"utf8,uid=1000,gid=1000,fmask=711,dmask=700");
if (rc && errno == EROFS) {
LOGE("vfat_mount(%s, %s): Read only filesystem - retrying mount RO\n",
dev->dev_fspath, vol->mount_point);
LOGE("vfat_mount(%d:%d, %s): Read only filesystem - retrying mount RO\n",
dev->major, dev->minor, vol->mount_point);
flags |= MS_RDONLY;
rc = mount(dev->dev_fspath, vol->mount_point, "vfat", flags,
rc = mount(devpath, vol->mount_point, "vfat", flags,
"utf8,uid=1000,gid=1000,fmask=711,dmask=700");
}
#if VFAT_DEBUG
LOG_VOL("vfat_mount(%s, %s): mount rc = %d\n", dev->dev_fspath,
LOG_VOL("vfat_mount(%s, %d:%d): mount rc = %d\n", dev->major,k dev->minor,
vol->mount_point, rc);
#endif
free (devpath);
return rc;
}

View File

@ -25,5 +25,5 @@
int vfat_identify(blkdev_t *blkdev);
int vfat_check(blkdev_t *blkdev);
int vfat_mount(blkdev_t *blkdev, volume_t *vol);
int vfat_mount(blkdev_t *blkdev, volume_t *vol, boolean safe_mode);
#endif