blob: b2c8eb28d6eccf71ac18692a98edf85e6cc7b0bd [file] [log] [blame]
The Android Open Source Project8ac3a132009-01-20 14:04:01 -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/inotify.h>
31#include <sys/un.h>
32
33#include <cutils/config_utils.h>
34#include <cutils/cpu_info.h>
35#include <cutils/properties.h>
36#include <cutils/sockets.h>
37
38#include <linux/netlink.h>
39
40#include <private/android_filesystem_config.h>
41
42#include "vold.h"
43#include "volmgr.h"
44
45
46#define VOLD_SOCKET "vold"
47
48/*
49 * Globals
50 */
51
52static int ver_major = 2;
53static int ver_minor = 0;
54static pthread_mutex_t write_mutex = PTHREAD_MUTEX_INITIALIZER;
55static int fw_sock = -1;
56
57int main(int argc, char **argv)
58{
59 int door_sock = -1;
60 int inotify_sock = -1;
61 int uevent_sock = -1;
62 struct sockaddr_nl nladdr;
63 int uevent_sz = 64 * 1024;
64
65 LOG_VOL("Android Volume Daemon version %d.%d\n", ver_major, ver_minor);
66
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\n",
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\n",
80 door_sock, VOLD_SOCKET, strerror(errno));
81 exit(1);
82 }
83
84 // Socket to listen on for changes to /dev/block
85 if ((inotify_sock = inotify_init()) < 0) {
86 LOGE("Unable to initialize inotify interface (%s)\n", strerror(errno));
87 exit(1);
88 }
89
90 fcntl(inotify_sock, F_SETFL, O_NONBLOCK | fcntl(inotify_sock, F_GETFL));
91
92 if (inotify_add_watch(inotify_sock, DEVPATH, IN_CREATE | IN_DELETE) < 0) {
93 LOGE("Unable to add inotify watch (%s)\n", strerror(errno));
94 exit(1);
95 }
96
97 // Socket to listen on for uevent changes
98 memset(&nladdr, 0, sizeof(nladdr));
99 nladdr.nl_family = AF_NETLINK;
100 nladdr.nl_pid = getpid();
101 nladdr.nl_groups = 0xffffffff;
102
103 if ((uevent_sock = socket(PF_NETLINK,
104 SOCK_DGRAM,NETLINK_KOBJECT_UEVENT)) < 0) {
105 LOGE("Unable to create uevent socket: %s\n", strerror(errno));
106 exit(1);
107 }
108
109 if (setsockopt(uevent_sock, SOL_SOCKET, SO_RCVBUFFORCE, &uevent_sz,
110 sizeof(uevent_sz)) < 0) {
111 LOGE("Unable to set uevent socket options: %s\n", strerror(errno));
112 exit(1);
113 }
114
115 if (bind(uevent_sock, (struct sockaddr *) &nladdr, sizeof(nladdr)) < 0) {
116 LOGE("Unable to bind uevent socket: %s\n", strerror(errno));
117 exit(1);
118 }
119
120 /*
121 * Bootstrap
122 */
123
124 // SD Card system
125 mmc_bootstrap();
126
127 // USB Mass Storage
128 ums_bootstrap();
129
130 // Volume Manager
131 volmgr_bootstrap();
132
133 // Block device system
134 inotify_bootstrap();
135
136 /*
137 * Main loop
138 */
139
140 while(1) {
141 fd_set read_fds;
142 struct timeval to;
143 int max = 0;
144 int rc = 0;
145
146 to.tv_sec = (60 * 60);
147 to.tv_usec = 0;
148
149 FD_SET(door_sock, &read_fds);
150 if (door_sock > max)
151 max = door_sock;
152 FD_SET(inotify_sock, &read_fds);
153 if (inotify_sock > max)
154 max = inotify_sock;
155 FD_SET(uevent_sock, &read_fds);
156 if (uevent_sock > max)
157 max = uevent_sock;
158
159 if (fw_sock != -1) {
160 FD_SET(fw_sock, &read_fds);
161 if (fw_sock > max)
162 max = fw_sock;
163 }
164
165 if ((rc = select(max + 1, &read_fds, NULL, NULL, &to)) < 0) {
166 LOGE("select() failed (%s)\n", strerror(errno));
167 sleep(1);
168 continue;
169 }
170
171 if (!rc) {
172 continue;
173 }
174
175 if (FD_ISSET(door_sock, &read_fds)) {
176 struct sockaddr addr;
177 socklen_t alen;
178
179 alen = sizeof(addr);
180
181 if ((fw_sock = accept(door_sock, &addr, &alen)) < 0) {
182 LOGE("Unable to accept framework connection (%s)\n",
183 strerror(errno));
184 }
185 LOG_VOL("Accepted connection from framework\n");
186 if ((rc = volmgr_send_states()) < 0) {
187 LOGE("Unable to send volmgr status to framework (%d)\n", rc);
188 }
189 }
190
191 if (FD_ISSET(fw_sock, &read_fds)) {
192 if ((rc = process_framework_command(fw_sock)) < 0) {
193 if (rc == -ECONNRESET) {
194 LOGE("Framework disconnected\n");
195 close(fw_sock);
196 fw_sock = -1;
197 } else {
198 LOGE("Error processing framework command (%s)\n",
199 strerror(errno));
200 }
201 }
202 }
203
204 if (FD_ISSET(inotify_sock, &read_fds)) {
205 if ((rc = process_inotify_event(inotify_sock)) < 0) {
206 LOGE("Error processing inotify msg (%s)\n", strerror(errno));
207 }
208 }
209
210 if (FD_ISSET(uevent_sock, &read_fds)) {
211 if ((rc = process_uevent_message(uevent_sock)) < 0) {
212 LOGE("Error processing uevent msg (%s)\n", strerror(errno));
213 }
214 }
215
216
217 } // while
218
219}
220
221int send_msg(char* message)
222{
223 int result = -1;
224
225 pthread_mutex_lock(&write_mutex);
226
227 LOG_VOL("send_msg(%s):\n", message);
228
229 if (fw_sock >= 0)
230 result = write(fw_sock, message, strlen(message) + 1);
231
232 pthread_mutex_unlock(&write_mutex);
233
234 return result;
235}
236
237int send_msg_with_data(char *message, char *data)
238{
239 int result = -1;
240
241 char* buffer = (char *)alloca(strlen(message) + strlen(data) + 1);
242 if (!buffer) {
243 LOGE("alloca failed in send_msg_with_data\n");
244 return -1;
245 }
246
247 strcpy(buffer, message);
248 strcat(buffer, data);
249 return send_msg(buffer);
250}