diff options
Diffstat (limited to 'vold/vold.c')
| -rw-r--r-- | vold/vold.c | 234 |
1 files changed, 234 insertions, 0 deletions
diff --git a/vold/vold.c b/vold/vold.c new file mode 100644 index 000000000..17331ac4e --- /dev/null +++ b/vold/vold.c @@ -0,0 +1,234 @@ + +/* + * 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 main(int argc, char **argv) +{ + int door_sock = -1; + int uevent_sock = -1; + struct sockaddr_nl nladdr; + int uevent_sz = 64 * 1024; + + LOG_VOL("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 + */ + + // Volume Manager + volmgr_bootstrap(); + + // SD Card system + mmc_bootstrap(); + + // USB Mass Storage + ums_bootstrap(); + + // Switch + switch_bootstrap(); + + /* + * 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); +} |
