• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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>
21 #include <sys/stat.h>
22 #include <sys/types.h>
23 
24 #include <fcntl.h>
25 #include <dirent.h>
26 #include <fs_mgr.h>
27 
28 #define LOG_TAG "Vold"
29 
30 #include "cutils/klog.h"
31 #include "cutils/log.h"
32 #include "cutils/properties.h"
33 
34 #include "VolumeManager.h"
35 #include "CommandListener.h"
36 #include "NetlinkManager.h"
37 #include "DirectVolume.h"
38 #include "cryptfs.h"
39 
40 static int process_config(VolumeManager *vm);
41 static void coldboot(const char *path);
42 
43 #define FSTAB_PREFIX "/fstab."
44 struct fstab *fstab;
45 
main()46 int main() {
47 
48     VolumeManager *vm;
49     CommandListener *cl;
50     NetlinkManager *nm;
51 
52     SLOGI("Vold 2.1 (the revenge) firing up");
53 
54     mkdir("/dev/block/vold", 0755);
55 
56     /* For when cryptfs checks and mounts an encrypted filesystem */
57     klog_set_level(6);
58 
59     /* Create our singleton managers */
60     if (!(vm = VolumeManager::Instance())) {
61         SLOGE("Unable to create VolumeManager");
62         exit(1);
63     };
64 
65     if (!(nm = NetlinkManager::Instance())) {
66         SLOGE("Unable to create NetlinkManager");
67         exit(1);
68     };
69 
70 
71     cl = new CommandListener();
72     vm->setBroadcaster((SocketListener *) cl);
73     nm->setBroadcaster((SocketListener *) cl);
74 
75     if (vm->start()) {
76         SLOGE("Unable to start VolumeManager (%s)", strerror(errno));
77         exit(1);
78     }
79 
80     if (process_config(vm)) {
81         SLOGE("Error reading configuration (%s)... continuing anyways", strerror(errno));
82     }
83 
84     if (nm->start()) {
85         SLOGE("Unable to start NetlinkManager (%s)", strerror(errno));
86         exit(1);
87     }
88 
89     coldboot("/sys/block");
90 //    coldboot("/sys/class/switch");
91 
92     /*
93      * Now that we're up, we can respond to commands
94      */
95     if (cl->startListener()) {
96         SLOGE("Unable to start CommandListener (%s)", strerror(errno));
97         exit(1);
98     }
99 
100     // Eventually we'll become the monitoring thread
101     while(1) {
102         sleep(1000);
103     }
104 
105     SLOGI("Vold exiting");
106     exit(0);
107 }
108 
do_coldboot(DIR * d,int lvl)109 static void do_coldboot(DIR *d, int lvl)
110 {
111     struct dirent *de;
112     int dfd, fd;
113 
114     dfd = dirfd(d);
115 
116     fd = openat(dfd, "uevent", O_WRONLY);
117     if(fd >= 0) {
118         write(fd, "add\n", 4);
119         close(fd);
120     }
121 
122     while((de = readdir(d))) {
123         DIR *d2;
124 
125         if (de->d_name[0] == '.')
126             continue;
127 
128         if (de->d_type != DT_DIR && lvl > 0)
129             continue;
130 
131         fd = openat(dfd, de->d_name, O_RDONLY | O_DIRECTORY);
132         if(fd < 0)
133             continue;
134 
135         d2 = fdopendir(fd);
136         if(d2 == 0)
137             close(fd);
138         else {
139             do_coldboot(d2, lvl + 1);
140             closedir(d2);
141         }
142     }
143 }
144 
coldboot(const char * path)145 static void coldboot(const char *path)
146 {
147     DIR *d = opendir(path);
148     if(d) {
149         do_coldboot(d, 0);
150         closedir(d);
151     }
152 }
153 
process_config(VolumeManager * vm)154 static int process_config(VolumeManager *vm)
155 {
156     char fstab_filename[PROPERTY_VALUE_MAX + sizeof(FSTAB_PREFIX)];
157     char propbuf[PROPERTY_VALUE_MAX];
158     int i;
159     int ret = -1;
160     int flags;
161 
162     property_get("ro.hardware", propbuf, "");
163     snprintf(fstab_filename, sizeof(fstab_filename), FSTAB_PREFIX"%s", propbuf);
164 
165     fstab = fs_mgr_read_fstab(fstab_filename);
166     if (!fstab) {
167         SLOGE("failed to open %s\n", fstab_filename);
168         return -1;
169     }
170 
171     /* Loop through entries looking for ones that vold manages */
172     for (i = 0; i < fstab->num_entries; i++) {
173         if (fs_mgr_is_voldmanaged(&fstab->recs[i])) {
174             DirectVolume *dv = NULL;
175             flags = 0;
176 
177             /* Set any flags that might be set for this volume */
178             if (fs_mgr_is_nonremovable(&fstab->recs[i])) {
179                 flags |= VOL_NONREMOVABLE;
180             }
181             if (fs_mgr_is_encryptable(&fstab->recs[i])) {
182                 flags |= VOL_ENCRYPTABLE;
183             }
184             /* Only set this flag if there is not an emulated sd card */
185             if (fs_mgr_is_noemulatedsd(&fstab->recs[i]) &&
186                 !strcmp(fstab->recs[i].fs_type, "vfat")) {
187                 flags |= VOL_PROVIDES_ASEC;
188             }
189             dv = new DirectVolume(vm, &(fstab->recs[i]), flags);
190 
191             if (dv->addPath(fstab->recs[i].blk_device)) {
192                 SLOGE("Failed to add devpath %s to volume %s",
193                       fstab->recs[i].blk_device, fstab->recs[i].label);
194                 goto out_fail;
195             }
196 
197             vm->addVolume(dv);
198         }
199     }
200 
201     ret = 0;
202 
203 out_fail:
204     return ret;
205 }
206