blob: ba8c33d3604c14c424b2930dc42de58f8f5169be [file] [log] [blame]
San Mehatf1b736b2009-10-10 17:22:08 -07001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <stdio.h>
18#include <stdlib.h>
19#include <errno.h>
20#include <string.h>
San Mehat3578c412009-10-12 14:51:52 -070021#include <sys/stat.h>
22#include <sys/types.h>
23
24#include <fcntl.h>
25#include <dirent.h>
San Mehatf1b736b2009-10-10 17:22:08 -070026
27#define LOG_TAG "Vold"
28
29#include "cutils/log.h"
30
31#include "VolumeManager.h"
32#include "CommandListener.h"
33#include "NetlinkManager.h"
34#include "DeviceVolume.h"
35
36static int process_config(VolumeManager *vm);
San Mehat3578c412009-10-12 14:51:52 -070037static void coldboot(const char *path);
San Mehatf1b736b2009-10-10 17:22:08 -070038
39int main() {
40
41 VolumeManager *vm;
42 CommandListener *cl;
43 NetlinkManager *nm;
44
45 LOGI("Vold 2.0 firing up");
46
47 /* Create our singleton managers */
48 if (!(vm = VolumeManager::Instance())) {
49 LOGE("Unable to create VolumeManager");
50 exit(1);
51 };
52
53 if (!(nm = NetlinkManager::Instance())) {
54 LOGE("Unable to create NetlinkManager");
55 exit(1);
56 };
57
58 cl = new CommandListener();
59 vm->setBroadcaster((SocketListener *) cl);
60 nm->setBroadcaster((SocketListener *) cl);
61
62 if (vm->start()) {
63 LOGE("Unable to start VolumeManager (%s)", strerror(errno));
64 exit(1);
65 }
66
67 if (process_config(vm)) {
68 LOGE("Error reading configuration (%s)", strerror(errno));
69 exit(1);
70 }
71
72 if (nm->start()) {
73 LOGE("Unable to start NetlinkManager (%s)", strerror(errno));
74 exit(1);
75 }
76
San Mehat3578c412009-10-12 14:51:52 -070077 coldboot("/sys/block");
78
San Mehatf1b736b2009-10-10 17:22:08 -070079 /*
80 * Now that we're up, we can respond to commands
81 */
82 if (cl->startListener()) {
83 LOGE("Unable to start CommandListener (%s)", strerror(errno));
84 exit(1);
85 }
86
87 // Eventually we'll become the monitoring thread
88 while(1) {
89 sleep(1000);
90 }
91
92 LOGI("Vold exiting");
93 exit(0);
94}
95
San Mehat3578c412009-10-12 14:51:52 -070096static void do_coldboot(DIR *d, int lvl)
97{
98 struct dirent *de;
99 int dfd, fd;
100
101 dfd = dirfd(d);
102
103 fd = openat(dfd, "uevent", O_WRONLY);
104 if(fd >= 0) {
105 write(fd, "add\n", 4);
106 close(fd);
107 }
108
109 while((de = readdir(d))) {
110 DIR *d2;
111
112 if (de->d_name[0] == '.')
113 continue;
114
115 if (de->d_type != DT_DIR && lvl > 0)
116 continue;
117
118 fd = openat(dfd, de->d_name, O_RDONLY | O_DIRECTORY);
119 if(fd < 0)
120 continue;
121
122 d2 = fdopendir(fd);
123 if(d2 == 0)
124 close(fd);
125 else {
126 do_coldboot(d2, lvl + 1);
127 closedir(d2);
128 }
129 }
130}
131
132static void coldboot(const char *path)
133{
134 DIR *d = opendir(path);
135 if(d) {
136 do_coldboot(d, 0);
137 closedir(d);
138 }
139}
140
San Mehatf1b736b2009-10-10 17:22:08 -0700141static int process_config(VolumeManager *vm) {
142 FILE *fp;
143 int n = 0;
144 char line[255];
145
146 if (!(fp = fopen("/etc/vold.fstab", "r"))) {
147 return -1;
148 }
149
150 while(fgets(line, sizeof(line), fp)) {
151 char *next = line;
152 char *type, *label, *mount_point;
153
154 n++;
155 line[strlen(line)-1] = '\0';
156
157 if (line[0] == '#' || line[0] == '\0')
158 continue;
159
160 if (!(type = strsep(&next, " \t"))) {
161 LOGE("Error parsing type");
162 goto out_syntax;
163 }
164 if (!(label = strsep(&next, " \t"))) {
165 LOGE("Error parsing label");
166 goto out_syntax;
167 }
168 if (!(mount_point = strsep(&next, " \t"))) {
169 LOGE("Error parsing mount point");
170 goto out_syntax;
171 }
172
173 if (!strcmp(type, "dev_mount")) {
174 DeviceVolume *dv = NULL;
175 char *part, *sysfs_path;
176
177 if (!(part = strsep(&next, " \t"))) {
178 LOGE("Error parsing partition");
179 goto out_syntax;
180 }
181 if (strcmp(part, "auto") && atoi(part) == 0) {
182 LOGE("Partition must either be 'auto' or 1 based index instead of '%s'", part);
183 goto out_syntax;
184 }
185
186 dv = new DeviceVolume(label, mount_point, atoi(part));
187
188 while((sysfs_path = strsep(&next, " \t"))) {
189 if (dv->addPath(sysfs_path)) {
190 LOGE("Failed to add devpath %s to volume %s", sysfs_path,
191 label);
192 goto out_fail;
193 }
194 }
195 vm->addVolume(dv);
196 } else if (!strcmp(type, "map_mount")) {
197 } else {
198 LOGE("Unknown type '%s'", type);
199 goto out_syntax;
200 }
201 }
202
203 fclose(fp);
204 return 0;
205
206out_syntax:
207 LOGE("Syntax error on config line %d", n);
208 errno = -EINVAL;
209out_fail:
210 fclose(fp);
211 return -1;
212}