blob: 11b99a9bf3f3682997e879613953aed50848a737 [file] [log] [blame]
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001
2/*
3 * Copyright (C) 2008 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18#include <errno.h>
19#include <stdio.h>
20#include <stdlib.h>
21#include <unistd.h>
22#include <string.h>
23#include <fcntl.h>
24#include <pthread.h>
25
26#include <sys/socket.h>
27#include <sys/select.h>
28#include <sys/time.h>
29#include <sys/types.h>
30#include <sys/un.h>
31
32#include <cutils/config_utils.h>
33#include <cutils/cpu_info.h>
34#include <cutils/properties.h>
35#include <cutils/sockets.h>
36
37#include <linux/netlink.h>
38
39#include <private/android_filesystem_config.h>
40
41#include "vold.h"
42#include "volmgr.h"
43
44
45#define VOLD_SOCKET "vold"
46
47/*
48 * Globals
49 */
50
51static int ver_major = 2;
52static int ver_minor = 0;
53static pthread_mutex_t write_mutex = PTHREAD_MUTEX_INITIALIZER;
54static int fw_sock = -1;
55
San Mehat1f278212009-07-16 10:44:15 -070056int bootstrap = 0;
57
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080058int main(int argc, char **argv)
59{
60 int door_sock = -1;
61 int uevent_sock = -1;
62 struct sockaddr_nl nladdr;
63 int uevent_sz = 64 * 1024;
64
The Android Open Source Projecte037fd72009-03-13 13:04:37 -070065 LOGI("Android Volume Daemon version %d.%d", ver_major, ver_minor);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080066
67 /*
68 * Create all the various sockets we'll need
69 */
70
71 // Socket to listen on for incomming framework connections
72 if ((door_sock = android_get_control_socket(VOLD_SOCKET)) < 0) {
73 LOGE("Obtaining file descriptor socket '%s' failed: %s",
74 VOLD_SOCKET, strerror(errno));
75 exit(1);
76 }
77
78 if (listen(door_sock, 4) < 0) {
79 LOGE("Unable to listen on fd '%d' for socket '%s': %s",
80 door_sock, VOLD_SOCKET, strerror(errno));
81 exit(1);
82 }
83
84 mkdir("/dev/block/vold", 0755);
85
86 // Socket to listen on for uevent changes
87 memset(&nladdr, 0, sizeof(nladdr));
88 nladdr.nl_family = AF_NETLINK;
89 nladdr.nl_pid = getpid();
90 nladdr.nl_groups = 0xffffffff;
91
92 if ((uevent_sock = socket(PF_NETLINK,
93 SOCK_DGRAM,NETLINK_KOBJECT_UEVENT)) < 0) {
94 LOGE("Unable to create uevent socket: %s", strerror(errno));
95 exit(1);
96 }
97
98 if (setsockopt(uevent_sock, SOL_SOCKET, SO_RCVBUFFORCE, &uevent_sz,
99 sizeof(uevent_sz)) < 0) {
100 LOGE("Unable to set uevent socket options: %s", strerror(errno));
101 exit(1);
102 }
103
104 if (bind(uevent_sock, (struct sockaddr *) &nladdr, sizeof(nladdr)) < 0) {
105 LOGE("Unable to bind uevent socket: %s", strerror(errno));
106 exit(1);
107 }
108
109 /*
110 * Bootstrap
111 */
112
San Mehat1f278212009-07-16 10:44:15 -0700113 bootstrap = 1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800114 // Volume Manager
115 volmgr_bootstrap();
116
117 // SD Card system
118 mmc_bootstrap();
119
120 // USB Mass Storage
121 ums_bootstrap();
122
123 // Switch
124 switch_bootstrap();
125
San Mehat1f278212009-07-16 10:44:15 -0700126 bootstrap = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800127 /*
128 * Main loop
129 */
130 LOG_VOL("Bootstrapping complete");
131 while(1) {
132 fd_set read_fds;
133 struct timeval to;
134 int max = 0;
135 int rc = 0;
136
137 to.tv_sec = (60 * 60);
138 to.tv_usec = 0;
139
140 FD_ZERO(&read_fds);
141 FD_SET(door_sock, &read_fds);
142 if (door_sock > max)
143 max = door_sock;
144 FD_SET(uevent_sock, &read_fds);
145 if (uevent_sock > max)
146 max = uevent_sock;
147
148 if (fw_sock != -1) {
149 FD_SET(fw_sock, &read_fds);
150 if (fw_sock > max)
151 max = fw_sock;
152 }
153
154 if ((rc = select(max + 1, &read_fds, NULL, NULL, &to)) < 0) {
155 LOGE("select() failed (%s)", strerror(errno));
156 sleep(1);
157 continue;
158 }
159
160 if (!rc) {
161 continue;
162 }
163
164 if (FD_ISSET(door_sock, &read_fds)) {
165 struct sockaddr addr;
166 socklen_t alen;
167
168 alen = sizeof(addr);
169
170 if (fw_sock != -1) {
171 LOGE("Dropping duplicate framework connection");
172 int tmp = accept(door_sock, &addr, &alen);
173 close(tmp);
174 continue;
175 }
176
177 if ((fw_sock = accept(door_sock, &addr, &alen)) < 0) {
178 LOGE("Unable to accept framework connection (%s)",
179 strerror(errno));
180 }
181 LOG_VOL("Accepted connection from framework");
182 if ((rc = volmgr_send_states()) < 0) {
183 LOGE("Unable to send volmgr status to framework (%d)", rc);
184 }
185 }
186
187 if (FD_ISSET(fw_sock, &read_fds)) {
188 if ((rc = process_framework_command(fw_sock)) < 0) {
189 if (rc == -ECONNRESET) {
190 LOGE("Framework disconnected");
191 close(fw_sock);
192 fw_sock = -1;
193 } else {
194 LOGE("Error processing framework command (%s)",
195 strerror(errno));
196 }
197 }
198 }
199
200 if (FD_ISSET(uevent_sock, &read_fds)) {
201 if ((rc = process_uevent_message(uevent_sock)) < 0) {
202 LOGE("Error processing uevent msg (%s)", strerror(errno));
203 }
204 }
205 } // while
206
207}
208
209int send_msg(char* message)
210{
211 int result = -1;
212
213 pthread_mutex_lock(&write_mutex);
214
The Android Open Source Projecte037fd72009-03-13 13:04:37 -0700215// LOG_VOL("send_msg(%s):", message);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800216
217 if (fw_sock >= 0)
218 result = write(fw_sock, message, strlen(message) + 1);
219
220 pthread_mutex_unlock(&write_mutex);
221
222 return result;
223}
224
225int send_msg_with_data(char *message, char *data)
226{
227 int result = -1;
228
229 char* buffer = (char *)alloca(strlen(message) + strlen(data) + 1);
230 if (!buffer) {
231 LOGE("alloca failed in send_msg_with_data");
232 return -1;
233 }
234
235 strcpy(buffer, message);
236 strcat(buffer, data);
237 return send_msg(buffer);
238}