blob: 2127eab9a8a4298cba446131a0b3bfc433d4dc55 [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"
San Mehat23969932010-01-09 07:08:06 -080044
San Mehatf1b736b2009-10-10 17:22:08 -070045VolumeManager *VolumeManager::sInstance = NULL;
46
47VolumeManager *VolumeManager::Instance() {
48 if (!sInstance)
49 sInstance = new VolumeManager();
50 return sInstance;
51}
52
53VolumeManager::VolumeManager() {
San Mehatd9a4e352010-03-12 13:32:47 -080054 mDebug = false;
San Mehatf1b736b2009-10-10 17:22:08 -070055 mVolumes = new VolumeCollection();
San Mehat88705162010-01-15 09:26:28 -080056 mActiveContainers = new AsecIdCollection();
San Mehatf1b736b2009-10-10 17:22:08 -070057 mBroadcaster = NULL;
Mike Lockwood99635f62010-06-25 23:04:04 -040058 mUsbMassStorageEnabled = false;
59 mUsbConnected = false;
60
61 readInitialState();
62}
63
64void VolumeManager::readInitialState() {
65 FILE *fp;
66 char state[255];
67
68 /*
69 * Read the initial mass storage enabled state
70 */
71 if ((fp = fopen("/sys/devices/virtual/usb_composite/usb_mass_storage/enable", "r"))) {
72 if (fgets(state, sizeof(state), fp)) {
73 mUsbMassStorageEnabled = !strncmp(state, "1", 1);
74 } else {
75 SLOGE("Failed to read usb_mass_storage enabled state (%s)", strerror(errno));
76 }
77 fclose(fp);
78 } else {
79 SLOGD("USB mass storage support is not enabled in the kernel");
80 }
81
82 /*
83 * Read the initial USB connected state
84 */
85 if ((fp = fopen("/sys/devices/virtual/switch/usb_configuration/state", "r"))) {
86 if (fgets(state, sizeof(state), fp)) {
87 mUsbConnected = !strncmp(state, "1", 1);
88 } else {
89 SLOGE("Failed to read usb_configuration switch (%s)", strerror(errno));
90 }
91 fclose(fp);
92 } else {
93 SLOGD("usb_configuration switch is not enabled in the kernel");
94 }
San Mehatf1b736b2009-10-10 17:22:08 -070095}
96
97VolumeManager::~VolumeManager() {
San Mehat88705162010-01-15 09:26:28 -080098 delete mVolumes;
99 delete mActiveContainers;
San Mehatf1b736b2009-10-10 17:22:08 -0700100}
101
Kenny Root7b18a7b2010-03-15 13:13:41 -0700102char *VolumeManager::asecHash(const char *id, char *buffer, size_t len) {
Kenny Rootacc9e7d2010-06-18 19:06:50 -0700103 static const char* digits = "0123456789abcdef";
104
Kenny Root7b18a7b2010-03-15 13:13:41 -0700105 unsigned char sig[MD5_DIGEST_LENGTH];
106
Kenny Rootacc9e7d2010-06-18 19:06:50 -0700107 if (buffer == NULL) {
108 SLOGE("Destination buffer is NULL");
109 errno = ESPIPE;
110 return NULL;
111 } else if (id == NULL) {
112 SLOGE("Source buffer is NULL");
113 errno = ESPIPE;
114 return NULL;
115 } else if (len < MD5_ASCII_LENGTH_PLUS_NULL) {
116 SLOGE("Target hash buffer size < %d bytes (%d)",
117 MD5_ASCII_LENGTH_PLUS_NULL, len);
San Mehatd9a4e352010-03-12 13:32:47 -0800118 errno = ESPIPE;
119 return NULL;
120 }
Kenny Root7b18a7b2010-03-15 13:13:41 -0700121
122 MD5(reinterpret_cast<const unsigned char*>(id), strlen(id), sig);
San Mehatd9a4e352010-03-12 13:32:47 -0800123
Kenny Rootacc9e7d2010-06-18 19:06:50 -0700124 char *p = buffer;
Kenny Root7b18a7b2010-03-15 13:13:41 -0700125 for (int i = 0; i < MD5_DIGEST_LENGTH; i++) {
Kenny Rootacc9e7d2010-06-18 19:06:50 -0700126 *p++ = digits[sig[i] >> 4];
127 *p++ = digits[sig[i] & 0x0F];
San Mehatd9a4e352010-03-12 13:32:47 -0800128 }
Kenny Rootacc9e7d2010-06-18 19:06:50 -0700129 *p = '\0';
San Mehatd9a4e352010-03-12 13:32:47 -0800130
131 return buffer;
132}
133
134void VolumeManager::setDebug(bool enable) {
135 mDebug = enable;
136 VolumeCollection::iterator it;
137 for (it = mVolumes->begin(); it != mVolumes->end(); ++it) {
138 (*it)->setDebug(enable);
139 }
140}
141
San Mehatf1b736b2009-10-10 17:22:08 -0700142int VolumeManager::start() {
143 return 0;
144}
145
146int VolumeManager::stop() {
147 return 0;
148}
149
150int VolumeManager::addVolume(Volume *v) {
151 mVolumes->push_back(v);
152 return 0;
153}
154
Mike Lockwood99635f62010-06-25 23:04:04 -0400155void VolumeManager::notifyUmsAvailable(bool available) {
San Mehata2677e42009-12-13 10:40:18 -0800156 char msg[255];
157
San Mehata2677e42009-12-13 10:40:18 -0800158 snprintf(msg, sizeof(msg), "Share method ums now %s",
Mike Lockwood99635f62010-06-25 23:04:04 -0400159 (available ? "available" : "unavailable"));
160 SLOGD(msg);
San Mehata2677e42009-12-13 10:40:18 -0800161 getBroadcaster()->sendBroadcast(ResponseCode::ShareAvailabilityChange,
162 msg, false);
163}
164
165void VolumeManager::handleSwitchEvent(NetlinkEvent *evt) {
San Mehat0cde53c2009-12-22 08:32:33 -0800166 const char *devpath = evt->findParam("DEVPATH");
San Mehata2677e42009-12-13 10:40:18 -0800167 const char *name = evt->findParam("SWITCH_NAME");
168 const char *state = evt->findParam("SWITCH_STATE");
169
San Mehat0cde53c2009-12-22 08:32:33 -0800170 if (!name || !state) {
San Mehat97ac40e2010-03-24 10:24:19 -0700171 SLOGW("Switch %s event missing name/state info", devpath);
San Mehat0cde53c2009-12-22 08:32:33 -0800172 return;
173 }
174
Mike Lockwood99635f62010-06-25 23:04:04 -0400175 bool oldAvailable = massStorageAvailable();
176 if (!strcmp(name, "usb_configuration")) {
177 mUsbConnected = !strcmp(state, "1");
178 SLOGD("USB %s", mUsbConnected ? "connected" : "disconnected");
179 bool newAvailable = massStorageAvailable();
180 if (newAvailable != oldAvailable) {
181 notifyUmsAvailable(newAvailable);
San Mehata2677e42009-12-13 10:40:18 -0800182 }
183 } else {
San Mehat97ac40e2010-03-24 10:24:19 -0700184 SLOGW("Ignoring unknown switch '%s'", name);
San Mehata2677e42009-12-13 10:40:18 -0800185 }
186}
Mike Lockwood99635f62010-06-25 23:04:04 -0400187void VolumeManager::handleUsbCompositeEvent(NetlinkEvent *evt) {
188 const char *function = evt->findParam("FUNCTION");
189 const char *enabled = evt->findParam("ENABLED");
190
191 if (!function || !enabled) {
192 SLOGW("usb_composite event missing function/enabled info");
193 return;
194 }
195
196 if (!strcmp(function, "usb_mass_storage")) {
197 bool oldAvailable = massStorageAvailable();
198 mUsbMassStorageEnabled = !strcmp(enabled, "1");
199 SLOGD("usb_mass_storage function %s", mUsbMassStorageEnabled ? "enabled" : "disabled");
200 bool newAvailable = massStorageAvailable();
201 if (newAvailable != oldAvailable) {
202 notifyUmsAvailable(newAvailable);
203 }
204 }
205}
San Mehata2677e42009-12-13 10:40:18 -0800206
San Mehatfd7f5872009-10-12 11:32:47 -0700207void VolumeManager::handleBlockEvent(NetlinkEvent *evt) {
208 const char *devpath = evt->findParam("DEVPATH");
San Mehatf1b736b2009-10-10 17:22:08 -0700209
San Mehatfd7f5872009-10-12 11:32:47 -0700210 /* Lookup a volume to handle this device */
San Mehatf1b736b2009-10-10 17:22:08 -0700211 VolumeCollection::iterator it;
212 bool hit = false;
213 for (it = mVolumes->begin(); it != mVolumes->end(); ++it) {
San Mehatfd7f5872009-10-12 11:32:47 -0700214 if (!(*it)->handleBlockEvent(evt)) {
San Mehata2677e42009-12-13 10:40:18 -0800215#ifdef NETLINK_DEBUG
San Mehat97ac40e2010-03-24 10:24:19 -0700216 SLOGD("Device '%s' event handled by volume %s\n", devpath, (*it)->getLabel());
San Mehata2677e42009-12-13 10:40:18 -0800217#endif
San Mehatf1b736b2009-10-10 17:22:08 -0700218 hit = true;
San Mehatf1b736b2009-10-10 17:22:08 -0700219 break;
220 }
221 }
222
223 if (!hit) {
San Mehata2677e42009-12-13 10:40:18 -0800224#ifdef NETLINK_DEBUG
San Mehat97ac40e2010-03-24 10:24:19 -0700225 SLOGW("No volumes handled block event for '%s'", devpath);
San Mehata2677e42009-12-13 10:40:18 -0800226#endif
San Mehatf1b736b2009-10-10 17:22:08 -0700227 }
228}
229
San Mehatf1b736b2009-10-10 17:22:08 -0700230int VolumeManager::listVolumes(SocketClient *cli) {
231 VolumeCollection::iterator i;
232
233 for (i = mVolumes->begin(); i != mVolumes->end(); ++i) {
234 char *buffer;
235 asprintf(&buffer, "%s %s %d",
236 (*i)->getLabel(), (*i)->getMountpoint(),
237 (*i)->getState());
San Mehata2677e42009-12-13 10:40:18 -0800238 cli->sendMsg(ResponseCode::VolumeListResult, buffer, false);
San Mehatf1b736b2009-10-10 17:22:08 -0700239 free(buffer);
240 }
San Mehata2677e42009-12-13 10:40:18 -0800241 cli->sendMsg(ResponseCode::CommandOkay, "Volumes listed.", false);
San Mehatf1b736b2009-10-10 17:22:08 -0700242 return 0;
243}
San Mehat49e2bce2009-10-12 16:29:01 -0700244
San Mehata2677e42009-12-13 10:40:18 -0800245int VolumeManager::formatVolume(const char *label) {
246 Volume *v = lookupVolume(label);
247
248 if (!v) {
249 errno = ENOENT;
250 return -1;
251 }
252
253 return v->formatVol();
254}
255
San Mehata19b2502010-01-06 10:33:53 -0800256int VolumeManager::getAsecMountPath(const char *id, char *buffer, int maxlen) {
San Mehat88ac2c02010-03-23 11:15:58 -0700257 char asecFileName[255];
258 snprintf(asecFileName, sizeof(asecFileName), "%s/%s.asec", Volume::SEC_ASECDIR, id);
259
260 memset(buffer, 0, maxlen);
261 if (access(asecFileName, F_OK)) {
262 errno = ENOENT;
263 return -1;
264 }
San Mehata19b2502010-01-06 10:33:53 -0800265
San Mehat3bb60202010-02-19 18:14:36 -0800266 snprintf(buffer, maxlen, "%s/%s", Volume::ASECDIR, id);
San Mehata19b2502010-01-06 10:33:53 -0800267 return 0;
268}
269
San Mehat8b8f71b2010-01-11 09:17:25 -0800270int VolumeManager::createAsec(const char *id, unsigned int numSectors,
San Mehata19b2502010-01-06 10:33:53 -0800271 const char *fstype, const char *key, int ownerUid) {
San Mehatfcf24fe2010-03-03 12:37:32 -0800272 struct asec_superblock sb;
273 memset(&sb, 0, sizeof(sb));
274
275 sb.magic = ASEC_SB_MAGIC;
276 sb.ver = ASEC_SB_VER;
San Mehata19b2502010-01-06 10:33:53 -0800277
San Mehatd31e3802010-02-18 08:37:45 -0800278 if (numSectors < ((1024*1024)/512)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700279 SLOGE("Invalid container size specified (%d sectors)", numSectors);
San Mehatd31e3802010-02-18 08:37:45 -0800280 errno = EINVAL;
281 return -1;
282 }
283
San Mehata19b2502010-01-06 10:33:53 -0800284 if (lookupVolume(id)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700285 SLOGE("ASEC id '%s' currently exists", id);
San Mehata19b2502010-01-06 10:33:53 -0800286 errno = EADDRINUSE;
287 return -1;
288 }
289
290 char asecFileName[255];
San Mehat3bb60202010-02-19 18:14:36 -0800291 snprintf(asecFileName, sizeof(asecFileName), "%s/%s.asec", Volume::SEC_ASECDIR, id);
San Mehata19b2502010-01-06 10:33:53 -0800292
293 if (!access(asecFileName, F_OK)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700294 SLOGE("ASEC file '%s' currently exists - destroy it first! (%s)",
San Mehata19b2502010-01-06 10:33:53 -0800295 asecFileName, strerror(errno));
296 errno = EADDRINUSE;
297 return -1;
298 }
299
San Mehatfcf24fe2010-03-03 12:37:32 -0800300 /*
301 * Add some headroom
302 */
303 unsigned fatSize = (((numSectors * 4) / 512) + 1) * 2;
304 unsigned numImgSectors = numSectors + fatSize + 2;
305
306 if (numImgSectors % 63) {
307 numImgSectors += (63 - (numImgSectors % 63));
308 }
309
310 // Add +1 for our superblock which is at the end
311 if (Loop::createImageFile(asecFileName, numImgSectors + 1)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700312 SLOGE("ASEC image file creation failed (%s)", strerror(errno));
San Mehata19b2502010-01-06 10:33:53 -0800313 return -1;
314 }
315
San Mehatd9a4e352010-03-12 13:32:47 -0800316 char idHash[33];
317 if (!asecHash(id, idHash, sizeof(idHash))) {
San Mehat97ac40e2010-03-24 10:24:19 -0700318 SLOGE("Hash of '%s' failed (%s)", id, strerror(errno));
San Mehatd9a4e352010-03-12 13:32:47 -0800319 unlink(asecFileName);
320 return -1;
321 }
322
San Mehata19b2502010-01-06 10:33:53 -0800323 char loopDevice[255];
San Mehatd9a4e352010-03-12 13:32:47 -0800324 if (Loop::create(idHash, asecFileName, loopDevice, sizeof(loopDevice))) {
San Mehat97ac40e2010-03-24 10:24:19 -0700325 SLOGE("ASEC loop device creation failed (%s)", strerror(errno));
San Mehata19b2502010-01-06 10:33:53 -0800326 unlink(asecFileName);
327 return -1;
328 }
329
San Mehatb78a32c2010-01-10 13:02:12 -0800330 char dmDevice[255];
331 bool cleanupDm = false;
San Mehata19b2502010-01-06 10:33:53 -0800332
San Mehatb78a32c2010-01-10 13:02:12 -0800333 if (strcmp(key, "none")) {
San Mehatfcf24fe2010-03-03 12:37:32 -0800334 // XXX: This is all we support for now
335 sb.c_cipher = ASEC_SB_C_CIPHER_TWOFISH;
San Mehatd9a4e352010-03-12 13:32:47 -0800336 if (Devmapper::create(idHash, loopDevice, key, numImgSectors, dmDevice,
San Mehatb78a32c2010-01-10 13:02:12 -0800337 sizeof(dmDevice))) {
San Mehat97ac40e2010-03-24 10:24:19 -0700338 SLOGE("ASEC device mapping failed (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800339 Loop::destroyByDevice(loopDevice);
340 unlink(asecFileName);
341 return -1;
342 }
343 cleanupDm = true;
344 } else {
San Mehatfcf24fe2010-03-03 12:37:32 -0800345 sb.c_cipher = ASEC_SB_C_CIPHER_NONE;
San Mehatb78a32c2010-01-10 13:02:12 -0800346 strcpy(dmDevice, loopDevice);
347 }
348
San Mehatfcf24fe2010-03-03 12:37:32 -0800349 /*
350 * Drop down the superblock at the end of the file
351 */
352
353 int sbfd = open(loopDevice, O_RDWR);
354 if (sbfd < 0) {
San Mehat97ac40e2010-03-24 10:24:19 -0700355 SLOGE("Failed to open new DM device for superblock write (%s)", strerror(errno));
San Mehatfcf24fe2010-03-03 12:37:32 -0800356 if (cleanupDm) {
San Mehatd9a4e352010-03-12 13:32:47 -0800357 Devmapper::destroy(idHash);
San Mehatfcf24fe2010-03-03 12:37:32 -0800358 }
359 Loop::destroyByDevice(loopDevice);
360 unlink(asecFileName);
361 return -1;
362 }
363
364 if (lseek(sbfd, (numImgSectors * 512), SEEK_SET) < 0) {
365 close(sbfd);
San Mehat97ac40e2010-03-24 10:24:19 -0700366 SLOGE("Failed to lseek for superblock (%s)", strerror(errno));
San Mehatfcf24fe2010-03-03 12:37:32 -0800367 if (cleanupDm) {
San Mehatd9a4e352010-03-12 13:32:47 -0800368 Devmapper::destroy(idHash);
San Mehatfcf24fe2010-03-03 12:37:32 -0800369 }
370 Loop::destroyByDevice(loopDevice);
371 unlink(asecFileName);
372 return -1;
373 }
374
375 if (write(sbfd, &sb, sizeof(sb)) != sizeof(sb)) {
376 close(sbfd);
San Mehat97ac40e2010-03-24 10:24:19 -0700377 SLOGE("Failed to write superblock (%s)", strerror(errno));
San Mehatfcf24fe2010-03-03 12:37:32 -0800378 if (cleanupDm) {
San Mehatd9a4e352010-03-12 13:32:47 -0800379 Devmapper::destroy(idHash);
San Mehatfcf24fe2010-03-03 12:37:32 -0800380 }
381 Loop::destroyByDevice(loopDevice);
382 unlink(asecFileName);
383 return -1;
384 }
385 close(sbfd);
386
San Mehata1091cb2010-02-28 20:17:20 -0800387 if (strcmp(fstype, "none")) {
388 if (strcmp(fstype, "fat")) {
San Mehat97ac40e2010-03-24 10:24:19 -0700389 SLOGW("Unknown fstype '%s' specified for container", fstype);
San Mehatb78a32c2010-01-10 13:02:12 -0800390 }
San Mehata19b2502010-01-06 10:33:53 -0800391
San Mehatfcf24fe2010-03-03 12:37:32 -0800392 if (Fat::format(dmDevice, numImgSectors)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700393 SLOGE("ASEC FAT format failed (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800394 if (cleanupDm) {
San Mehatd9a4e352010-03-12 13:32:47 -0800395 Devmapper::destroy(idHash);
San Mehatb78a32c2010-01-10 13:02:12 -0800396 }
San Mehateb13a902010-01-07 12:12:50 -0800397 Loop::destroyByDevice(loopDevice);
398 unlink(asecFileName);
399 return -1;
400 }
San Mehata1091cb2010-02-28 20:17:20 -0800401 char mountPoint[255];
San Mehata19b2502010-01-06 10:33:53 -0800402
San Mehata1091cb2010-02-28 20:17:20 -0800403 snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id);
404 if (mkdir(mountPoint, 0777)) {
405 if (errno != EEXIST) {
San Mehat97ac40e2010-03-24 10:24:19 -0700406 SLOGE("Mountpoint creation failed (%s)", strerror(errno));
San Mehata1091cb2010-02-28 20:17:20 -0800407 if (cleanupDm) {
San Mehatd9a4e352010-03-12 13:32:47 -0800408 Devmapper::destroy(idHash);
San Mehata1091cb2010-02-28 20:17:20 -0800409 }
410 Loop::destroyByDevice(loopDevice);
411 unlink(asecFileName);
412 return -1;
413 }
San Mehatb78a32c2010-01-10 13:02:12 -0800414 }
San Mehata1091cb2010-02-28 20:17:20 -0800415
416 if (Fat::doMount(dmDevice, mountPoint, false, false, ownerUid,
417 0, 0000, false)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700418 SLOGE("ASEC FAT mount failed (%s)", strerror(errno));
San Mehata1091cb2010-02-28 20:17:20 -0800419 if (cleanupDm) {
San Mehatd9a4e352010-03-12 13:32:47 -0800420 Devmapper::destroy(idHash);
San Mehata1091cb2010-02-28 20:17:20 -0800421 }
422 Loop::destroyByDevice(loopDevice);
423 unlink(asecFileName);
424 return -1;
425 }
426 } else {
San Mehat97ac40e2010-03-24 10:24:19 -0700427 SLOGI("Created raw secure container %s (no filesystem)", id);
San Mehata19b2502010-01-06 10:33:53 -0800428 }
San Mehat88705162010-01-15 09:26:28 -0800429
430 mActiveContainers->push_back(strdup(id));
San Mehata19b2502010-01-06 10:33:53 -0800431 return 0;
432}
433
434int VolumeManager::finalizeAsec(const char *id) {
435 char asecFileName[255];
436 char loopDevice[255];
437 char mountPoint[255];
438
San Mehat3bb60202010-02-19 18:14:36 -0800439 snprintf(asecFileName, sizeof(asecFileName), "%s/%s.asec", Volume::SEC_ASECDIR, id);
San Mehata19b2502010-01-06 10:33:53 -0800440
San Mehatd9a4e352010-03-12 13:32:47 -0800441 char idHash[33];
442 if (!asecHash(id, idHash, sizeof(idHash))) {
San Mehat97ac40e2010-03-24 10:24:19 -0700443 SLOGE("Hash of '%s' failed (%s)", id, strerror(errno));
San Mehatd9a4e352010-03-12 13:32:47 -0800444 return -1;
445 }
446
447 if (Loop::lookupActive(idHash, loopDevice, sizeof(loopDevice))) {
San Mehat97ac40e2010-03-24 10:24:19 -0700448 SLOGE("Unable to finalize %s (%s)", id, strerror(errno));
San Mehata19b2502010-01-06 10:33:53 -0800449 return -1;
450 }
451
San Mehat3bb60202010-02-19 18:14:36 -0800452 snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id);
San Mehatfff0b472010-01-06 19:19:46 -0800453 // XXX:
454 if (Fat::doMount(loopDevice, mountPoint, true, true, 0, 0, 0227, false)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700455 SLOGE("ASEC finalize mount failed (%s)", strerror(errno));
San Mehata19b2502010-01-06 10:33:53 -0800456 return -1;
457 }
458
San Mehatd9a4e352010-03-12 13:32:47 -0800459 if (mDebug) {
San Mehat97ac40e2010-03-24 10:24:19 -0700460 SLOGD("ASEC %s finalized", id);
San Mehatd9a4e352010-03-12 13:32:47 -0800461 }
San Mehata19b2502010-01-06 10:33:53 -0800462 return 0;
463}
464
San Mehat048b0802010-01-23 08:17:06 -0800465int VolumeManager::renameAsec(const char *id1, const char *id2) {
466 char *asecFilename1;
467 char *asecFilename2;
468 char mountPoint[255];
469
San Mehat3bb60202010-02-19 18:14:36 -0800470 asprintf(&asecFilename1, "%s/%s.asec", Volume::SEC_ASECDIR, id1);
471 asprintf(&asecFilename2, "%s/%s.asec", Volume::SEC_ASECDIR, id2);
San Mehat048b0802010-01-23 08:17:06 -0800472
San Mehat3bb60202010-02-19 18:14:36 -0800473 snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id1);
San Mehat048b0802010-01-23 08:17:06 -0800474 if (isMountpointMounted(mountPoint)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700475 SLOGW("Rename attempt when src mounted");
San Mehat048b0802010-01-23 08:17:06 -0800476 errno = EBUSY;
477 goto out_err;
478 }
479
San Mehat96956ed2010-02-24 08:42:51 -0800480 snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id2);
481 if (isMountpointMounted(mountPoint)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700482 SLOGW("Rename attempt when dst mounted");
San Mehat96956ed2010-02-24 08:42:51 -0800483 errno = EBUSY;
484 goto out_err;
485 }
486
San Mehat048b0802010-01-23 08:17:06 -0800487 if (!access(asecFilename2, F_OK)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700488 SLOGE("Rename attempt when dst exists");
San Mehat048b0802010-01-23 08:17:06 -0800489 errno = EADDRINUSE;
490 goto out_err;
491 }
492
493 if (rename(asecFilename1, asecFilename2)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700494 SLOGE("Rename of '%s' to '%s' failed (%s)", asecFilename1, asecFilename2, strerror(errno));
San Mehat048b0802010-01-23 08:17:06 -0800495 goto out_err;
496 }
497
498 free(asecFilename1);
499 free(asecFilename2);
500 return 0;
501
502out_err:
503 free(asecFilename1);
504 free(asecFilename2);
505 return -1;
506}
507
Kenny Rootfb7c4d52010-06-30 18:48:41 -0700508#define UNMOUNT_RETRIES 5
509#define UNMOUNT_SLEEP_BETWEEN_RETRY_MS (1000 * 1000)
San Mehat4ba89482010-02-18 09:00:18 -0800510int VolumeManager::unmountAsec(const char *id, bool force) {
San Mehata19b2502010-01-06 10:33:53 -0800511 char asecFileName[255];
512 char mountPoint[255];
513
San Mehat3bb60202010-02-19 18:14:36 -0800514 snprintf(asecFileName, sizeof(asecFileName), "%s/%s.asec", Volume::SEC_ASECDIR, id);
515 snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id);
San Mehata19b2502010-01-06 10:33:53 -0800516
San Mehatd9a4e352010-03-12 13:32:47 -0800517 char idHash[33];
518 if (!asecHash(id, idHash, sizeof(idHash))) {
San Mehat97ac40e2010-03-24 10:24:19 -0700519 SLOGE("Hash of '%s' failed (%s)", id, strerror(errno));
San Mehatd9a4e352010-03-12 13:32:47 -0800520 return -1;
521 }
522
Kenny Rootfb7c4d52010-06-30 18:48:41 -0700523 return unmountLoopImage(id, idHash, asecFileName, mountPoint, force);
524}
525
526int VolumeManager::unmountImage(const char *fileName, bool force) {
527 char mountPoint[255];
528
529 char idHash[33];
530 if (!asecHash(fileName, idHash, sizeof(idHash))) {
531 SLOGE("Hash of '%s' failed (%s)", fileName, strerror(errno));
532 return -1;
533 }
534
535 snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::LOOPDIR, idHash);
536
537 return unmountLoopImage(fileName, idHash, fileName, mountPoint, force);
538}
539
540int VolumeManager::unmountLoopImage(const char *id, const char *idHash,
541 const char *fileName, const char *mountPoint, bool force) {
San Mehat0586d542010-01-12 15:38:59 -0800542 if (!isMountpointMounted(mountPoint)) {
Kenny Rootfb7c4d52010-06-30 18:48:41 -0700543 SLOGE("Unmount request for %s when not mounted", id);
San Mehatb78a32c2010-01-10 13:02:12 -0800544 errno = EINVAL;
545 return -1;
546 }
San Mehat23969932010-01-09 07:08:06 -0800547
San Mehatb78a32c2010-01-10 13:02:12 -0800548 int i, rc;
Kenny Rootfb7c4d52010-06-30 18:48:41 -0700549 for (i = 1; i <= UNMOUNT_RETRIES; i++) {
San Mehatb78a32c2010-01-10 13:02:12 -0800550 rc = umount(mountPoint);
551 if (!rc) {
552 break;
San Mehata19b2502010-01-06 10:33:53 -0800553 }
San Mehatb78a32c2010-01-10 13:02:12 -0800554 if (rc && (errno == EINVAL || errno == ENOENT)) {
Kenny Rootfb7c4d52010-06-30 18:48:41 -0700555 SLOGI("Container %s unmounted OK", id);
San Mehatb78a32c2010-01-10 13:02:12 -0800556 rc = 0;
557 break;
San Mehata19b2502010-01-06 10:33:53 -0800558 }
Kenny Rootfb7c4d52010-06-30 18:48:41 -0700559 SLOGW("%s unmount attempt %d failed (%s)",
San Mehat8c940ef2010-02-13 14:19:53 -0800560 id, i, strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800561
San Mehat4ba89482010-02-18 09:00:18 -0800562 int action = 0; // default is to just complain
563
564 if (force) {
Kenny Rootfb7c4d52010-06-30 18:48:41 -0700565 if (i > (UNMOUNT_RETRIES - 2))
San Mehat4ba89482010-02-18 09:00:18 -0800566 action = 2; // SIGKILL
Kenny Rootfb7c4d52010-06-30 18:48:41 -0700567 else if (i > (UNMOUNT_RETRIES - 3))
San Mehat4ba89482010-02-18 09:00:18 -0800568 action = 1; // SIGHUP
569 }
San Mehat8c940ef2010-02-13 14:19:53 -0800570
San Mehat586536c2010-02-16 17:12:00 -0800571 Process::killProcessesWithOpenFiles(mountPoint, action);
Kenny Rootfb7c4d52010-06-30 18:48:41 -0700572 usleep(UNMOUNT_SLEEP_BETWEEN_RETRY_MS);
San Mehatb78a32c2010-01-10 13:02:12 -0800573 }
574
575 if (rc) {
San Mehat4ba89482010-02-18 09:00:18 -0800576 errno = EBUSY;
San Mehat97ac40e2010-03-24 10:24:19 -0700577 SLOGE("Failed to unmount container %s (%s)", id, strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800578 return -1;
579 }
580
San Mehat12f4b892010-02-24 11:43:22 -0800581 int retries = 10;
582
583 while(retries--) {
584 if (!rmdir(mountPoint)) {
585 break;
586 }
587
San Mehat97ac40e2010-03-24 10:24:19 -0700588 SLOGW("Failed to rmdir %s (%s)", mountPoint, strerror(errno));
Kenny Rootfb7c4d52010-06-30 18:48:41 -0700589 usleep(UNMOUNT_SLEEP_BETWEEN_RETRY_MS);
San Mehat12f4b892010-02-24 11:43:22 -0800590 }
591
592 if (!retries) {
San Mehat97ac40e2010-03-24 10:24:19 -0700593 SLOGE("Timed out trying to rmdir %s (%s)", mountPoint, strerror(errno));
San Mehatf5c61982010-02-03 11:04:46 -0800594 }
San Mehat88705162010-01-15 09:26:28 -0800595
San Mehatd9a4e352010-03-12 13:32:47 -0800596 if (Devmapper::destroy(idHash) && errno != ENXIO) {
San Mehat97ac40e2010-03-24 10:24:19 -0700597 SLOGE("Failed to destroy devmapper instance (%s)", strerror(errno));
San Mehata19b2502010-01-06 10:33:53 -0800598 }
599
600 char loopDevice[255];
San Mehatd9a4e352010-03-12 13:32:47 -0800601 if (!Loop::lookupActive(idHash, loopDevice, sizeof(loopDevice))) {
San Mehata19b2502010-01-06 10:33:53 -0800602 Loop::destroyByDevice(loopDevice);
San Mehatd9a4e352010-03-12 13:32:47 -0800603 } else {
Kenny Rootfb7c4d52010-06-30 18:48:41 -0700604 SLOGW("Failed to find loop device for {%s} (%s)", fileName, strerror(errno));
San Mehata19b2502010-01-06 10:33:53 -0800605 }
San Mehat88705162010-01-15 09:26:28 -0800606
607 AsecIdCollection::iterator it;
608 for (it = mActiveContainers->begin(); it != mActiveContainers->end(); ++it) {
609 if (!strcmp(*it, id)) {
610 free(*it);
611 mActiveContainers->erase(it);
612 break;
613 }
614 }
615 if (it == mActiveContainers->end()) {
San Mehat97ac40e2010-03-24 10:24:19 -0700616 SLOGW("mActiveContainers is inconsistent!");
San Mehat88705162010-01-15 09:26:28 -0800617 }
San Mehatb78a32c2010-01-10 13:02:12 -0800618 return 0;
619}
620
San Mehat4ba89482010-02-18 09:00:18 -0800621int VolumeManager::destroyAsec(const char *id, bool force) {
San Mehatb78a32c2010-01-10 13:02:12 -0800622 char asecFileName[255];
623 char mountPoint[255];
624
San Mehat3bb60202010-02-19 18:14:36 -0800625 snprintf(asecFileName, sizeof(asecFileName), "%s/%s.asec", Volume::SEC_ASECDIR, id);
San Mehat55013f72010-02-24 12:12:34 -0800626 snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id);
San Mehatb78a32c2010-01-10 13:02:12 -0800627
San Mehat0586d542010-01-12 15:38:59 -0800628 if (isMountpointMounted(mountPoint)) {
San Mehatd9a4e352010-03-12 13:32:47 -0800629 if (mDebug) {
San Mehat97ac40e2010-03-24 10:24:19 -0700630 SLOGD("Unmounting container before destroy");
San Mehatd9a4e352010-03-12 13:32:47 -0800631 }
San Mehat4ba89482010-02-18 09:00:18 -0800632 if (unmountAsec(id, force)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700633 SLOGE("Failed to unmount asec %s for destroy (%s)", id, strerror(errno));
San Mehat0586d542010-01-12 15:38:59 -0800634 return -1;
635 }
636 }
San Mehata19b2502010-01-06 10:33:53 -0800637
San Mehat0586d542010-01-12 15:38:59 -0800638 if (unlink(asecFileName)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700639 SLOGE("Failed to unlink asec '%s' (%s)", asecFileName, strerror(errno));
San Mehat0586d542010-01-12 15:38:59 -0800640 return -1;
641 }
San Mehata19b2502010-01-06 10:33:53 -0800642
San Mehatd9a4e352010-03-12 13:32:47 -0800643 if (mDebug) {
San Mehat97ac40e2010-03-24 10:24:19 -0700644 SLOGD("ASEC %s destroyed", id);
San Mehatd9a4e352010-03-12 13:32:47 -0800645 }
San Mehata19b2502010-01-06 10:33:53 -0800646 return 0;
647}
648
649int VolumeManager::mountAsec(const char *id, const char *key, int ownerUid) {
650 char asecFileName[255];
651 char mountPoint[255];
652
San Mehat3bb60202010-02-19 18:14:36 -0800653 snprintf(asecFileName, sizeof(asecFileName), "%s/%s.asec", Volume::SEC_ASECDIR, id);
654 snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id);
San Mehata19b2502010-01-06 10:33:53 -0800655
656 if (isMountpointMounted(mountPoint)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700657 SLOGE("ASEC %s already mounted", id);
San Mehata19b2502010-01-06 10:33:53 -0800658 errno = EBUSY;
659 return -1;
660 }
661
San Mehatd9a4e352010-03-12 13:32:47 -0800662 char idHash[33];
663 if (!asecHash(id, idHash, sizeof(idHash))) {
San Mehat97ac40e2010-03-24 10:24:19 -0700664 SLOGE("Hash of '%s' failed (%s)", id, strerror(errno));
San Mehatd9a4e352010-03-12 13:32:47 -0800665 return -1;
666 }
Kenny Root7b18a7b2010-03-15 13:13:41 -0700667
San Mehata19b2502010-01-06 10:33:53 -0800668 char loopDevice[255];
San Mehatd9a4e352010-03-12 13:32:47 -0800669 if (Loop::lookupActive(idHash, loopDevice, sizeof(loopDevice))) {
670 if (Loop::create(idHash, asecFileName, loopDevice, sizeof(loopDevice))) {
San Mehat97ac40e2010-03-24 10:24:19 -0700671 SLOGE("ASEC loop device creation failed (%s)", strerror(errno));
San Mehata19b2502010-01-06 10:33:53 -0800672 return -1;
673 }
San Mehatd9a4e352010-03-12 13:32:47 -0800674 if (mDebug) {
San Mehat97ac40e2010-03-24 10:24:19 -0700675 SLOGD("New loop device created at %s", loopDevice);
San Mehatd9a4e352010-03-12 13:32:47 -0800676 }
San Mehatb78a32c2010-01-10 13:02:12 -0800677 } else {
San Mehatd9a4e352010-03-12 13:32:47 -0800678 if (mDebug) {
San Mehat97ac40e2010-03-24 10:24:19 -0700679 SLOGD("Found active loopback for %s at %s", asecFileName, loopDevice);
San Mehatd9a4e352010-03-12 13:32:47 -0800680 }
San Mehatb78a32c2010-01-10 13:02:12 -0800681 }
682
683 char dmDevice[255];
684 bool cleanupDm = false;
San Mehatfcf24fe2010-03-03 12:37:32 -0800685 int fd;
686 unsigned int nr_sec = 0;
687
688 if ((fd = open(loopDevice, O_RDWR)) < 0) {
San Mehat97ac40e2010-03-24 10:24:19 -0700689 SLOGE("Failed to open loopdevice (%s)", strerror(errno));
San Mehatfcf24fe2010-03-03 12:37:32 -0800690 Loop::destroyByDevice(loopDevice);
691 return -1;
692 }
693
694 if (ioctl(fd, BLKGETSIZE, &nr_sec)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700695 SLOGE("Failed to get loop size (%s)", strerror(errno));
San Mehatfcf24fe2010-03-03 12:37:32 -0800696 Loop::destroyByDevice(loopDevice);
697 close(fd);
698 return -1;
699 }
700
701 /*
702 * Validate superblock
703 */
704 struct asec_superblock sb;
705 memset(&sb, 0, sizeof(sb));
706 if (lseek(fd, ((nr_sec-1) * 512), SEEK_SET) < 0) {
San Mehat97ac40e2010-03-24 10:24:19 -0700707 SLOGE("lseek failed (%s)", strerror(errno));
San Mehatfcf24fe2010-03-03 12:37:32 -0800708 close(fd);
709 Loop::destroyByDevice(loopDevice);
710 return -1;
711 }
712 if (read(fd, &sb, sizeof(sb)) != sizeof(sb)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700713 SLOGE("superblock read failed (%s)", strerror(errno));
San Mehatfcf24fe2010-03-03 12:37:32 -0800714 close(fd);
715 Loop::destroyByDevice(loopDevice);
716 return -1;
717 }
718
719 close(fd);
720
San Mehatd9a4e352010-03-12 13:32:47 -0800721 if (mDebug) {
San Mehat97ac40e2010-03-24 10:24:19 -0700722 SLOGD("Container sb magic/ver (%.8x/%.2x)", sb.magic, sb.ver);
San Mehatd9a4e352010-03-12 13:32:47 -0800723 }
San Mehatfcf24fe2010-03-03 12:37:32 -0800724 if (sb.magic != ASEC_SB_MAGIC || sb.ver != ASEC_SB_VER) {
San Mehat97ac40e2010-03-24 10:24:19 -0700725 SLOGE("Bad container magic/version (%.8x/%.2x)", sb.magic, sb.ver);
San Mehatfcf24fe2010-03-03 12:37:32 -0800726 Loop::destroyByDevice(loopDevice);
727 errno = EMEDIUMTYPE;
728 return -1;
729 }
730 nr_sec--; // We don't want the devmapping to extend onto our superblock
731
San Mehatb78a32c2010-01-10 13:02:12 -0800732 if (strcmp(key, "none")) {
San Mehatd9a4e352010-03-12 13:32:47 -0800733 if (Devmapper::lookupActive(idHash, dmDevice, sizeof(dmDevice))) {
734 if (Devmapper::create(idHash, loopDevice, key, nr_sec,
San Mehatb78a32c2010-01-10 13:02:12 -0800735 dmDevice, sizeof(dmDevice))) {
San Mehat97ac40e2010-03-24 10:24:19 -0700736 SLOGE("ASEC device mapping failed (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800737 Loop::destroyByDevice(loopDevice);
738 return -1;
739 }
San Mehatd9a4e352010-03-12 13:32:47 -0800740 if (mDebug) {
San Mehat97ac40e2010-03-24 10:24:19 -0700741 SLOGD("New devmapper instance created at %s", dmDevice);
San Mehatd9a4e352010-03-12 13:32:47 -0800742 }
San Mehatb78a32c2010-01-10 13:02:12 -0800743 } else {
San Mehatd9a4e352010-03-12 13:32:47 -0800744 if (mDebug) {
San Mehat97ac40e2010-03-24 10:24:19 -0700745 SLOGD("Found active devmapper for %s at %s", asecFileName, dmDevice);
San Mehatd9a4e352010-03-12 13:32:47 -0800746 }
San Mehatb78a32c2010-01-10 13:02:12 -0800747 }
748 cleanupDm = true;
749 } else {
750 strcpy(dmDevice, loopDevice);
San Mehata19b2502010-01-06 10:33:53 -0800751 }
752
753 if (mkdir(mountPoint, 0777)) {
San Mehatb78a32c2010-01-10 13:02:12 -0800754 if (errno != EEXIST) {
San Mehat97ac40e2010-03-24 10:24:19 -0700755 SLOGE("Mountpoint creation failed (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800756 if (cleanupDm) {
San Mehatd9a4e352010-03-12 13:32:47 -0800757 Devmapper::destroy(idHash);
San Mehatb78a32c2010-01-10 13:02:12 -0800758 }
759 Loop::destroyByDevice(loopDevice);
760 return -1;
761 }
San Mehata19b2502010-01-06 10:33:53 -0800762 }
763
San Mehatb78a32c2010-01-10 13:02:12 -0800764 if (Fat::doMount(dmDevice, mountPoint, true, false, ownerUid, 0,
San Mehatcff5ec32010-01-08 12:31:44 -0800765 0222, false)) {
766// 0227, false)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700767 SLOGE("ASEC mount failed (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800768 if (cleanupDm) {
San Mehatd9a4e352010-03-12 13:32:47 -0800769 Devmapper::destroy(idHash);
San Mehatb78a32c2010-01-10 13:02:12 -0800770 }
771 Loop::destroyByDevice(loopDevice);
San Mehata19b2502010-01-06 10:33:53 -0800772 return -1;
773 }
774
San Mehat88705162010-01-15 09:26:28 -0800775 mActiveContainers->push_back(strdup(id));
San Mehatd9a4e352010-03-12 13:32:47 -0800776 if (mDebug) {
San Mehat97ac40e2010-03-24 10:24:19 -0700777 SLOGD("ASEC %s mounted", id);
San Mehatd9a4e352010-03-12 13:32:47 -0800778 }
San Mehata19b2502010-01-06 10:33:53 -0800779 return 0;
780}
781
Kenny Rootfb7c4d52010-06-30 18:48:41 -0700782/**
783 * Mounts an image file <code>img</code>.
784 */
785int VolumeManager::mountImage(const char *img, const char *key, int ownerUid) {
786 char mountPoint[255];
787
788#if 0
789 struct stat imgStat;
790 if (stat(img, &imgStat) != 0) {
791 SLOGE("Could not stat '%s': %s", img, strerror(errno));
792 return -1;
793 }
794
795 if (imgStat.st_uid != ownerUid) {
796 SLOGW("Image UID does not match requestor UID (%d != %d)",
797 imgStat.st_uid, ownerUid);
798 return -1;
799 }
800#endif
801
802 char idHash[33];
803 if (!asecHash(img, idHash, sizeof(idHash))) {
804 SLOGE("Hash of '%s' failed (%s)", img, strerror(errno));
805 return -1;
806 }
807
808 snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::LOOPDIR, idHash);
809
810 if (isMountpointMounted(mountPoint)) {
811 SLOGE("Image %s already mounted", img);
812 errno = EBUSY;
813 return -1;
814 }
815
816 char loopDevice[255];
817 if (Loop::lookupActive(idHash, loopDevice, sizeof(loopDevice))) {
818 if (Loop::create(idHash, img, loopDevice, sizeof(loopDevice))) {
819 SLOGE("Image loop device creation failed (%s)", strerror(errno));
820 return -1;
821 }
822 if (mDebug) {
823 SLOGD("New loop device created at %s", loopDevice);
824 }
825 } else {
826 if (mDebug) {
827 SLOGD("Found active loopback for %s at %s", img, loopDevice);
828 }
829 }
830
831 char dmDevice[255];
832 bool cleanupDm = false;
833 int fd;
834 unsigned int nr_sec = 0;
835
836 if ((fd = open(loopDevice, O_RDWR)) < 0) {
837 SLOGE("Failed to open loopdevice (%s)", strerror(errno));
838 Loop::destroyByDevice(loopDevice);
839 return -1;
840 }
841
842 if (ioctl(fd, BLKGETSIZE, &nr_sec)) {
843 SLOGE("Failed to get loop size (%s)", strerror(errno));
844 Loop::destroyByDevice(loopDevice);
845 close(fd);
846 return -1;
847 }
848
849 close(fd);
850
851 if (strcmp(key, "none")) {
852 if (Devmapper::lookupActive(idHash, dmDevice, sizeof(dmDevice))) {
853 if (Devmapper::create(idHash, loopDevice, key, nr_sec,
854 dmDevice, sizeof(dmDevice))) {
855 SLOGE("ASEC device mapping failed (%s)", strerror(errno));
856 Loop::destroyByDevice(loopDevice);
857 return -1;
858 }
859 if (mDebug) {
860 SLOGD("New devmapper instance created at %s", dmDevice);
861 }
862 } else {
863 if (mDebug) {
864 SLOGD("Found active devmapper for %s at %s", img, dmDevice);
865 }
866 }
867 cleanupDm = true;
868 } else {
869 strcpy(dmDevice, loopDevice);
870 }
871
872 if (mkdir(mountPoint, 0755)) {
873 if (errno != EEXIST) {
874 SLOGE("Mountpoint creation failed (%s)", strerror(errno));
875 if (cleanupDm) {
876 Devmapper::destroy(idHash);
877 }
878 Loop::destroyByDevice(loopDevice);
879 return -1;
880 }
881 }
882
883 if (Fat::doMount(dmDevice, mountPoint, true, false, ownerUid, 0,
884 0227, false)) {
885 SLOGE("Image mount failed (%s)", strerror(errno));
886 if (cleanupDm) {
887 Devmapper::destroy(idHash);
888 }
889 Loop::destroyByDevice(loopDevice);
890 return -1;
891 }
892
893 mActiveContainers->push_back(strdup(img));
894 if (mDebug) {
895 SLOGD("Image %s mounted", img);
896 }
897 return 0;
898}
899
San Mehat49e2bce2009-10-12 16:29:01 -0700900int VolumeManager::mountVolume(const char *label) {
901 Volume *v = lookupVolume(label);
902
903 if (!v) {
904 errno = ENOENT;
905 return -1;
906 }
907
San Mehata2677e42009-12-13 10:40:18 -0800908 return v->mountVol();
909}
910
911int VolumeManager::shareAvailable(const char *method, bool *avail) {
912
913 if (strcmp(method, "ums")) {
914 errno = ENOSYS;
915 return -1;
916 }
917
Mike Lockwood99635f62010-06-25 23:04:04 -0400918 *avail = massStorageAvailable();
San Mehata2677e42009-12-13 10:40:18 -0800919 return 0;
920}
921
San Mehateba65e92010-01-29 05:15:16 -0800922int VolumeManager::shareEnabled(const char *label, const char *method, bool *enabled) {
923 Volume *v = lookupVolume(label);
924
925 if (!v) {
926 errno = ENOENT;
927 return -1;
928 }
929
930 if (strcmp(method, "ums")) {
931 errno = ENOSYS;
932 return -1;
933 }
934
935 if (v->getState() != Volume::State_Shared) {
San Mehateba65e92010-01-29 05:15:16 -0800936 *enabled = false;
San Mehatb9aed742010-02-04 15:07:01 -0800937 } else {
938 *enabled = true;
San Mehateba65e92010-01-29 05:15:16 -0800939 }
940 return 0;
941}
942
San Mehata2677e42009-12-13 10:40:18 -0800943int VolumeManager::simulate(const char *cmd, const char *arg) {
944
945 if (!strcmp(cmd, "ums")) {
946 if (!strcmp(arg, "connect")) {
Mike Lockwood99635f62010-06-25 23:04:04 -0400947 notifyUmsAvailable(true);
San Mehata2677e42009-12-13 10:40:18 -0800948 } else if (!strcmp(arg, "disconnect")) {
Mike Lockwood99635f62010-06-25 23:04:04 -0400949 notifyUmsAvailable(false);
San Mehata2677e42009-12-13 10:40:18 -0800950 } else {
951 errno = EINVAL;
952 return -1;
953 }
954 } else {
955 errno = EINVAL;
956 return -1;
957 }
958 return 0;
959}
960
961int VolumeManager::shareVolume(const char *label, const char *method) {
962 Volume *v = lookupVolume(label);
963
964 if (!v) {
965 errno = ENOENT;
966 return -1;
967 }
968
969 /*
970 * Eventually, we'll want to support additional share back-ends,
971 * some of which may work while the media is mounted. For now,
972 * we just support UMS
973 */
974 if (strcmp(method, "ums")) {
975 errno = ENOSYS;
976 return -1;
977 }
978
979 if (v->getState() == Volume::State_NoMedia) {
980 errno = ENODEV;
981 return -1;
982 }
983
San Mehat49e2bce2009-10-12 16:29:01 -0700984 if (v->getState() != Volume::State_Idle) {
San Mehata2677e42009-12-13 10:40:18 -0800985 // You need to unmount manually befoe sharing
San Mehat49e2bce2009-10-12 16:29:01 -0700986 errno = EBUSY;
987 return -1;
988 }
989
San Mehata2677e42009-12-13 10:40:18 -0800990 dev_t d = v->getDiskDevice();
991 if ((MAJOR(d) == 0) && (MINOR(d) == 0)) {
992 // This volume does not support raw disk access
993 errno = EINVAL;
994 return -1;
995 }
996
997 int fd;
998 char nodepath[255];
999 snprintf(nodepath,
1000 sizeof(nodepath), "/dev/block/vold/%d:%d",
1001 MAJOR(d), MINOR(d));
1002
San Mehat0cde53c2009-12-22 08:32:33 -08001003 if ((fd = open("/sys/devices/platform/usb_mass_storage/lun0/file",
1004 O_WRONLY)) < 0) {
San Mehat97ac40e2010-03-24 10:24:19 -07001005 SLOGE("Unable to open ums lunfile (%s)", strerror(errno));
San Mehata2677e42009-12-13 10:40:18 -08001006 return -1;
1007 }
1008
1009 if (write(fd, nodepath, strlen(nodepath)) < 0) {
San Mehat97ac40e2010-03-24 10:24:19 -07001010 SLOGE("Unable to write to ums lunfile (%s)", strerror(errno));
San Mehata2677e42009-12-13 10:40:18 -08001011 close(fd);
1012 return -1;
1013 }
1014
1015 close(fd);
1016 v->handleVolumeShared();
1017 return 0;
1018}
1019
1020int VolumeManager::unshareVolume(const char *label, const char *method) {
1021 Volume *v = lookupVolume(label);
1022
1023 if (!v) {
1024 errno = ENOENT;
1025 return -1;
1026 }
1027
1028 if (strcmp(method, "ums")) {
1029 errno = ENOSYS;
1030 return -1;
1031 }
1032
1033 if (v->getState() != Volume::State_Shared) {
1034 errno = EINVAL;
1035 return -1;
1036 }
1037
1038 dev_t d = v->getDiskDevice();
1039
1040 int fd;
1041 char nodepath[255];
1042 snprintf(nodepath,
1043 sizeof(nodepath), "/dev/block/vold/%d:%d",
1044 MAJOR(d), MINOR(d));
1045
San Mehat0cde53c2009-12-22 08:32:33 -08001046 if ((fd = open("/sys/devices/platform/usb_mass_storage/lun0/file", O_WRONLY)) < 0) {
San Mehat97ac40e2010-03-24 10:24:19 -07001047 SLOGE("Unable to open ums lunfile (%s)", strerror(errno));
San Mehata2677e42009-12-13 10:40:18 -08001048 return -1;
1049 }
1050
1051 char ch = 0;
1052 if (write(fd, &ch, 1) < 0) {
San Mehat97ac40e2010-03-24 10:24:19 -07001053 SLOGE("Unable to write to ums lunfile (%s)", strerror(errno));
San Mehata2677e42009-12-13 10:40:18 -08001054 close(fd);
1055 return -1;
1056 }
1057
1058 close(fd);
1059 v->handleVolumeUnshared();
1060 return 0;
San Mehat49e2bce2009-10-12 16:29:01 -07001061}
1062
San Mehat4ba89482010-02-18 09:00:18 -08001063int VolumeManager::unmountVolume(const char *label, bool force) {
San Mehat49e2bce2009-10-12 16:29:01 -07001064 Volume *v = lookupVolume(label);
1065
1066 if (!v) {
1067 errno = ENOENT;
1068 return -1;
1069 }
1070
San Mehata2677e42009-12-13 10:40:18 -08001071 if (v->getState() == Volume::State_NoMedia) {
1072 errno = ENODEV;
1073 return -1;
1074 }
1075
San Mehat49e2bce2009-10-12 16:29:01 -07001076 if (v->getState() != Volume::State_Mounted) {
San Mehat97ac40e2010-03-24 10:24:19 -07001077 SLOGW("Attempt to unmount volume which isn't mounted (%d)\n",
San Mehata2677e42009-12-13 10:40:18 -08001078 v->getState());
San Mehat49e2bce2009-10-12 16:29:01 -07001079 errno = EBUSY;
1080 return -1;
1081 }
1082
San Mehat1a06eda2010-04-15 12:58:50 -07001083 cleanupAsec(v, force);
San Mehat88705162010-01-15 09:26:28 -08001084
San Mehat4ba89482010-02-18 09:00:18 -08001085 return v->unmountVol(force);
San Mehat49e2bce2009-10-12 16:29:01 -07001086}
1087
San Mehata2677e42009-12-13 10:40:18 -08001088/*
1089 * Looks up a volume by it's label or mount-point
1090 */
San Mehat49e2bce2009-10-12 16:29:01 -07001091Volume *VolumeManager::lookupVolume(const char *label) {
1092 VolumeCollection::iterator i;
1093
1094 for (i = mVolumes->begin(); i != mVolumes->end(); ++i) {
San Mehata2677e42009-12-13 10:40:18 -08001095 if (label[0] == '/') {
1096 if (!strcmp(label, (*i)->getMountpoint()))
1097 return (*i);
1098 } else {
1099 if (!strcmp(label, (*i)->getLabel()))
1100 return (*i);
1101 }
San Mehat49e2bce2009-10-12 16:29:01 -07001102 }
1103 return NULL;
1104}
San Mehata19b2502010-01-06 10:33:53 -08001105
1106bool VolumeManager::isMountpointMounted(const char *mp)
1107{
1108 char device[256];
1109 char mount_path[256];
1110 char rest[256];
1111 FILE *fp;
1112 char line[1024];
1113
1114 if (!(fp = fopen("/proc/mounts", "r"))) {
San Mehat97ac40e2010-03-24 10:24:19 -07001115 SLOGE("Error opening /proc/mounts (%s)", strerror(errno));
San Mehata19b2502010-01-06 10:33:53 -08001116 return false;
1117 }
1118
1119 while(fgets(line, sizeof(line), fp)) {
1120 line[strlen(line)-1] = '\0';
1121 sscanf(line, "%255s %255s %255s\n", device, mount_path, rest);
1122 if (!strcmp(mount_path, mp)) {
1123 fclose(fp);
1124 return true;
1125 }
San Mehata19b2502010-01-06 10:33:53 -08001126 }
1127
1128 fclose(fp);
1129 return false;
1130}
1131
San Mehat1a06eda2010-04-15 12:58:50 -07001132int VolumeManager::cleanupAsec(Volume *v, bool force) {
1133 while(mActiveContainers->size()) {
1134 AsecIdCollection::iterator it = mActiveContainers->begin();
1135 SLOGI("Unmounting ASEC %s (dependant on %s)", *it, v->getMountpoint());
1136 if (unmountAsec(*it, force)) {
1137 SLOGE("Failed to unmount ASEC %s (%s)", *it, strerror(errno));
1138 return -1;
1139 }
1140 }
1141 return 0;
1142}
1143