blob: 0f04a06412649195ccf4d23afc373d28ceb66261 [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>
San Mehatfd7f5872009-10-12 11:32:47 -070018#include <stdlib.h>
19#include <string.h>
San Mehatf1b736b2009-10-10 17:22:08 -070020#include <errno.h>
San Mehata2677e42009-12-13 10:40:18 -080021#include <fcntl.h>
San Mehata19b2502010-01-06 10:33:53 -080022#include <sys/stat.h>
23#include <sys/types.h>
24#include <sys/mount.h>
25
San Mehata2677e42009-12-13 10:40:18 -080026#include <linux/kdev_t.h>
San Mehatf1b736b2009-10-10 17:22:08 -070027
28#define LOG_TAG "Vold"
29
Kenny Root7b18a7b2010-03-15 13:13:41 -070030#include <openssl/md5.h>
31
San Mehatf1b736b2009-10-10 17:22:08 -070032#include <cutils/log.h>
33
San Mehatfd7f5872009-10-12 11:32:47 -070034#include <sysutils/NetlinkEvent.h>
35
San Mehatf1b736b2009-10-10 17:22:08 -070036#include "VolumeManager.h"
San Mehatae10b912009-10-12 14:57:05 -070037#include "DirectVolume.h"
San Mehata2677e42009-12-13 10:40:18 -080038#include "ResponseCode.h"
San Mehata19b2502010-01-06 10:33:53 -080039#include "Loop.h"
40#include "Fat.h"
San Mehatb78a32c2010-01-10 13:02:12 -080041#include "Devmapper.h"
San Mehat586536c2010-02-16 17:12:00 -080042#include "Process.h"
San Mehatfcf24fe2010-03-03 12:37:32 -080043#include "Asec.h"
Ken Sumrall29d8da82011-05-18 17:20:07 -070044#include "cryptfs.h"
San Mehat23969932010-01-09 07:08:06 -080045
Mike Lockwood97f2fc12011-06-07 10:51:38 -070046#define MASS_STORAGE_FILE_PATH "/sys/class/android_usb/android0/f_mass_storage/lun/file"
47
San Mehatf1b736b2009-10-10 17:22:08 -070048VolumeManager *VolumeManager::sInstance = NULL;
49
50VolumeManager *VolumeManager::Instance() {
51 if (!sInstance)
52 sInstance = new VolumeManager();
53 return sInstance;
54}
55
56VolumeManager::VolumeManager() {
San Mehatd9a4e352010-03-12 13:32:47 -080057 mDebug = false;
San Mehatf1b736b2009-10-10 17:22:08 -070058 mVolumes = new VolumeCollection();
San Mehat88705162010-01-15 09:26:28 -080059 mActiveContainers = new AsecIdCollection();
San Mehatf1b736b2009-10-10 17:22:08 -070060 mBroadcaster = NULL;
Mike Lockwooda28056b2010-10-28 15:21:24 -040061 mUmsSharingCount = 0;
62 mSavedDirtyRatio = -1;
63 // set dirty ratio to 0 when UMS is active
64 mUmsDirtyRatio = 0;
Ken Sumrall3b170052011-07-11 15:38:57 -070065 mVolManagerDisabled = 0;
San Mehatf1b736b2009-10-10 17:22:08 -070066}
67
68VolumeManager::~VolumeManager() {
San Mehat88705162010-01-15 09:26:28 -080069 delete mVolumes;
70 delete mActiveContainers;
San Mehatf1b736b2009-10-10 17:22:08 -070071}
72
Kenny Root7b18a7b2010-03-15 13:13:41 -070073char *VolumeManager::asecHash(const char *id, char *buffer, size_t len) {
Kenny Rootacc9e7d2010-06-18 19:06:50 -070074 static const char* digits = "0123456789abcdef";
75
Kenny Root7b18a7b2010-03-15 13:13:41 -070076 unsigned char sig[MD5_DIGEST_LENGTH];
77
Kenny Rootacc9e7d2010-06-18 19:06:50 -070078 if (buffer == NULL) {
79 SLOGE("Destination buffer is NULL");
80 errno = ESPIPE;
81 return NULL;
82 } else if (id == NULL) {
83 SLOGE("Source buffer is NULL");
84 errno = ESPIPE;
85 return NULL;
86 } else if (len < MD5_ASCII_LENGTH_PLUS_NULL) {
87 SLOGE("Target hash buffer size < %d bytes (%d)",
88 MD5_ASCII_LENGTH_PLUS_NULL, len);
San Mehatd9a4e352010-03-12 13:32:47 -080089 errno = ESPIPE;
90 return NULL;
91 }
Kenny Root7b18a7b2010-03-15 13:13:41 -070092
93 MD5(reinterpret_cast<const unsigned char*>(id), strlen(id), sig);
San Mehatd9a4e352010-03-12 13:32:47 -080094
Kenny Rootacc9e7d2010-06-18 19:06:50 -070095 char *p = buffer;
Kenny Root7b18a7b2010-03-15 13:13:41 -070096 for (int i = 0; i < MD5_DIGEST_LENGTH; i++) {
Kenny Rootacc9e7d2010-06-18 19:06:50 -070097 *p++ = digits[sig[i] >> 4];
98 *p++ = digits[sig[i] & 0x0F];
San Mehatd9a4e352010-03-12 13:32:47 -080099 }
Kenny Rootacc9e7d2010-06-18 19:06:50 -0700100 *p = '\0';
San Mehatd9a4e352010-03-12 13:32:47 -0800101
102 return buffer;
103}
104
105void VolumeManager::setDebug(bool enable) {
106 mDebug = enable;
107 VolumeCollection::iterator it;
108 for (it = mVolumes->begin(); it != mVolumes->end(); ++it) {
109 (*it)->setDebug(enable);
110 }
111}
112
San Mehatf1b736b2009-10-10 17:22:08 -0700113int VolumeManager::start() {
114 return 0;
115}
116
117int VolumeManager::stop() {
118 return 0;
119}
120
121int VolumeManager::addVolume(Volume *v) {
122 mVolumes->push_back(v);
123 return 0;
124}
125
San Mehatfd7f5872009-10-12 11:32:47 -0700126void VolumeManager::handleBlockEvent(NetlinkEvent *evt) {
127 const char *devpath = evt->findParam("DEVPATH");
San Mehatf1b736b2009-10-10 17:22:08 -0700128
San Mehatfd7f5872009-10-12 11:32:47 -0700129 /* Lookup a volume to handle this device */
San Mehatf1b736b2009-10-10 17:22:08 -0700130 VolumeCollection::iterator it;
131 bool hit = false;
132 for (it = mVolumes->begin(); it != mVolumes->end(); ++it) {
San Mehatfd7f5872009-10-12 11:32:47 -0700133 if (!(*it)->handleBlockEvent(evt)) {
San Mehata2677e42009-12-13 10:40:18 -0800134#ifdef NETLINK_DEBUG
San Mehat97ac40e2010-03-24 10:24:19 -0700135 SLOGD("Device '%s' event handled by volume %s\n", devpath, (*it)->getLabel());
San Mehata2677e42009-12-13 10:40:18 -0800136#endif
San Mehatf1b736b2009-10-10 17:22:08 -0700137 hit = true;
San Mehatf1b736b2009-10-10 17:22:08 -0700138 break;
139 }
140 }
141
142 if (!hit) {
San Mehata2677e42009-12-13 10:40:18 -0800143#ifdef NETLINK_DEBUG
San Mehat97ac40e2010-03-24 10:24:19 -0700144 SLOGW("No volumes handled block event for '%s'", devpath);
San Mehata2677e42009-12-13 10:40:18 -0800145#endif
San Mehatf1b736b2009-10-10 17:22:08 -0700146 }
147}
148
San Mehatf1b736b2009-10-10 17:22:08 -0700149int VolumeManager::listVolumes(SocketClient *cli) {
150 VolumeCollection::iterator i;
151
152 for (i = mVolumes->begin(); i != mVolumes->end(); ++i) {
153 char *buffer;
154 asprintf(&buffer, "%s %s %d",
155 (*i)->getLabel(), (*i)->getMountpoint(),
156 (*i)->getState());
San Mehata2677e42009-12-13 10:40:18 -0800157 cli->sendMsg(ResponseCode::VolumeListResult, buffer, false);
San Mehatf1b736b2009-10-10 17:22:08 -0700158 free(buffer);
159 }
San Mehata2677e42009-12-13 10:40:18 -0800160 cli->sendMsg(ResponseCode::CommandOkay, "Volumes listed.", false);
San Mehatf1b736b2009-10-10 17:22:08 -0700161 return 0;
162}
San Mehat49e2bce2009-10-12 16:29:01 -0700163
San Mehata2677e42009-12-13 10:40:18 -0800164int VolumeManager::formatVolume(const char *label) {
165 Volume *v = lookupVolume(label);
166
167 if (!v) {
168 errno = ENOENT;
169 return -1;
170 }
171
Ken Sumrall3b170052011-07-11 15:38:57 -0700172 if (mVolManagerDisabled) {
173 errno = EBUSY;
174 return -1;
175 }
176
San Mehata2677e42009-12-13 10:40:18 -0800177 return v->formatVol();
178}
179
Kenny Root508c0e12010-07-12 09:59:49 -0700180int VolumeManager::getObbMountPath(const char *sourceFile, char *mountPath, int mountPathLen) {
181 char idHash[33];
182 if (!asecHash(sourceFile, idHash, sizeof(idHash))) {
183 SLOGE("Hash of '%s' failed (%s)", sourceFile, strerror(errno));
184 return -1;
185 }
186
187 memset(mountPath, 0, mountPathLen);
188 snprintf(mountPath, mountPathLen, "%s/%s", Volume::LOOPDIR, idHash);
189
190 if (access(mountPath, F_OK)) {
191 errno = ENOENT;
192 return -1;
193 }
194
195 return 0;
196}
197
San Mehata19b2502010-01-06 10:33:53 -0800198int VolumeManager::getAsecMountPath(const char *id, char *buffer, int maxlen) {
San Mehat88ac2c02010-03-23 11:15:58 -0700199 char asecFileName[255];
200 snprintf(asecFileName, sizeof(asecFileName), "%s/%s.asec", Volume::SEC_ASECDIR, id);
201
202 memset(buffer, 0, maxlen);
203 if (access(asecFileName, F_OK)) {
204 errno = ENOENT;
205 return -1;
206 }
San Mehata19b2502010-01-06 10:33:53 -0800207
San Mehat3bb60202010-02-19 18:14:36 -0800208 snprintf(buffer, maxlen, "%s/%s", Volume::ASECDIR, id);
San Mehata19b2502010-01-06 10:33:53 -0800209 return 0;
210}
211
Dianne Hackborn736910c2011-06-27 13:37:07 -0700212int VolumeManager::getAsecFilesystemPath(const char *id, char *buffer, int maxlen) {
213 char asecFileName[255];
214 snprintf(asecFileName, sizeof(asecFileName), "%s/%s.asec", Volume::SEC_ASECDIR, id);
215
216 memset(buffer, 0, maxlen);
217 if (access(asecFileName, F_OK)) {
218 errno = ENOENT;
219 return -1;
220 }
221
222 snprintf(buffer, maxlen, "%s", asecFileName);
223 return 0;
224}
225
San Mehat8b8f71b2010-01-11 09:17:25 -0800226int VolumeManager::createAsec(const char *id, unsigned int numSectors,
San Mehata19b2502010-01-06 10:33:53 -0800227 const char *fstype, const char *key, int ownerUid) {
San Mehatfcf24fe2010-03-03 12:37:32 -0800228 struct asec_superblock sb;
229 memset(&sb, 0, sizeof(sb));
230
231 sb.magic = ASEC_SB_MAGIC;
232 sb.ver = ASEC_SB_VER;
San Mehata19b2502010-01-06 10:33:53 -0800233
San Mehatd31e3802010-02-18 08:37:45 -0800234 if (numSectors < ((1024*1024)/512)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700235 SLOGE("Invalid container size specified (%d sectors)", numSectors);
San Mehatd31e3802010-02-18 08:37:45 -0800236 errno = EINVAL;
237 return -1;
238 }
239
San Mehata19b2502010-01-06 10:33:53 -0800240 if (lookupVolume(id)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700241 SLOGE("ASEC id '%s' currently exists", id);
San Mehata19b2502010-01-06 10:33:53 -0800242 errno = EADDRINUSE;
243 return -1;
244 }
245
246 char asecFileName[255];
San Mehat3bb60202010-02-19 18:14:36 -0800247 snprintf(asecFileName, sizeof(asecFileName), "%s/%s.asec", Volume::SEC_ASECDIR, id);
San Mehata19b2502010-01-06 10:33:53 -0800248
249 if (!access(asecFileName, F_OK)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700250 SLOGE("ASEC file '%s' currently exists - destroy it first! (%s)",
San Mehata19b2502010-01-06 10:33:53 -0800251 asecFileName, strerror(errno));
252 errno = EADDRINUSE;
253 return -1;
254 }
255
San Mehatfcf24fe2010-03-03 12:37:32 -0800256 /*
257 * Add some headroom
258 */
259 unsigned fatSize = (((numSectors * 4) / 512) + 1) * 2;
260 unsigned numImgSectors = numSectors + fatSize + 2;
261
262 if (numImgSectors % 63) {
263 numImgSectors += (63 - (numImgSectors % 63));
264 }
265
266 // Add +1 for our superblock which is at the end
267 if (Loop::createImageFile(asecFileName, numImgSectors + 1)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700268 SLOGE("ASEC image file creation failed (%s)", strerror(errno));
San Mehata19b2502010-01-06 10:33:53 -0800269 return -1;
270 }
271
San Mehatd9a4e352010-03-12 13:32:47 -0800272 char idHash[33];
273 if (!asecHash(id, idHash, sizeof(idHash))) {
San Mehat97ac40e2010-03-24 10:24:19 -0700274 SLOGE("Hash of '%s' failed (%s)", id, strerror(errno));
San Mehatd9a4e352010-03-12 13:32:47 -0800275 unlink(asecFileName);
276 return -1;
277 }
278
San Mehata19b2502010-01-06 10:33:53 -0800279 char loopDevice[255];
San Mehatd9a4e352010-03-12 13:32:47 -0800280 if (Loop::create(idHash, asecFileName, loopDevice, sizeof(loopDevice))) {
San Mehat97ac40e2010-03-24 10:24:19 -0700281 SLOGE("ASEC loop device creation failed (%s)", strerror(errno));
San Mehata19b2502010-01-06 10:33:53 -0800282 unlink(asecFileName);
283 return -1;
284 }
285
San Mehatb78a32c2010-01-10 13:02:12 -0800286 char dmDevice[255];
287 bool cleanupDm = false;
San Mehata19b2502010-01-06 10:33:53 -0800288
San Mehatb78a32c2010-01-10 13:02:12 -0800289 if (strcmp(key, "none")) {
San Mehatfcf24fe2010-03-03 12:37:32 -0800290 // XXX: This is all we support for now
291 sb.c_cipher = ASEC_SB_C_CIPHER_TWOFISH;
San Mehatd9a4e352010-03-12 13:32:47 -0800292 if (Devmapper::create(idHash, loopDevice, key, numImgSectors, dmDevice,
San Mehatb78a32c2010-01-10 13:02:12 -0800293 sizeof(dmDevice))) {
San Mehat97ac40e2010-03-24 10:24:19 -0700294 SLOGE("ASEC device mapping failed (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800295 Loop::destroyByDevice(loopDevice);
296 unlink(asecFileName);
297 return -1;
298 }
299 cleanupDm = true;
300 } else {
San Mehatfcf24fe2010-03-03 12:37:32 -0800301 sb.c_cipher = ASEC_SB_C_CIPHER_NONE;
San Mehatb78a32c2010-01-10 13:02:12 -0800302 strcpy(dmDevice, loopDevice);
303 }
304
San Mehatfcf24fe2010-03-03 12:37:32 -0800305 /*
306 * Drop down the superblock at the end of the file
307 */
308
309 int sbfd = open(loopDevice, O_RDWR);
310 if (sbfd < 0) {
San Mehat97ac40e2010-03-24 10:24:19 -0700311 SLOGE("Failed to open new DM device for superblock write (%s)", strerror(errno));
San Mehatfcf24fe2010-03-03 12:37:32 -0800312 if (cleanupDm) {
San Mehatd9a4e352010-03-12 13:32:47 -0800313 Devmapper::destroy(idHash);
San Mehatfcf24fe2010-03-03 12:37:32 -0800314 }
315 Loop::destroyByDevice(loopDevice);
316 unlink(asecFileName);
317 return -1;
318 }
319
320 if (lseek(sbfd, (numImgSectors * 512), SEEK_SET) < 0) {
321 close(sbfd);
San Mehat97ac40e2010-03-24 10:24:19 -0700322 SLOGE("Failed to lseek for superblock (%s)", strerror(errno));
San Mehatfcf24fe2010-03-03 12:37:32 -0800323 if (cleanupDm) {
San Mehatd9a4e352010-03-12 13:32:47 -0800324 Devmapper::destroy(idHash);
San Mehatfcf24fe2010-03-03 12:37:32 -0800325 }
326 Loop::destroyByDevice(loopDevice);
327 unlink(asecFileName);
328 return -1;
329 }
330
331 if (write(sbfd, &sb, sizeof(sb)) != sizeof(sb)) {
332 close(sbfd);
San Mehat97ac40e2010-03-24 10:24:19 -0700333 SLOGE("Failed to write superblock (%s)", strerror(errno));
San Mehatfcf24fe2010-03-03 12:37:32 -0800334 if (cleanupDm) {
San Mehatd9a4e352010-03-12 13:32:47 -0800335 Devmapper::destroy(idHash);
San Mehatfcf24fe2010-03-03 12:37:32 -0800336 }
337 Loop::destroyByDevice(loopDevice);
338 unlink(asecFileName);
339 return -1;
340 }
341 close(sbfd);
342
San Mehata1091cb2010-02-28 20:17:20 -0800343 if (strcmp(fstype, "none")) {
344 if (strcmp(fstype, "fat")) {
San Mehat97ac40e2010-03-24 10:24:19 -0700345 SLOGW("Unknown fstype '%s' specified for container", fstype);
San Mehatb78a32c2010-01-10 13:02:12 -0800346 }
San Mehata19b2502010-01-06 10:33:53 -0800347
San Mehatfcf24fe2010-03-03 12:37:32 -0800348 if (Fat::format(dmDevice, numImgSectors)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700349 SLOGE("ASEC FAT format failed (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800350 if (cleanupDm) {
San Mehatd9a4e352010-03-12 13:32:47 -0800351 Devmapper::destroy(idHash);
San Mehatb78a32c2010-01-10 13:02:12 -0800352 }
San Mehateb13a902010-01-07 12:12:50 -0800353 Loop::destroyByDevice(loopDevice);
354 unlink(asecFileName);
355 return -1;
356 }
San Mehata1091cb2010-02-28 20:17:20 -0800357 char mountPoint[255];
San Mehata19b2502010-01-06 10:33:53 -0800358
San Mehata1091cb2010-02-28 20:17:20 -0800359 snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id);
360 if (mkdir(mountPoint, 0777)) {
361 if (errno != EEXIST) {
San Mehat97ac40e2010-03-24 10:24:19 -0700362 SLOGE("Mountpoint creation failed (%s)", strerror(errno));
San Mehata1091cb2010-02-28 20:17:20 -0800363 if (cleanupDm) {
San Mehatd9a4e352010-03-12 13:32:47 -0800364 Devmapper::destroy(idHash);
San Mehata1091cb2010-02-28 20:17:20 -0800365 }
366 Loop::destroyByDevice(loopDevice);
367 unlink(asecFileName);
368 return -1;
369 }
San Mehatb78a32c2010-01-10 13:02:12 -0800370 }
San Mehata1091cb2010-02-28 20:17:20 -0800371
Kenny Roota3e06082010-08-27 08:31:35 -0700372 if (Fat::doMount(dmDevice, mountPoint, false, false, false, ownerUid,
San Mehata1091cb2010-02-28 20:17:20 -0800373 0, 0000, false)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700374 SLOGE("ASEC FAT mount failed (%s)", strerror(errno));
San Mehata1091cb2010-02-28 20:17:20 -0800375 if (cleanupDm) {
San Mehatd9a4e352010-03-12 13:32:47 -0800376 Devmapper::destroy(idHash);
San Mehata1091cb2010-02-28 20:17:20 -0800377 }
378 Loop::destroyByDevice(loopDevice);
379 unlink(asecFileName);
380 return -1;
381 }
382 } else {
San Mehat97ac40e2010-03-24 10:24:19 -0700383 SLOGI("Created raw secure container %s (no filesystem)", id);
San Mehata19b2502010-01-06 10:33:53 -0800384 }
San Mehat88705162010-01-15 09:26:28 -0800385
Kenny Rootcbacf782010-09-24 15:11:48 -0700386 mActiveContainers->push_back(new ContainerData(strdup(id), ASEC));
San Mehata19b2502010-01-06 10:33:53 -0800387 return 0;
388}
389
390int VolumeManager::finalizeAsec(const char *id) {
391 char asecFileName[255];
392 char loopDevice[255];
393 char mountPoint[255];
394
San Mehat3bb60202010-02-19 18:14:36 -0800395 snprintf(asecFileName, sizeof(asecFileName), "%s/%s.asec", Volume::SEC_ASECDIR, id);
San Mehata19b2502010-01-06 10:33:53 -0800396
San Mehatd9a4e352010-03-12 13:32:47 -0800397 char idHash[33];
398 if (!asecHash(id, idHash, sizeof(idHash))) {
San Mehat97ac40e2010-03-24 10:24:19 -0700399 SLOGE("Hash of '%s' failed (%s)", id, strerror(errno));
San Mehatd9a4e352010-03-12 13:32:47 -0800400 return -1;
401 }
402
403 if (Loop::lookupActive(idHash, loopDevice, sizeof(loopDevice))) {
San Mehat97ac40e2010-03-24 10:24:19 -0700404 SLOGE("Unable to finalize %s (%s)", id, strerror(errno));
San Mehata19b2502010-01-06 10:33:53 -0800405 return -1;
406 }
407
San Mehat3bb60202010-02-19 18:14:36 -0800408 snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id);
San Mehatfff0b472010-01-06 19:19:46 -0800409 // XXX:
Kenny Roota3e06082010-08-27 08:31:35 -0700410 if (Fat::doMount(loopDevice, mountPoint, true, true, true, 0, 0, 0227, false)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700411 SLOGE("ASEC finalize mount failed (%s)", strerror(errno));
San Mehata19b2502010-01-06 10:33:53 -0800412 return -1;
413 }
414
San Mehatd9a4e352010-03-12 13:32:47 -0800415 if (mDebug) {
San Mehat97ac40e2010-03-24 10:24:19 -0700416 SLOGD("ASEC %s finalized", id);
San Mehatd9a4e352010-03-12 13:32:47 -0800417 }
San Mehata19b2502010-01-06 10:33:53 -0800418 return 0;
419}
420
San Mehat048b0802010-01-23 08:17:06 -0800421int VolumeManager::renameAsec(const char *id1, const char *id2) {
422 char *asecFilename1;
423 char *asecFilename2;
424 char mountPoint[255];
425
San Mehat3bb60202010-02-19 18:14:36 -0800426 asprintf(&asecFilename1, "%s/%s.asec", Volume::SEC_ASECDIR, id1);
427 asprintf(&asecFilename2, "%s/%s.asec", Volume::SEC_ASECDIR, id2);
San Mehat048b0802010-01-23 08:17:06 -0800428
San Mehat3bb60202010-02-19 18:14:36 -0800429 snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id1);
San Mehat048b0802010-01-23 08:17:06 -0800430 if (isMountpointMounted(mountPoint)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700431 SLOGW("Rename attempt when src mounted");
San Mehat048b0802010-01-23 08:17:06 -0800432 errno = EBUSY;
433 goto out_err;
434 }
435
San Mehat96956ed2010-02-24 08:42:51 -0800436 snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id2);
437 if (isMountpointMounted(mountPoint)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700438 SLOGW("Rename attempt when dst mounted");
San Mehat96956ed2010-02-24 08:42:51 -0800439 errno = EBUSY;
440 goto out_err;
441 }
442
San Mehat048b0802010-01-23 08:17:06 -0800443 if (!access(asecFilename2, F_OK)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700444 SLOGE("Rename attempt when dst exists");
San Mehat048b0802010-01-23 08:17:06 -0800445 errno = EADDRINUSE;
446 goto out_err;
447 }
448
449 if (rename(asecFilename1, asecFilename2)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700450 SLOGE("Rename of '%s' to '%s' failed (%s)", asecFilename1, asecFilename2, strerror(errno));
San Mehat048b0802010-01-23 08:17:06 -0800451 goto out_err;
452 }
453
454 free(asecFilename1);
455 free(asecFilename2);
456 return 0;
457
458out_err:
459 free(asecFilename1);
460 free(asecFilename2);
461 return -1;
462}
463
Kenny Rootfb7c4d52010-06-30 18:48:41 -0700464#define UNMOUNT_RETRIES 5
465#define UNMOUNT_SLEEP_BETWEEN_RETRY_MS (1000 * 1000)
San Mehat4ba89482010-02-18 09:00:18 -0800466int VolumeManager::unmountAsec(const char *id, bool force) {
San Mehata19b2502010-01-06 10:33:53 -0800467 char asecFileName[255];
468 char mountPoint[255];
469
San Mehat3bb60202010-02-19 18:14:36 -0800470 snprintf(asecFileName, sizeof(asecFileName), "%s/%s.asec", Volume::SEC_ASECDIR, id);
471 snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id);
San Mehata19b2502010-01-06 10:33:53 -0800472
San Mehatd9a4e352010-03-12 13:32:47 -0800473 char idHash[33];
474 if (!asecHash(id, idHash, sizeof(idHash))) {
San Mehat97ac40e2010-03-24 10:24:19 -0700475 SLOGE("Hash of '%s' failed (%s)", id, strerror(errno));
San Mehatd9a4e352010-03-12 13:32:47 -0800476 return -1;
477 }
478
Kenny Rootfb7c4d52010-06-30 18:48:41 -0700479 return unmountLoopImage(id, idHash, asecFileName, mountPoint, force);
480}
481
Kenny Root508c0e12010-07-12 09:59:49 -0700482int VolumeManager::unmountObb(const char *fileName, bool force) {
Kenny Rootfb7c4d52010-06-30 18:48:41 -0700483 char mountPoint[255];
484
485 char idHash[33];
486 if (!asecHash(fileName, idHash, sizeof(idHash))) {
487 SLOGE("Hash of '%s' failed (%s)", fileName, strerror(errno));
488 return -1;
489 }
490
491 snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::LOOPDIR, idHash);
492
493 return unmountLoopImage(fileName, idHash, fileName, mountPoint, force);
494}
495
496int VolumeManager::unmountLoopImage(const char *id, const char *idHash,
497 const char *fileName, const char *mountPoint, bool force) {
San Mehat0586d542010-01-12 15:38:59 -0800498 if (!isMountpointMounted(mountPoint)) {
Kenny Rootfb7c4d52010-06-30 18:48:41 -0700499 SLOGE("Unmount request for %s when not mounted", id);
Kenny Root918e5f92010-09-30 18:00:52 -0700500 errno = ENOENT;
San Mehatb78a32c2010-01-10 13:02:12 -0800501 return -1;
502 }
San Mehat23969932010-01-09 07:08:06 -0800503
San Mehatb78a32c2010-01-10 13:02:12 -0800504 int i, rc;
Kenny Rootfb7c4d52010-06-30 18:48:41 -0700505 for (i = 1; i <= UNMOUNT_RETRIES; i++) {
San Mehatb78a32c2010-01-10 13:02:12 -0800506 rc = umount(mountPoint);
507 if (!rc) {
508 break;
San Mehata19b2502010-01-06 10:33:53 -0800509 }
San Mehatb78a32c2010-01-10 13:02:12 -0800510 if (rc && (errno == EINVAL || errno == ENOENT)) {
Kenny Rootfb7c4d52010-06-30 18:48:41 -0700511 SLOGI("Container %s unmounted OK", id);
San Mehatb78a32c2010-01-10 13:02:12 -0800512 rc = 0;
513 break;
San Mehata19b2502010-01-06 10:33:53 -0800514 }
Kenny Rootfb7c4d52010-06-30 18:48:41 -0700515 SLOGW("%s unmount attempt %d failed (%s)",
San Mehat8c940ef2010-02-13 14:19:53 -0800516 id, i, strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800517
San Mehat4ba89482010-02-18 09:00:18 -0800518 int action = 0; // default is to just complain
519
520 if (force) {
Kenny Rootfb7c4d52010-06-30 18:48:41 -0700521 if (i > (UNMOUNT_RETRIES - 2))
San Mehat4ba89482010-02-18 09:00:18 -0800522 action = 2; // SIGKILL
Kenny Rootfb7c4d52010-06-30 18:48:41 -0700523 else if (i > (UNMOUNT_RETRIES - 3))
San Mehat4ba89482010-02-18 09:00:18 -0800524 action = 1; // SIGHUP
525 }
San Mehat8c940ef2010-02-13 14:19:53 -0800526
San Mehat586536c2010-02-16 17:12:00 -0800527 Process::killProcessesWithOpenFiles(mountPoint, action);
Kenny Rootfb7c4d52010-06-30 18:48:41 -0700528 usleep(UNMOUNT_SLEEP_BETWEEN_RETRY_MS);
San Mehatb78a32c2010-01-10 13:02:12 -0800529 }
530
531 if (rc) {
San Mehat4ba89482010-02-18 09:00:18 -0800532 errno = EBUSY;
San Mehat97ac40e2010-03-24 10:24:19 -0700533 SLOGE("Failed to unmount container %s (%s)", id, strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800534 return -1;
535 }
536
San Mehat12f4b892010-02-24 11:43:22 -0800537 int retries = 10;
538
539 while(retries--) {
540 if (!rmdir(mountPoint)) {
541 break;
542 }
543
San Mehat97ac40e2010-03-24 10:24:19 -0700544 SLOGW("Failed to rmdir %s (%s)", mountPoint, strerror(errno));
Kenny Rootfb7c4d52010-06-30 18:48:41 -0700545 usleep(UNMOUNT_SLEEP_BETWEEN_RETRY_MS);
San Mehat12f4b892010-02-24 11:43:22 -0800546 }
547
548 if (!retries) {
San Mehat97ac40e2010-03-24 10:24:19 -0700549 SLOGE("Timed out trying to rmdir %s (%s)", mountPoint, strerror(errno));
San Mehatf5c61982010-02-03 11:04:46 -0800550 }
San Mehat88705162010-01-15 09:26:28 -0800551
San Mehatd9a4e352010-03-12 13:32:47 -0800552 if (Devmapper::destroy(idHash) && errno != ENXIO) {
San Mehat97ac40e2010-03-24 10:24:19 -0700553 SLOGE("Failed to destroy devmapper instance (%s)", strerror(errno));
San Mehata19b2502010-01-06 10:33:53 -0800554 }
555
556 char loopDevice[255];
San Mehatd9a4e352010-03-12 13:32:47 -0800557 if (!Loop::lookupActive(idHash, loopDevice, sizeof(loopDevice))) {
San Mehata19b2502010-01-06 10:33:53 -0800558 Loop::destroyByDevice(loopDevice);
San Mehatd9a4e352010-03-12 13:32:47 -0800559 } else {
Kenny Rootfb7c4d52010-06-30 18:48:41 -0700560 SLOGW("Failed to find loop device for {%s} (%s)", fileName, strerror(errno));
San Mehata19b2502010-01-06 10:33:53 -0800561 }
San Mehat88705162010-01-15 09:26:28 -0800562
563 AsecIdCollection::iterator it;
564 for (it = mActiveContainers->begin(); it != mActiveContainers->end(); ++it) {
Kenny Rootcbacf782010-09-24 15:11:48 -0700565 ContainerData* cd = *it;
566 if (!strcmp(cd->id, id)) {
San Mehat88705162010-01-15 09:26:28 -0800567 free(*it);
568 mActiveContainers->erase(it);
569 break;
570 }
571 }
572 if (it == mActiveContainers->end()) {
San Mehat97ac40e2010-03-24 10:24:19 -0700573 SLOGW("mActiveContainers is inconsistent!");
San Mehat88705162010-01-15 09:26:28 -0800574 }
San Mehatb78a32c2010-01-10 13:02:12 -0800575 return 0;
576}
577
San Mehat4ba89482010-02-18 09:00:18 -0800578int VolumeManager::destroyAsec(const char *id, bool force) {
San Mehatb78a32c2010-01-10 13:02:12 -0800579 char asecFileName[255];
580 char mountPoint[255];
581
San Mehat3bb60202010-02-19 18:14:36 -0800582 snprintf(asecFileName, sizeof(asecFileName), "%s/%s.asec", Volume::SEC_ASECDIR, id);
San Mehat55013f72010-02-24 12:12:34 -0800583 snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id);
San Mehatb78a32c2010-01-10 13:02:12 -0800584
San Mehat0586d542010-01-12 15:38:59 -0800585 if (isMountpointMounted(mountPoint)) {
San Mehatd9a4e352010-03-12 13:32:47 -0800586 if (mDebug) {
San Mehat97ac40e2010-03-24 10:24:19 -0700587 SLOGD("Unmounting container before destroy");
San Mehatd9a4e352010-03-12 13:32:47 -0800588 }
San Mehat4ba89482010-02-18 09:00:18 -0800589 if (unmountAsec(id, force)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700590 SLOGE("Failed to unmount asec %s for destroy (%s)", id, strerror(errno));
San Mehat0586d542010-01-12 15:38:59 -0800591 return -1;
592 }
593 }
San Mehata19b2502010-01-06 10:33:53 -0800594
San Mehat0586d542010-01-12 15:38:59 -0800595 if (unlink(asecFileName)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700596 SLOGE("Failed to unlink asec '%s' (%s)", asecFileName, strerror(errno));
San Mehat0586d542010-01-12 15:38:59 -0800597 return -1;
598 }
San Mehata19b2502010-01-06 10:33:53 -0800599
San Mehatd9a4e352010-03-12 13:32:47 -0800600 if (mDebug) {
San Mehat97ac40e2010-03-24 10:24:19 -0700601 SLOGD("ASEC %s destroyed", id);
San Mehatd9a4e352010-03-12 13:32:47 -0800602 }
San Mehata19b2502010-01-06 10:33:53 -0800603 return 0;
604}
605
606int VolumeManager::mountAsec(const char *id, const char *key, int ownerUid) {
607 char asecFileName[255];
608 char mountPoint[255];
609
San Mehat3bb60202010-02-19 18:14:36 -0800610 snprintf(asecFileName, sizeof(asecFileName), "%s/%s.asec", Volume::SEC_ASECDIR, id);
611 snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id);
San Mehata19b2502010-01-06 10:33:53 -0800612
613 if (isMountpointMounted(mountPoint)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700614 SLOGE("ASEC %s already mounted", id);
San Mehata19b2502010-01-06 10:33:53 -0800615 errno = EBUSY;
616 return -1;
617 }
618
San Mehatd9a4e352010-03-12 13:32:47 -0800619 char idHash[33];
620 if (!asecHash(id, idHash, sizeof(idHash))) {
San Mehat97ac40e2010-03-24 10:24:19 -0700621 SLOGE("Hash of '%s' failed (%s)", id, strerror(errno));
San Mehatd9a4e352010-03-12 13:32:47 -0800622 return -1;
623 }
Kenny Root7b18a7b2010-03-15 13:13:41 -0700624
San Mehata19b2502010-01-06 10:33:53 -0800625 char loopDevice[255];
San Mehatd9a4e352010-03-12 13:32:47 -0800626 if (Loop::lookupActive(idHash, loopDevice, sizeof(loopDevice))) {
627 if (Loop::create(idHash, asecFileName, loopDevice, sizeof(loopDevice))) {
San Mehat97ac40e2010-03-24 10:24:19 -0700628 SLOGE("ASEC loop device creation failed (%s)", strerror(errno));
San Mehata19b2502010-01-06 10:33:53 -0800629 return -1;
630 }
San Mehatd9a4e352010-03-12 13:32:47 -0800631 if (mDebug) {
San Mehat97ac40e2010-03-24 10:24:19 -0700632 SLOGD("New loop device created at %s", loopDevice);
San Mehatd9a4e352010-03-12 13:32:47 -0800633 }
San Mehatb78a32c2010-01-10 13:02:12 -0800634 } else {
San Mehatd9a4e352010-03-12 13:32:47 -0800635 if (mDebug) {
San Mehat97ac40e2010-03-24 10:24:19 -0700636 SLOGD("Found active loopback for %s at %s", asecFileName, loopDevice);
San Mehatd9a4e352010-03-12 13:32:47 -0800637 }
San Mehatb78a32c2010-01-10 13:02:12 -0800638 }
639
640 char dmDevice[255];
641 bool cleanupDm = false;
San Mehatfcf24fe2010-03-03 12:37:32 -0800642 int fd;
643 unsigned int nr_sec = 0;
644
645 if ((fd = open(loopDevice, O_RDWR)) < 0) {
San Mehat97ac40e2010-03-24 10:24:19 -0700646 SLOGE("Failed to open loopdevice (%s)", strerror(errno));
San Mehatfcf24fe2010-03-03 12:37:32 -0800647 Loop::destroyByDevice(loopDevice);
648 return -1;
649 }
650
651 if (ioctl(fd, BLKGETSIZE, &nr_sec)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700652 SLOGE("Failed to get loop size (%s)", strerror(errno));
San Mehatfcf24fe2010-03-03 12:37:32 -0800653 Loop::destroyByDevice(loopDevice);
654 close(fd);
655 return -1;
656 }
657
658 /*
659 * Validate superblock
660 */
661 struct asec_superblock sb;
662 memset(&sb, 0, sizeof(sb));
663 if (lseek(fd, ((nr_sec-1) * 512), SEEK_SET) < 0) {
San Mehat97ac40e2010-03-24 10:24:19 -0700664 SLOGE("lseek failed (%s)", strerror(errno));
San Mehatfcf24fe2010-03-03 12:37:32 -0800665 close(fd);
666 Loop::destroyByDevice(loopDevice);
667 return -1;
668 }
669 if (read(fd, &sb, sizeof(sb)) != sizeof(sb)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700670 SLOGE("superblock read failed (%s)", strerror(errno));
San Mehatfcf24fe2010-03-03 12:37:32 -0800671 close(fd);
672 Loop::destroyByDevice(loopDevice);
673 return -1;
674 }
675
676 close(fd);
677
San Mehatd9a4e352010-03-12 13:32:47 -0800678 if (mDebug) {
San Mehat97ac40e2010-03-24 10:24:19 -0700679 SLOGD("Container sb magic/ver (%.8x/%.2x)", sb.magic, sb.ver);
San Mehatd9a4e352010-03-12 13:32:47 -0800680 }
San Mehatfcf24fe2010-03-03 12:37:32 -0800681 if (sb.magic != ASEC_SB_MAGIC || sb.ver != ASEC_SB_VER) {
San Mehat97ac40e2010-03-24 10:24:19 -0700682 SLOGE("Bad container magic/version (%.8x/%.2x)", sb.magic, sb.ver);
San Mehatfcf24fe2010-03-03 12:37:32 -0800683 Loop::destroyByDevice(loopDevice);
684 errno = EMEDIUMTYPE;
685 return -1;
686 }
687 nr_sec--; // We don't want the devmapping to extend onto our superblock
688
San Mehatb78a32c2010-01-10 13:02:12 -0800689 if (strcmp(key, "none")) {
San Mehatd9a4e352010-03-12 13:32:47 -0800690 if (Devmapper::lookupActive(idHash, dmDevice, sizeof(dmDevice))) {
691 if (Devmapper::create(idHash, loopDevice, key, nr_sec,
San Mehatb78a32c2010-01-10 13:02:12 -0800692 dmDevice, sizeof(dmDevice))) {
San Mehat97ac40e2010-03-24 10:24:19 -0700693 SLOGE("ASEC device mapping failed (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800694 Loop::destroyByDevice(loopDevice);
695 return -1;
696 }
San Mehatd9a4e352010-03-12 13:32:47 -0800697 if (mDebug) {
San Mehat97ac40e2010-03-24 10:24:19 -0700698 SLOGD("New devmapper instance created at %s", dmDevice);
San Mehatd9a4e352010-03-12 13:32:47 -0800699 }
San Mehatb78a32c2010-01-10 13:02:12 -0800700 } else {
San Mehatd9a4e352010-03-12 13:32:47 -0800701 if (mDebug) {
San Mehat97ac40e2010-03-24 10:24:19 -0700702 SLOGD("Found active devmapper for %s at %s", asecFileName, dmDevice);
San Mehatd9a4e352010-03-12 13:32:47 -0800703 }
San Mehatb78a32c2010-01-10 13:02:12 -0800704 }
705 cleanupDm = true;
706 } else {
707 strcpy(dmDevice, loopDevice);
San Mehata19b2502010-01-06 10:33:53 -0800708 }
709
710 if (mkdir(mountPoint, 0777)) {
San Mehatb78a32c2010-01-10 13:02:12 -0800711 if (errno != EEXIST) {
San Mehat97ac40e2010-03-24 10:24:19 -0700712 SLOGE("Mountpoint creation failed (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800713 if (cleanupDm) {
San Mehatd9a4e352010-03-12 13:32:47 -0800714 Devmapper::destroy(idHash);
San Mehatb78a32c2010-01-10 13:02:12 -0800715 }
716 Loop::destroyByDevice(loopDevice);
717 return -1;
718 }
San Mehata19b2502010-01-06 10:33:53 -0800719 }
720
Kenny Roota3e06082010-08-27 08:31:35 -0700721 if (Fat::doMount(dmDevice, mountPoint, true, false, true, ownerUid, 0,
San Mehatcff5ec32010-01-08 12:31:44 -0800722 0222, false)) {
723// 0227, false)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700724 SLOGE("ASEC mount failed (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800725 if (cleanupDm) {
San Mehatd9a4e352010-03-12 13:32:47 -0800726 Devmapper::destroy(idHash);
San Mehatb78a32c2010-01-10 13:02:12 -0800727 }
728 Loop::destroyByDevice(loopDevice);
San Mehata19b2502010-01-06 10:33:53 -0800729 return -1;
730 }
731
Kenny Rootcbacf782010-09-24 15:11:48 -0700732 mActiveContainers->push_back(new ContainerData(strdup(id), ASEC));
San Mehatd9a4e352010-03-12 13:32:47 -0800733 if (mDebug) {
San Mehat97ac40e2010-03-24 10:24:19 -0700734 SLOGD("ASEC %s mounted", id);
San Mehatd9a4e352010-03-12 13:32:47 -0800735 }
San Mehata19b2502010-01-06 10:33:53 -0800736 return 0;
737}
738
Kenny Rootfb7c4d52010-06-30 18:48:41 -0700739/**
740 * Mounts an image file <code>img</code>.
741 */
Kenny Root508c0e12010-07-12 09:59:49 -0700742int VolumeManager::mountObb(const char *img, const char *key, int ownerUid) {
Kenny Rootfb7c4d52010-06-30 18:48:41 -0700743 char mountPoint[255];
744
Kenny Rootfb7c4d52010-06-30 18:48:41 -0700745 char idHash[33];
746 if (!asecHash(img, idHash, sizeof(idHash))) {
747 SLOGE("Hash of '%s' failed (%s)", img, strerror(errno));
748 return -1;
749 }
750
751 snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::LOOPDIR, idHash);
752
753 if (isMountpointMounted(mountPoint)) {
754 SLOGE("Image %s already mounted", img);
755 errno = EBUSY;
756 return -1;
757 }
758
759 char loopDevice[255];
760 if (Loop::lookupActive(idHash, loopDevice, sizeof(loopDevice))) {
761 if (Loop::create(idHash, img, loopDevice, sizeof(loopDevice))) {
762 SLOGE("Image loop device creation failed (%s)", strerror(errno));
763 return -1;
764 }
765 if (mDebug) {
766 SLOGD("New loop device created at %s", loopDevice);
767 }
768 } else {
769 if (mDebug) {
770 SLOGD("Found active loopback for %s at %s", img, loopDevice);
771 }
772 }
773
774 char dmDevice[255];
775 bool cleanupDm = false;
776 int fd;
777 unsigned int nr_sec = 0;
778
779 if ((fd = open(loopDevice, O_RDWR)) < 0) {
780 SLOGE("Failed to open loopdevice (%s)", strerror(errno));
781 Loop::destroyByDevice(loopDevice);
782 return -1;
783 }
784
785 if (ioctl(fd, BLKGETSIZE, &nr_sec)) {
786 SLOGE("Failed to get loop size (%s)", strerror(errno));
787 Loop::destroyByDevice(loopDevice);
788 close(fd);
789 return -1;
790 }
791
792 close(fd);
793
794 if (strcmp(key, "none")) {
795 if (Devmapper::lookupActive(idHash, dmDevice, sizeof(dmDevice))) {
796 if (Devmapper::create(idHash, loopDevice, key, nr_sec,
797 dmDevice, sizeof(dmDevice))) {
798 SLOGE("ASEC device mapping failed (%s)", strerror(errno));
799 Loop::destroyByDevice(loopDevice);
800 return -1;
801 }
802 if (mDebug) {
803 SLOGD("New devmapper instance created at %s", dmDevice);
804 }
805 } else {
806 if (mDebug) {
807 SLOGD("Found active devmapper for %s at %s", img, dmDevice);
808 }
809 }
810 cleanupDm = true;
811 } else {
812 strcpy(dmDevice, loopDevice);
813 }
814
815 if (mkdir(mountPoint, 0755)) {
816 if (errno != EEXIST) {
817 SLOGE("Mountpoint creation failed (%s)", strerror(errno));
818 if (cleanupDm) {
819 Devmapper::destroy(idHash);
820 }
821 Loop::destroyByDevice(loopDevice);
822 return -1;
823 }
824 }
825
Kenny Roota3e06082010-08-27 08:31:35 -0700826 if (Fat::doMount(dmDevice, mountPoint, true, false, true, ownerUid, 0,
Kenny Rootfb7c4d52010-06-30 18:48:41 -0700827 0227, false)) {
828 SLOGE("Image mount failed (%s)", strerror(errno));
829 if (cleanupDm) {
830 Devmapper::destroy(idHash);
831 }
832 Loop::destroyByDevice(loopDevice);
833 return -1;
834 }
835
Kenny Rootcbacf782010-09-24 15:11:48 -0700836 mActiveContainers->push_back(new ContainerData(strdup(img), OBB));
Kenny Rootfb7c4d52010-06-30 18:48:41 -0700837 if (mDebug) {
838 SLOGD("Image %s mounted", img);
839 }
840 return 0;
841}
842
San Mehat49e2bce2009-10-12 16:29:01 -0700843int VolumeManager::mountVolume(const char *label) {
844 Volume *v = lookupVolume(label);
845
846 if (!v) {
847 errno = ENOENT;
848 return -1;
849 }
850
San Mehata2677e42009-12-13 10:40:18 -0800851 return v->mountVol();
852}
853
Kenny Root508c0e12010-07-12 09:59:49 -0700854int VolumeManager::listMountedObbs(SocketClient* cli) {
855 char device[256];
856 char mount_path[256];
857 char rest[256];
858 FILE *fp;
859 char line[1024];
860
861 if (!(fp = fopen("/proc/mounts", "r"))) {
862 SLOGE("Error opening /proc/mounts (%s)", strerror(errno));
863 return -1;
864 }
865
866 // Create a string to compare against that has a trailing slash
867 int loopDirLen = sizeof(Volume::LOOPDIR);
868 char loopDir[loopDirLen + 2];
869 strcpy(loopDir, Volume::LOOPDIR);
870 loopDir[loopDirLen++] = '/';
871 loopDir[loopDirLen] = '\0';
872
873 while(fgets(line, sizeof(line), fp)) {
874 line[strlen(line)-1] = '\0';
875
876 /*
877 * Should look like:
878 * /dev/block/loop0 /mnt/obb/fc99df1323fd36424f864dcb76b76d65 ...
879 */
880 sscanf(line, "%255s %255s %255s\n", device, mount_path, rest);
881
882 if (!strncmp(mount_path, loopDir, loopDirLen)) {
883 int fd = open(device, O_RDONLY);
884 if (fd >= 0) {
885 struct loop_info64 li;
886 if (ioctl(fd, LOOP_GET_STATUS64, &li) >= 0) {
887 cli->sendMsg(ResponseCode::AsecListResult,
888 (const char*) li.lo_file_name, false);
889 }
890 close(fd);
891 }
892 }
893 }
894
895 fclose(fp);
896 return 0;
897}
898
San Mehateba65e92010-01-29 05:15:16 -0800899int VolumeManager::shareEnabled(const char *label, const char *method, bool *enabled) {
900 Volume *v = lookupVolume(label);
901
902 if (!v) {
903 errno = ENOENT;
904 return -1;
905 }
906
907 if (strcmp(method, "ums")) {
908 errno = ENOSYS;
909 return -1;
910 }
911
912 if (v->getState() != Volume::State_Shared) {
San Mehateba65e92010-01-29 05:15:16 -0800913 *enabled = false;
San Mehatb9aed742010-02-04 15:07:01 -0800914 } else {
915 *enabled = true;
San Mehateba65e92010-01-29 05:15:16 -0800916 }
917 return 0;
918}
919
San Mehata2677e42009-12-13 10:40:18 -0800920int VolumeManager::shareVolume(const char *label, const char *method) {
921 Volume *v = lookupVolume(label);
922
923 if (!v) {
924 errno = ENOENT;
925 return -1;
926 }
927
928 /*
929 * Eventually, we'll want to support additional share back-ends,
930 * some of which may work while the media is mounted. For now,
931 * we just support UMS
932 */
933 if (strcmp(method, "ums")) {
934 errno = ENOSYS;
935 return -1;
936 }
937
938 if (v->getState() == Volume::State_NoMedia) {
939 errno = ENODEV;
940 return -1;
941 }
942
San Mehat49e2bce2009-10-12 16:29:01 -0700943 if (v->getState() != Volume::State_Idle) {
San Mehata2677e42009-12-13 10:40:18 -0800944 // You need to unmount manually befoe sharing
San Mehat49e2bce2009-10-12 16:29:01 -0700945 errno = EBUSY;
946 return -1;
947 }
948
Ken Sumrall3b170052011-07-11 15:38:57 -0700949 if (mVolManagerDisabled) {
950 errno = EBUSY;
951 return -1;
952 }
953
Mike Lockwood2dfe2972010-09-17 18:50:51 -0400954 dev_t d = v->getShareDevice();
San Mehata2677e42009-12-13 10:40:18 -0800955 if ((MAJOR(d) == 0) && (MINOR(d) == 0)) {
956 // This volume does not support raw disk access
957 errno = EINVAL;
958 return -1;
959 }
960
961 int fd;
962 char nodepath[255];
963 snprintf(nodepath,
964 sizeof(nodepath), "/dev/block/vold/%d:%d",
965 MAJOR(d), MINOR(d));
966
Mike Lockwood97f2fc12011-06-07 10:51:38 -0700967 if ((fd = open(MASS_STORAGE_FILE_PATH, O_WRONLY)) < 0) {
San Mehat97ac40e2010-03-24 10:24:19 -0700968 SLOGE("Unable to open ums lunfile (%s)", strerror(errno));
San Mehata2677e42009-12-13 10:40:18 -0800969 return -1;
970 }
971
972 if (write(fd, nodepath, strlen(nodepath)) < 0) {
San Mehat97ac40e2010-03-24 10:24:19 -0700973 SLOGE("Unable to write to ums lunfile (%s)", strerror(errno));
San Mehata2677e42009-12-13 10:40:18 -0800974 close(fd);
975 return -1;
976 }
977
978 close(fd);
979 v->handleVolumeShared();
Mike Lockwooda28056b2010-10-28 15:21:24 -0400980 if (mUmsSharingCount++ == 0) {
981 FILE* fp;
982 mSavedDirtyRatio = -1; // in case we fail
983 if ((fp = fopen("/proc/sys/vm/dirty_ratio", "r+"))) {
984 char line[16];
985 if (fgets(line, sizeof(line), fp) && sscanf(line, "%d", &mSavedDirtyRatio)) {
986 fprintf(fp, "%d\n", mUmsDirtyRatio);
987 } else {
988 SLOGE("Failed to read dirty_ratio (%s)", strerror(errno));
989 }
990 fclose(fp);
991 } else {
992 SLOGE("Failed to open /proc/sys/vm/dirty_ratio (%s)", strerror(errno));
993 }
994 }
San Mehata2677e42009-12-13 10:40:18 -0800995 return 0;
996}
997
998int VolumeManager::unshareVolume(const char *label, const char *method) {
999 Volume *v = lookupVolume(label);
1000
1001 if (!v) {
1002 errno = ENOENT;
1003 return -1;
1004 }
1005
1006 if (strcmp(method, "ums")) {
1007 errno = ENOSYS;
1008 return -1;
1009 }
1010
1011 if (v->getState() != Volume::State_Shared) {
1012 errno = EINVAL;
1013 return -1;
1014 }
1015
San Mehata2677e42009-12-13 10:40:18 -08001016 int fd;
Mike Lockwood97f2fc12011-06-07 10:51:38 -07001017 if ((fd = open(MASS_STORAGE_FILE_PATH, O_WRONLY)) < 0) {
San Mehat97ac40e2010-03-24 10:24:19 -07001018 SLOGE("Unable to open ums lunfile (%s)", strerror(errno));
San Mehata2677e42009-12-13 10:40:18 -08001019 return -1;
1020 }
1021
1022 char ch = 0;
1023 if (write(fd, &ch, 1) < 0) {
San Mehat97ac40e2010-03-24 10:24:19 -07001024 SLOGE("Unable to write to ums lunfile (%s)", strerror(errno));
San Mehata2677e42009-12-13 10:40:18 -08001025 close(fd);
1026 return -1;
1027 }
1028
1029 close(fd);
1030 v->handleVolumeUnshared();
Mike Lockwooda28056b2010-10-28 15:21:24 -04001031 if (--mUmsSharingCount == 0 && mSavedDirtyRatio != -1) {
1032 FILE* fp;
1033 if ((fp = fopen("/proc/sys/vm/dirty_ratio", "r+"))) {
1034 fprintf(fp, "%d\n", mSavedDirtyRatio);
1035 fclose(fp);
1036 } else {
1037 SLOGE("Failed to open /proc/sys/vm/dirty_ratio (%s)", strerror(errno));
1038 }
1039 mSavedDirtyRatio = -1;
1040 }
San Mehata2677e42009-12-13 10:40:18 -08001041 return 0;
San Mehat49e2bce2009-10-12 16:29:01 -07001042}
1043
Ken Sumrall3b170052011-07-11 15:38:57 -07001044extern "C" int vold_disableVol(const char *label) {
Ken Sumrall29d8da82011-05-18 17:20:07 -07001045 VolumeManager *vm = VolumeManager::Instance();
Ken Sumrall3b170052011-07-11 15:38:57 -07001046 vm->disableVolumeManager();
1047 vm->unshareVolume(label, "ums");
Ken Sumrall29d8da82011-05-18 17:20:07 -07001048 return vm->unmountVolume(label, true);
1049}
1050
1051extern "C" int vold_getNumDirectVolumes(void) {
1052 VolumeManager *vm = VolumeManager::Instance();
1053 return vm->getNumDirectVolumes();
1054}
1055
1056int VolumeManager::getNumDirectVolumes(void) {
1057 VolumeCollection::iterator i;
1058 int n=0;
1059
1060 for (i = mVolumes->begin(); i != mVolumes->end(); ++i) {
1061 if ((*i)->getShareDevice() != (dev_t)0) {
1062 n++;
1063 }
1064 }
1065 return n;
1066}
1067
1068extern "C" int vold_getDirectVolumeList(struct volume_info *vol_list) {
1069 VolumeManager *vm = VolumeManager::Instance();
1070 return vm->getDirectVolumeList(vol_list);
1071}
1072
1073int VolumeManager::getDirectVolumeList(struct volume_info *vol_list) {
1074 VolumeCollection::iterator i;
1075 int n=0;
1076 dev_t d;
1077
1078 for (i = mVolumes->begin(); i != mVolumes->end(); ++i) {
1079 if ((d=(*i)->getShareDevice()) != (dev_t)0) {
1080 (*i)->getVolInfo(&vol_list[n]);
1081 snprintf(vol_list[n].blk_dev, sizeof(vol_list[n].blk_dev),
1082 "/dev/block/vold/%d:%d",MAJOR(d), MINOR(d));
1083 n++;
1084 }
1085 }
1086
1087 return 0;
1088}
1089
San Mehat4ba89482010-02-18 09:00:18 -08001090int VolumeManager::unmountVolume(const char *label, bool force) {
San Mehat49e2bce2009-10-12 16:29:01 -07001091 Volume *v = lookupVolume(label);
1092
1093 if (!v) {
1094 errno = ENOENT;
1095 return -1;
1096 }
1097
San Mehata2677e42009-12-13 10:40:18 -08001098 if (v->getState() == Volume::State_NoMedia) {
1099 errno = ENODEV;
1100 return -1;
1101 }
1102
San Mehat49e2bce2009-10-12 16:29:01 -07001103 if (v->getState() != Volume::State_Mounted) {
San Mehat97ac40e2010-03-24 10:24:19 -07001104 SLOGW("Attempt to unmount volume which isn't mounted (%d)\n",
San Mehata2677e42009-12-13 10:40:18 -08001105 v->getState());
San Mehat49e2bce2009-10-12 16:29:01 -07001106 errno = EBUSY;
Ken Sumrall319b1042011-06-14 14:01:55 -07001107 return UNMOUNT_NOT_MOUNTED_ERR;
San Mehat49e2bce2009-10-12 16:29:01 -07001108 }
1109
San Mehat1a06eda2010-04-15 12:58:50 -07001110 cleanupAsec(v, force);
San Mehat88705162010-01-15 09:26:28 -08001111
San Mehat4ba89482010-02-18 09:00:18 -08001112 return v->unmountVol(force);
San Mehat49e2bce2009-10-12 16:29:01 -07001113}
1114
San Mehata2677e42009-12-13 10:40:18 -08001115/*
1116 * Looks up a volume by it's label or mount-point
1117 */
San Mehat49e2bce2009-10-12 16:29:01 -07001118Volume *VolumeManager::lookupVolume(const char *label) {
1119 VolumeCollection::iterator i;
1120
1121 for (i = mVolumes->begin(); i != mVolumes->end(); ++i) {
San Mehata2677e42009-12-13 10:40:18 -08001122 if (label[0] == '/') {
1123 if (!strcmp(label, (*i)->getMountpoint()))
1124 return (*i);
1125 } else {
1126 if (!strcmp(label, (*i)->getLabel()))
1127 return (*i);
1128 }
San Mehat49e2bce2009-10-12 16:29:01 -07001129 }
1130 return NULL;
1131}
San Mehata19b2502010-01-06 10:33:53 -08001132
1133bool VolumeManager::isMountpointMounted(const char *mp)
1134{
1135 char device[256];
1136 char mount_path[256];
1137 char rest[256];
1138 FILE *fp;
1139 char line[1024];
1140
1141 if (!(fp = fopen("/proc/mounts", "r"))) {
San Mehat97ac40e2010-03-24 10:24:19 -07001142 SLOGE("Error opening /proc/mounts (%s)", strerror(errno));
San Mehata19b2502010-01-06 10:33:53 -08001143 return false;
1144 }
1145
1146 while(fgets(line, sizeof(line), fp)) {
1147 line[strlen(line)-1] = '\0';
1148 sscanf(line, "%255s %255s %255s\n", device, mount_path, rest);
1149 if (!strcmp(mount_path, mp)) {
1150 fclose(fp);
1151 return true;
1152 }
San Mehata19b2502010-01-06 10:33:53 -08001153 }
1154
1155 fclose(fp);
1156 return false;
1157}
1158
San Mehat1a06eda2010-04-15 12:58:50 -07001159int VolumeManager::cleanupAsec(Volume *v, bool force) {
1160 while(mActiveContainers->size()) {
1161 AsecIdCollection::iterator it = mActiveContainers->begin();
Kenny Rootcbacf782010-09-24 15:11:48 -07001162 ContainerData* cd = *it;
1163 SLOGI("Unmounting ASEC %s (dependant on %s)", cd->id, v->getMountpoint());
1164 if (cd->type == ASEC) {
1165 if (unmountAsec(cd->id, force)) {
1166 SLOGE("Failed to unmount ASEC %s (%s)", cd->id, strerror(errno));
1167 return -1;
1168 }
1169 } else if (cd->type == OBB) {
1170 if (unmountObb(cd->id, force)) {
1171 SLOGE("Failed to unmount OBB %s (%s)", cd->id, strerror(errno));
1172 return -1;
1173 }
1174 } else {
1175 SLOGE("Unknown container type %d!", cd->type);
San Mehat1a06eda2010-04-15 12:58:50 -07001176 return -1;
1177 }
1178 }
1179 return 0;
1180}
1181