blob: 17331ac4e5d73bdf9a2010c3726efd4f0dd46d4b [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
56int main(int argc, char **argv)
57{
58 int door_sock = -1;
59 int uevent_sock = -1;
60 struct sockaddr_nl nladdr;
61 int uevent_sz = 64 * 1024;
62
63 LOG_VOL("Android Volume Daemon version %d.%d", ver_major, ver_minor);
64
65 /*
66 * Create all the various sockets we'll need
67 */
68
69 // Socket to listen on for incomming framework connections
70 if ((door_sock = android_get_control_socket(VOLD_SOCKET)) < 0) {
71 LOGE("Obtaining file descriptor socket '%s' failed: %s",
72 VOLD_SOCKET, strerror(errno));
73 exit(1);
74 }
75
76 if (listen(door_sock, 4) < 0) {
77 LOGE("Unable to listen on fd '%d' for socket '%s': %s",
78 door_sock, VOLD_SOCKET, strerror(errno));
79 exit(1);
80 }
81
82 mkdir("/dev/block/vold", 0755);
83
84 // Socket to listen on for uevent changes
85 memset(&nladdr, 0, sizeof(nladdr));
86 nladdr.nl_family = AF_NETLINK;
87 nladdr.nl_pid = getpid();
88 nladdr.nl_groups = 0xffffffff;
89
90 if ((uevent_sock = socket(PF_NETLINK,
91 SOCK_DGRAM,NETLINK_KOBJECT_UEVENT)) < 0) {
92 LOGE("Unable to create uevent socket: %s", strerror(errno));
93 exit(1);
94 }
95
96 if (setsockopt(uevent_sock, SOL_SOCKET, SO_RCVBUFFORCE, &uevent_sz,
97 sizeof(uevent_sz)) < 0) {
98 LOGE("Unable to set uevent socket options: %s", strerror(errno));
99 exit(1);
100 }
101
102 if (bind(uevent_sock, (struct sockaddr *) &nladdr, sizeof(nladdr)) < 0) {
103 LOGE("Unable to bind uevent socket: %s", strerror(errno));
104 exit(1);
105 }
106
107 /*
108 * Bootstrap
109 */
110
111 // Volume Manager
112 volmgr_bootstrap();
113
114 // SD Card system
115 mmc_bootstrap();
116
117 // USB Mass Storage
118 ums_bootstrap();
119
120 // Switch
121 switch_bootstrap();
122
123 /*
124 * Main loop
125 */
126 LOG_VOL("Bootstrapping complete");
127 while(1) {
128 fd_set read_fds;
129 struct timeval to;
130 int max = 0;
131 int rc = 0;
132
133 to.tv_sec = (60 * 60);
134 to.tv_usec = 0;
135
136 FD_ZERO(&read_fds);
137 FD_SET(door_sock, &read_fds);
138 if (door_sock > max)
139 max = door_sock;
140 FD_SET(uevent_sock, &read_fds);
141 if (uevent_sock > max)
142 max = uevent_sock;
143
144 if (fw_sock != -1) {
145 FD_SET(fw_sock, &read_fds);
146 if (fw_sock > max)
147 max = fw_sock;
148 }
149
150 if ((rc = select(max + 1, &read_fds, NULL, NULL, &to)) < 0) {
151 LOGE("select() failed (%s)", strerror(errno));
152 sleep(1);
153 continue;
154 }
155
156 if (!rc) {
157 continue;
158 }
159
160 if (FD_ISSET(door_sock, &read_fds)) {
161 struct sockaddr addr;
162 socklen_t alen;
163
164 alen = sizeof(addr);
165
166 if (fw_sock != -1) {
167 LOGE("Dropping duplicate framework connection");
168 int tmp = accept(door_sock, &addr, &alen);
169 close(tmp);
170 continue;
171 }
172
173 if ((fw_sock = accept(door_sock, &addr, &alen)) < 0) {
174 LOGE("Unable to accept framework connection (%s)",
175 strerror(errno));
176 }
177 LOG_VOL("Accepted connection from framework");
178 if ((rc = volmgr_send_states()) < 0) {
179 LOGE("Unable to send volmgr status to framework (%d)", rc);
180 }
181 }
182
183 if (FD_ISSET(fw_sock, &read_fds)) {
184 if ((rc = process_framework_command(fw_sock)) < 0) {
185 if (rc == -ECONNRESET) {
186 LOGE("Framework disconnected");
187 close(fw_sock);
188 fw_sock = -1;
189 } else {
190 LOGE("Error processing framework command (%s)",
191 strerror(errno));
192 }
193 }
194 }
195
196 if (FD_ISSET(uevent_sock, &read_fds)) {
197 if ((rc = process_uevent_message(uevent_sock)) < 0) {
198 LOGE("Error processing uevent msg (%s)", strerror(errno));
199 }
200 }
201 } // while
202
203}
204
205int send_msg(char* message)
206{
207 int result = -1;
208
209 pthread_mutex_lock(&write_mutex);
210
211 LOG_VOL("send_msg(%s):", message);
212
213 if (fw_sock >= 0)
214 result = write(fw_sock, message, strlen(message) + 1);
215
216 pthread_mutex_unlock(&write_mutex);
217
218 return result;
219}
220
221int send_msg_with_data(char *message, char *data)
222{
223 int result = -1;
224
225 char* buffer = (char *)alloca(strlen(message) + strlen(data) + 1);
226 if (!buffer) {
227 LOGE("alloca failed in send_msg_with_data");
228 return -1;
229 }
230
231 strcpy(buffer, message);
232 strcat(buffer, data);
233 return send_msg(buffer);
234}