blob: c41baf3fce9c16401ab761610cd2178b0339399e [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
San Mehatf1b736b2009-10-10 17:22:08 -070046VolumeManager *VolumeManager::sInstance = NULL;
47
48VolumeManager *VolumeManager::Instance() {
49 if (!sInstance)
50 sInstance = new VolumeManager();
51 return sInstance;
52}
53
54VolumeManager::VolumeManager() {
San Mehatd9a4e352010-03-12 13:32:47 -080055 mDebug = false;
San Mehatf1b736b2009-10-10 17:22:08 -070056 mVolumes = new VolumeCollection();
San Mehat88705162010-01-15 09:26:28 -080057 mActiveContainers = new AsecIdCollection();
San Mehatf1b736b2009-10-10 17:22:08 -070058 mBroadcaster = NULL;
Mike Lockwooda28056b2010-10-28 15:21:24 -040059 mUmsSharingCount = 0;
60 mSavedDirtyRatio = -1;
61 // set dirty ratio to 0 when UMS is active
62 mUmsDirtyRatio = 0;
San Mehatf1b736b2009-10-10 17:22:08 -070063}
64
65VolumeManager::~VolumeManager() {
San Mehat88705162010-01-15 09:26:28 -080066 delete mVolumes;
67 delete mActiveContainers;
San Mehatf1b736b2009-10-10 17:22:08 -070068}
69
Kenny Root7b18a7b2010-03-15 13:13:41 -070070char *VolumeManager::asecHash(const char *id, char *buffer, size_t len) {
Kenny Rootacc9e7d2010-06-18 19:06:50 -070071 static const char* digits = "0123456789abcdef";
72
Kenny Root7b18a7b2010-03-15 13:13:41 -070073 unsigned char sig[MD5_DIGEST_LENGTH];
74
Kenny Rootacc9e7d2010-06-18 19:06:50 -070075 if (buffer == NULL) {
76 SLOGE("Destination buffer is NULL");
77 errno = ESPIPE;
78 return NULL;
79 } else if (id == NULL) {
80 SLOGE("Source buffer is NULL");
81 errno = ESPIPE;
82 return NULL;
83 } else if (len < MD5_ASCII_LENGTH_PLUS_NULL) {
84 SLOGE("Target hash buffer size < %d bytes (%d)",
85 MD5_ASCII_LENGTH_PLUS_NULL, len);
San Mehatd9a4e352010-03-12 13:32:47 -080086 errno = ESPIPE;
87 return NULL;
88 }
Kenny Root7b18a7b2010-03-15 13:13:41 -070089
90 MD5(reinterpret_cast<const unsigned char*>(id), strlen(id), sig);
San Mehatd9a4e352010-03-12 13:32:47 -080091
Kenny Rootacc9e7d2010-06-18 19:06:50 -070092 char *p = buffer;
Kenny Root7b18a7b2010-03-15 13:13:41 -070093 for (int i = 0; i < MD5_DIGEST_LENGTH; i++) {
Kenny Rootacc9e7d2010-06-18 19:06:50 -070094 *p++ = digits[sig[i] >> 4];
95 *p++ = digits[sig[i] & 0x0F];
San Mehatd9a4e352010-03-12 13:32:47 -080096 }
Kenny Rootacc9e7d2010-06-18 19:06:50 -070097 *p = '\0';
San Mehatd9a4e352010-03-12 13:32:47 -080098
99 return buffer;
100}
101
102void VolumeManager::setDebug(bool enable) {
103 mDebug = enable;
104 VolumeCollection::iterator it;
105 for (it = mVolumes->begin(); it != mVolumes->end(); ++it) {
106 (*it)->setDebug(enable);
107 }
108}
109
San Mehatf1b736b2009-10-10 17:22:08 -0700110int VolumeManager::start() {
111 return 0;
112}
113
114int VolumeManager::stop() {
115 return 0;
116}
117
118int VolumeManager::addVolume(Volume *v) {
119 mVolumes->push_back(v);
120 return 0;
121}
122
San Mehatfd7f5872009-10-12 11:32:47 -0700123void VolumeManager::handleBlockEvent(NetlinkEvent *evt) {
124 const char *devpath = evt->findParam("DEVPATH");
San Mehatf1b736b2009-10-10 17:22:08 -0700125
San Mehatfd7f5872009-10-12 11:32:47 -0700126 /* Lookup a volume to handle this device */
San Mehatf1b736b2009-10-10 17:22:08 -0700127 VolumeCollection::iterator it;
128 bool hit = false;
129 for (it = mVolumes->begin(); it != mVolumes->end(); ++it) {
San Mehatfd7f5872009-10-12 11:32:47 -0700130 if (!(*it)->handleBlockEvent(evt)) {
San Mehata2677e42009-12-13 10:40:18 -0800131#ifdef NETLINK_DEBUG
San Mehat97ac40e2010-03-24 10:24:19 -0700132 SLOGD("Device '%s' event handled by volume %s\n", devpath, (*it)->getLabel());
San Mehata2677e42009-12-13 10:40:18 -0800133#endif
San Mehatf1b736b2009-10-10 17:22:08 -0700134 hit = true;
San Mehatf1b736b2009-10-10 17:22:08 -0700135 break;
136 }
137 }
138
139 if (!hit) {
San Mehata2677e42009-12-13 10:40:18 -0800140#ifdef NETLINK_DEBUG
San Mehat97ac40e2010-03-24 10:24:19 -0700141 SLOGW("No volumes handled block event for '%s'", devpath);
San Mehata2677e42009-12-13 10:40:18 -0800142#endif
San Mehatf1b736b2009-10-10 17:22:08 -0700143 }
144}
145
San Mehatf1b736b2009-10-10 17:22:08 -0700146int VolumeManager::listVolumes(SocketClient *cli) {
147 VolumeCollection::iterator i;
148
149 for (i = mVolumes->begin(); i != mVolumes->end(); ++i) {
150 char *buffer;
151 asprintf(&buffer, "%s %s %d",
152 (*i)->getLabel(), (*i)->getMountpoint(),
153 (*i)->getState());
San Mehata2677e42009-12-13 10:40:18 -0800154 cli->sendMsg(ResponseCode::VolumeListResult, buffer, false);
San Mehatf1b736b2009-10-10 17:22:08 -0700155 free(buffer);
156 }
San Mehata2677e42009-12-13 10:40:18 -0800157 cli->sendMsg(ResponseCode::CommandOkay, "Volumes listed.", false);
San Mehatf1b736b2009-10-10 17:22:08 -0700158 return 0;
159}
San Mehat49e2bce2009-10-12 16:29:01 -0700160
San Mehata2677e42009-12-13 10:40:18 -0800161int VolumeManager::formatVolume(const char *label) {
162 Volume *v = lookupVolume(label);
163
164 if (!v) {
165 errno = ENOENT;
166 return -1;
167 }
168
169 return v->formatVol();
170}
171
Kenny Root508c0e12010-07-12 09:59:49 -0700172int VolumeManager::getObbMountPath(const char *sourceFile, char *mountPath, int mountPathLen) {
173 char idHash[33];
174 if (!asecHash(sourceFile, idHash, sizeof(idHash))) {
175 SLOGE("Hash of '%s' failed (%s)", sourceFile, strerror(errno));
176 return -1;
177 }
178
179 memset(mountPath, 0, mountPathLen);
180 snprintf(mountPath, mountPathLen, "%s/%s", Volume::LOOPDIR, idHash);
181
182 if (access(mountPath, F_OK)) {
183 errno = ENOENT;
184 return -1;
185 }
186
187 return 0;
188}
189
San Mehata19b2502010-01-06 10:33:53 -0800190int VolumeManager::getAsecMountPath(const char *id, char *buffer, int maxlen) {
San Mehat88ac2c02010-03-23 11:15:58 -0700191 char asecFileName[255];
192 snprintf(asecFileName, sizeof(asecFileName), "%s/%s.asec", Volume::SEC_ASECDIR, id);
193
194 memset(buffer, 0, maxlen);
195 if (access(asecFileName, F_OK)) {
196 errno = ENOENT;
197 return -1;
198 }
San Mehata19b2502010-01-06 10:33:53 -0800199
San Mehat3bb60202010-02-19 18:14:36 -0800200 snprintf(buffer, maxlen, "%s/%s", Volume::ASECDIR, id);
San Mehata19b2502010-01-06 10:33:53 -0800201 return 0;
202}
203
San Mehat8b8f71b2010-01-11 09:17:25 -0800204int VolumeManager::createAsec(const char *id, unsigned int numSectors,
San Mehata19b2502010-01-06 10:33:53 -0800205 const char *fstype, const char *key, int ownerUid) {
San Mehatfcf24fe2010-03-03 12:37:32 -0800206 struct asec_superblock sb;
207 memset(&sb, 0, sizeof(sb));
208
209 sb.magic = ASEC_SB_MAGIC;
210 sb.ver = ASEC_SB_VER;
San Mehata19b2502010-01-06 10:33:53 -0800211
San Mehatd31e3802010-02-18 08:37:45 -0800212 if (numSectors < ((1024*1024)/512)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700213 SLOGE("Invalid container size specified (%d sectors)", numSectors);
San Mehatd31e3802010-02-18 08:37:45 -0800214 errno = EINVAL;
215 return -1;
216 }
217
San Mehata19b2502010-01-06 10:33:53 -0800218 if (lookupVolume(id)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700219 SLOGE("ASEC id '%s' currently exists", id);
San Mehata19b2502010-01-06 10:33:53 -0800220 errno = EADDRINUSE;
221 return -1;
222 }
223
224 char asecFileName[255];
San Mehat3bb60202010-02-19 18:14:36 -0800225 snprintf(asecFileName, sizeof(asecFileName), "%s/%s.asec", Volume::SEC_ASECDIR, id);
San Mehata19b2502010-01-06 10:33:53 -0800226
227 if (!access(asecFileName, F_OK)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700228 SLOGE("ASEC file '%s' currently exists - destroy it first! (%s)",
San Mehata19b2502010-01-06 10:33:53 -0800229 asecFileName, strerror(errno));
230 errno = EADDRINUSE;
231 return -1;
232 }
233
San Mehatfcf24fe2010-03-03 12:37:32 -0800234 /*
235 * Add some headroom
236 */
237 unsigned fatSize = (((numSectors * 4) / 512) + 1) * 2;
238 unsigned numImgSectors = numSectors + fatSize + 2;
239
240 if (numImgSectors % 63) {
241 numImgSectors += (63 - (numImgSectors % 63));
242 }
243
244 // Add +1 for our superblock which is at the end
245 if (Loop::createImageFile(asecFileName, numImgSectors + 1)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700246 SLOGE("ASEC image file creation failed (%s)", strerror(errno));
San Mehata19b2502010-01-06 10:33:53 -0800247 return -1;
248 }
249
San Mehatd9a4e352010-03-12 13:32:47 -0800250 char idHash[33];
251 if (!asecHash(id, idHash, sizeof(idHash))) {
San Mehat97ac40e2010-03-24 10:24:19 -0700252 SLOGE("Hash of '%s' failed (%s)", id, strerror(errno));
San Mehatd9a4e352010-03-12 13:32:47 -0800253 unlink(asecFileName);
254 return -1;
255 }
256
San Mehata19b2502010-01-06 10:33:53 -0800257 char loopDevice[255];
San Mehatd9a4e352010-03-12 13:32:47 -0800258 if (Loop::create(idHash, asecFileName, loopDevice, sizeof(loopDevice))) {
San Mehat97ac40e2010-03-24 10:24:19 -0700259 SLOGE("ASEC loop device creation failed (%s)", strerror(errno));
San Mehata19b2502010-01-06 10:33:53 -0800260 unlink(asecFileName);
261 return -1;
262 }
263
San Mehatb78a32c2010-01-10 13:02:12 -0800264 char dmDevice[255];
265 bool cleanupDm = false;
San Mehata19b2502010-01-06 10:33:53 -0800266
San Mehatb78a32c2010-01-10 13:02:12 -0800267 if (strcmp(key, "none")) {
San Mehatfcf24fe2010-03-03 12:37:32 -0800268 // XXX: This is all we support for now
269 sb.c_cipher = ASEC_SB_C_CIPHER_TWOFISH;
San Mehatd9a4e352010-03-12 13:32:47 -0800270 if (Devmapper::create(idHash, loopDevice, key, numImgSectors, dmDevice,
San Mehatb78a32c2010-01-10 13:02:12 -0800271 sizeof(dmDevice))) {
San Mehat97ac40e2010-03-24 10:24:19 -0700272 SLOGE("ASEC device mapping failed (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800273 Loop::destroyByDevice(loopDevice);
274 unlink(asecFileName);
275 return -1;
276 }
277 cleanupDm = true;
278 } else {
San Mehatfcf24fe2010-03-03 12:37:32 -0800279 sb.c_cipher = ASEC_SB_C_CIPHER_NONE;
San Mehatb78a32c2010-01-10 13:02:12 -0800280 strcpy(dmDevice, loopDevice);
281 }
282
San Mehatfcf24fe2010-03-03 12:37:32 -0800283 /*
284 * Drop down the superblock at the end of the file
285 */
286
287 int sbfd = open(loopDevice, O_RDWR);
288 if (sbfd < 0) {
San Mehat97ac40e2010-03-24 10:24:19 -0700289 SLOGE("Failed to open new DM device for superblock write (%s)", strerror(errno));
San Mehatfcf24fe2010-03-03 12:37:32 -0800290 if (cleanupDm) {
San Mehatd9a4e352010-03-12 13:32:47 -0800291 Devmapper::destroy(idHash);
San Mehatfcf24fe2010-03-03 12:37:32 -0800292 }
293 Loop::destroyByDevice(loopDevice);
294 unlink(asecFileName);
295 return -1;
296 }
297
298 if (lseek(sbfd, (numImgSectors * 512), SEEK_SET) < 0) {
299 close(sbfd);
San Mehat97ac40e2010-03-24 10:24:19 -0700300 SLOGE("Failed to lseek for superblock (%s)", strerror(errno));
San Mehatfcf24fe2010-03-03 12:37:32 -0800301 if (cleanupDm) {
San Mehatd9a4e352010-03-12 13:32:47 -0800302 Devmapper::destroy(idHash);
San Mehatfcf24fe2010-03-03 12:37:32 -0800303 }
304 Loop::destroyByDevice(loopDevice);
305 unlink(asecFileName);
306 return -1;
307 }
308
309 if (write(sbfd, &sb, sizeof(sb)) != sizeof(sb)) {
310 close(sbfd);
San Mehat97ac40e2010-03-24 10:24:19 -0700311 SLOGE("Failed to write superblock (%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 close(sbfd);
320
San Mehata1091cb2010-02-28 20:17:20 -0800321 if (strcmp(fstype, "none")) {
322 if (strcmp(fstype, "fat")) {
San Mehat97ac40e2010-03-24 10:24:19 -0700323 SLOGW("Unknown fstype '%s' specified for container", fstype);
San Mehatb78a32c2010-01-10 13:02:12 -0800324 }
San Mehata19b2502010-01-06 10:33:53 -0800325
San Mehatfcf24fe2010-03-03 12:37:32 -0800326 if (Fat::format(dmDevice, numImgSectors)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700327 SLOGE("ASEC FAT format failed (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800328 if (cleanupDm) {
San Mehatd9a4e352010-03-12 13:32:47 -0800329 Devmapper::destroy(idHash);
San Mehatb78a32c2010-01-10 13:02:12 -0800330 }
San Mehateb13a902010-01-07 12:12:50 -0800331 Loop::destroyByDevice(loopDevice);
332 unlink(asecFileName);
333 return -1;
334 }
San Mehata1091cb2010-02-28 20:17:20 -0800335 char mountPoint[255];
San Mehata19b2502010-01-06 10:33:53 -0800336
San Mehata1091cb2010-02-28 20:17:20 -0800337 snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id);
338 if (mkdir(mountPoint, 0777)) {
339 if (errno != EEXIST) {
San Mehat97ac40e2010-03-24 10:24:19 -0700340 SLOGE("Mountpoint creation failed (%s)", strerror(errno));
San Mehata1091cb2010-02-28 20:17:20 -0800341 if (cleanupDm) {
San Mehatd9a4e352010-03-12 13:32:47 -0800342 Devmapper::destroy(idHash);
San Mehata1091cb2010-02-28 20:17:20 -0800343 }
344 Loop::destroyByDevice(loopDevice);
345 unlink(asecFileName);
346 return -1;
347 }
San Mehatb78a32c2010-01-10 13:02:12 -0800348 }
San Mehata1091cb2010-02-28 20:17:20 -0800349
Kenny Roota3e06082010-08-27 08:31:35 -0700350 if (Fat::doMount(dmDevice, mountPoint, false, false, false, ownerUid,
San Mehata1091cb2010-02-28 20:17:20 -0800351 0, 0000, false)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700352 SLOGE("ASEC FAT mount failed (%s)", strerror(errno));
San Mehata1091cb2010-02-28 20:17:20 -0800353 if (cleanupDm) {
San Mehatd9a4e352010-03-12 13:32:47 -0800354 Devmapper::destroy(idHash);
San Mehata1091cb2010-02-28 20:17:20 -0800355 }
356 Loop::destroyByDevice(loopDevice);
357 unlink(asecFileName);
358 return -1;
359 }
360 } else {
San Mehat97ac40e2010-03-24 10:24:19 -0700361 SLOGI("Created raw secure container %s (no filesystem)", id);
San Mehata19b2502010-01-06 10:33:53 -0800362 }
San Mehat88705162010-01-15 09:26:28 -0800363
Kenny Rootcbacf782010-09-24 15:11:48 -0700364 mActiveContainers->push_back(new ContainerData(strdup(id), ASEC));
San Mehata19b2502010-01-06 10:33:53 -0800365 return 0;
366}
367
368int VolumeManager::finalizeAsec(const char *id) {
369 char asecFileName[255];
370 char loopDevice[255];
371 char mountPoint[255];
372
San Mehat3bb60202010-02-19 18:14:36 -0800373 snprintf(asecFileName, sizeof(asecFileName), "%s/%s.asec", Volume::SEC_ASECDIR, id);
San Mehata19b2502010-01-06 10:33:53 -0800374
San Mehatd9a4e352010-03-12 13:32:47 -0800375 char idHash[33];
376 if (!asecHash(id, idHash, sizeof(idHash))) {
San Mehat97ac40e2010-03-24 10:24:19 -0700377 SLOGE("Hash of '%s' failed (%s)", id, strerror(errno));
San Mehatd9a4e352010-03-12 13:32:47 -0800378 return -1;
379 }
380
381 if (Loop::lookupActive(idHash, loopDevice, sizeof(loopDevice))) {
San Mehat97ac40e2010-03-24 10:24:19 -0700382 SLOGE("Unable to finalize %s (%s)", id, strerror(errno));
San Mehata19b2502010-01-06 10:33:53 -0800383 return -1;
384 }
385
San Mehat3bb60202010-02-19 18:14:36 -0800386 snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id);
San Mehatfff0b472010-01-06 19:19:46 -0800387 // XXX:
Kenny Roota3e06082010-08-27 08:31:35 -0700388 if (Fat::doMount(loopDevice, mountPoint, true, true, true, 0, 0, 0227, false)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700389 SLOGE("ASEC finalize mount failed (%s)", strerror(errno));
San Mehata19b2502010-01-06 10:33:53 -0800390 return -1;
391 }
392
San Mehatd9a4e352010-03-12 13:32:47 -0800393 if (mDebug) {
San Mehat97ac40e2010-03-24 10:24:19 -0700394 SLOGD("ASEC %s finalized", id);
San Mehatd9a4e352010-03-12 13:32:47 -0800395 }
San Mehata19b2502010-01-06 10:33:53 -0800396 return 0;
397}
398
San Mehat048b0802010-01-23 08:17:06 -0800399int VolumeManager::renameAsec(const char *id1, const char *id2) {
400 char *asecFilename1;
401 char *asecFilename2;
402 char mountPoint[255];
403
San Mehat3bb60202010-02-19 18:14:36 -0800404 asprintf(&asecFilename1, "%s/%s.asec", Volume::SEC_ASECDIR, id1);
405 asprintf(&asecFilename2, "%s/%s.asec", Volume::SEC_ASECDIR, id2);
San Mehat048b0802010-01-23 08:17:06 -0800406
San Mehat3bb60202010-02-19 18:14:36 -0800407 snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id1);
San Mehat048b0802010-01-23 08:17:06 -0800408 if (isMountpointMounted(mountPoint)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700409 SLOGW("Rename attempt when src mounted");
San Mehat048b0802010-01-23 08:17:06 -0800410 errno = EBUSY;
411 goto out_err;
412 }
413
San Mehat96956ed2010-02-24 08:42:51 -0800414 snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id2);
415 if (isMountpointMounted(mountPoint)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700416 SLOGW("Rename attempt when dst mounted");
San Mehat96956ed2010-02-24 08:42:51 -0800417 errno = EBUSY;
418 goto out_err;
419 }
420
San Mehat048b0802010-01-23 08:17:06 -0800421 if (!access(asecFilename2, F_OK)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700422 SLOGE("Rename attempt when dst exists");
San Mehat048b0802010-01-23 08:17:06 -0800423 errno = EADDRINUSE;
424 goto out_err;
425 }
426
427 if (rename(asecFilename1, asecFilename2)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700428 SLOGE("Rename of '%s' to '%s' failed (%s)", asecFilename1, asecFilename2, strerror(errno));
San Mehat048b0802010-01-23 08:17:06 -0800429 goto out_err;
430 }
431
432 free(asecFilename1);
433 free(asecFilename2);
434 return 0;
435
436out_err:
437 free(asecFilename1);
438 free(asecFilename2);
439 return -1;
440}
441
Kenny Rootfb7c4d52010-06-30 18:48:41 -0700442#define UNMOUNT_RETRIES 5
443#define UNMOUNT_SLEEP_BETWEEN_RETRY_MS (1000 * 1000)
San Mehat4ba89482010-02-18 09:00:18 -0800444int VolumeManager::unmountAsec(const char *id, bool force) {
San Mehata19b2502010-01-06 10:33:53 -0800445 char asecFileName[255];
446 char mountPoint[255];
447
San Mehat3bb60202010-02-19 18:14:36 -0800448 snprintf(asecFileName, sizeof(asecFileName), "%s/%s.asec", Volume::SEC_ASECDIR, id);
449 snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id);
San Mehata19b2502010-01-06 10:33:53 -0800450
San Mehatd9a4e352010-03-12 13:32:47 -0800451 char idHash[33];
452 if (!asecHash(id, idHash, sizeof(idHash))) {
San Mehat97ac40e2010-03-24 10:24:19 -0700453 SLOGE("Hash of '%s' failed (%s)", id, strerror(errno));
San Mehatd9a4e352010-03-12 13:32:47 -0800454 return -1;
455 }
456
Kenny Rootfb7c4d52010-06-30 18:48:41 -0700457 return unmountLoopImage(id, idHash, asecFileName, mountPoint, force);
458}
459
Kenny Root508c0e12010-07-12 09:59:49 -0700460int VolumeManager::unmountObb(const char *fileName, bool force) {
Kenny Rootfb7c4d52010-06-30 18:48:41 -0700461 char mountPoint[255];
462
463 char idHash[33];
464 if (!asecHash(fileName, idHash, sizeof(idHash))) {
465 SLOGE("Hash of '%s' failed (%s)", fileName, strerror(errno));
466 return -1;
467 }
468
469 snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::LOOPDIR, idHash);
470
471 return unmountLoopImage(fileName, idHash, fileName, mountPoint, force);
472}
473
474int VolumeManager::unmountLoopImage(const char *id, const char *idHash,
475 const char *fileName, const char *mountPoint, bool force) {
San Mehat0586d542010-01-12 15:38:59 -0800476 if (!isMountpointMounted(mountPoint)) {
Kenny Rootfb7c4d52010-06-30 18:48:41 -0700477 SLOGE("Unmount request for %s when not mounted", id);
Kenny Root918e5f92010-09-30 18:00:52 -0700478 errno = ENOENT;
San Mehatb78a32c2010-01-10 13:02:12 -0800479 return -1;
480 }
San Mehat23969932010-01-09 07:08:06 -0800481
San Mehatb78a32c2010-01-10 13:02:12 -0800482 int i, rc;
Kenny Rootfb7c4d52010-06-30 18:48:41 -0700483 for (i = 1; i <= UNMOUNT_RETRIES; i++) {
San Mehatb78a32c2010-01-10 13:02:12 -0800484 rc = umount(mountPoint);
485 if (!rc) {
486 break;
San Mehata19b2502010-01-06 10:33:53 -0800487 }
San Mehatb78a32c2010-01-10 13:02:12 -0800488 if (rc && (errno == EINVAL || errno == ENOENT)) {
Kenny Rootfb7c4d52010-06-30 18:48:41 -0700489 SLOGI("Container %s unmounted OK", id);
San Mehatb78a32c2010-01-10 13:02:12 -0800490 rc = 0;
491 break;
San Mehata19b2502010-01-06 10:33:53 -0800492 }
Kenny Rootfb7c4d52010-06-30 18:48:41 -0700493 SLOGW("%s unmount attempt %d failed (%s)",
San Mehat8c940ef2010-02-13 14:19:53 -0800494 id, i, strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800495
San Mehat4ba89482010-02-18 09:00:18 -0800496 int action = 0; // default is to just complain
497
498 if (force) {
Kenny Rootfb7c4d52010-06-30 18:48:41 -0700499 if (i > (UNMOUNT_RETRIES - 2))
San Mehat4ba89482010-02-18 09:00:18 -0800500 action = 2; // SIGKILL
Kenny Rootfb7c4d52010-06-30 18:48:41 -0700501 else if (i > (UNMOUNT_RETRIES - 3))
San Mehat4ba89482010-02-18 09:00:18 -0800502 action = 1; // SIGHUP
503 }
San Mehat8c940ef2010-02-13 14:19:53 -0800504
San Mehat586536c2010-02-16 17:12:00 -0800505 Process::killProcessesWithOpenFiles(mountPoint, action);
Kenny Rootfb7c4d52010-06-30 18:48:41 -0700506 usleep(UNMOUNT_SLEEP_BETWEEN_RETRY_MS);
San Mehatb78a32c2010-01-10 13:02:12 -0800507 }
508
509 if (rc) {
San Mehat4ba89482010-02-18 09:00:18 -0800510 errno = EBUSY;
San Mehat97ac40e2010-03-24 10:24:19 -0700511 SLOGE("Failed to unmount container %s (%s)", id, strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800512 return -1;
513 }
514
San Mehat12f4b892010-02-24 11:43:22 -0800515 int retries = 10;
516
517 while(retries--) {
518 if (!rmdir(mountPoint)) {
519 break;
520 }
521
San Mehat97ac40e2010-03-24 10:24:19 -0700522 SLOGW("Failed to rmdir %s (%s)", mountPoint, strerror(errno));
Kenny Rootfb7c4d52010-06-30 18:48:41 -0700523 usleep(UNMOUNT_SLEEP_BETWEEN_RETRY_MS);
San Mehat12f4b892010-02-24 11:43:22 -0800524 }
525
526 if (!retries) {
San Mehat97ac40e2010-03-24 10:24:19 -0700527 SLOGE("Timed out trying to rmdir %s (%s)", mountPoint, strerror(errno));
San Mehatf5c61982010-02-03 11:04:46 -0800528 }
San Mehat88705162010-01-15 09:26:28 -0800529
San Mehatd9a4e352010-03-12 13:32:47 -0800530 if (Devmapper::destroy(idHash) && errno != ENXIO) {
San Mehat97ac40e2010-03-24 10:24:19 -0700531 SLOGE("Failed to destroy devmapper instance (%s)", strerror(errno));
San Mehata19b2502010-01-06 10:33:53 -0800532 }
533
534 char loopDevice[255];
San Mehatd9a4e352010-03-12 13:32:47 -0800535 if (!Loop::lookupActive(idHash, loopDevice, sizeof(loopDevice))) {
San Mehata19b2502010-01-06 10:33:53 -0800536 Loop::destroyByDevice(loopDevice);
San Mehatd9a4e352010-03-12 13:32:47 -0800537 } else {
Kenny Rootfb7c4d52010-06-30 18:48:41 -0700538 SLOGW("Failed to find loop device for {%s} (%s)", fileName, strerror(errno));
San Mehata19b2502010-01-06 10:33:53 -0800539 }
San Mehat88705162010-01-15 09:26:28 -0800540
541 AsecIdCollection::iterator it;
542 for (it = mActiveContainers->begin(); it != mActiveContainers->end(); ++it) {
Kenny Rootcbacf782010-09-24 15:11:48 -0700543 ContainerData* cd = *it;
544 if (!strcmp(cd->id, id)) {
San Mehat88705162010-01-15 09:26:28 -0800545 free(*it);
546 mActiveContainers->erase(it);
547 break;
548 }
549 }
550 if (it == mActiveContainers->end()) {
San Mehat97ac40e2010-03-24 10:24:19 -0700551 SLOGW("mActiveContainers is inconsistent!");
San Mehat88705162010-01-15 09:26:28 -0800552 }
San Mehatb78a32c2010-01-10 13:02:12 -0800553 return 0;
554}
555
San Mehat4ba89482010-02-18 09:00:18 -0800556int VolumeManager::destroyAsec(const char *id, bool force) {
San Mehatb78a32c2010-01-10 13:02:12 -0800557 char asecFileName[255];
558 char mountPoint[255];
559
San Mehat3bb60202010-02-19 18:14:36 -0800560 snprintf(asecFileName, sizeof(asecFileName), "%s/%s.asec", Volume::SEC_ASECDIR, id);
San Mehat55013f72010-02-24 12:12:34 -0800561 snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id);
San Mehatb78a32c2010-01-10 13:02:12 -0800562
San Mehat0586d542010-01-12 15:38:59 -0800563 if (isMountpointMounted(mountPoint)) {
San Mehatd9a4e352010-03-12 13:32:47 -0800564 if (mDebug) {
San Mehat97ac40e2010-03-24 10:24:19 -0700565 SLOGD("Unmounting container before destroy");
San Mehatd9a4e352010-03-12 13:32:47 -0800566 }
San Mehat4ba89482010-02-18 09:00:18 -0800567 if (unmountAsec(id, force)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700568 SLOGE("Failed to unmount asec %s for destroy (%s)", id, strerror(errno));
San Mehat0586d542010-01-12 15:38:59 -0800569 return -1;
570 }
571 }
San Mehata19b2502010-01-06 10:33:53 -0800572
San Mehat0586d542010-01-12 15:38:59 -0800573 if (unlink(asecFileName)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700574 SLOGE("Failed to unlink asec '%s' (%s)", asecFileName, strerror(errno));
San Mehat0586d542010-01-12 15:38:59 -0800575 return -1;
576 }
San Mehata19b2502010-01-06 10:33:53 -0800577
San Mehatd9a4e352010-03-12 13:32:47 -0800578 if (mDebug) {
San Mehat97ac40e2010-03-24 10:24:19 -0700579 SLOGD("ASEC %s destroyed", id);
San Mehatd9a4e352010-03-12 13:32:47 -0800580 }
San Mehata19b2502010-01-06 10:33:53 -0800581 return 0;
582}
583
584int VolumeManager::mountAsec(const char *id, const char *key, int ownerUid) {
585 char asecFileName[255];
586 char mountPoint[255];
587
San Mehat3bb60202010-02-19 18:14:36 -0800588 snprintf(asecFileName, sizeof(asecFileName), "%s/%s.asec", Volume::SEC_ASECDIR, id);
589 snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id);
San Mehata19b2502010-01-06 10:33:53 -0800590
591 if (isMountpointMounted(mountPoint)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700592 SLOGE("ASEC %s already mounted", id);
San Mehata19b2502010-01-06 10:33:53 -0800593 errno = EBUSY;
594 return -1;
595 }
596
San Mehatd9a4e352010-03-12 13:32:47 -0800597 char idHash[33];
598 if (!asecHash(id, idHash, sizeof(idHash))) {
San Mehat97ac40e2010-03-24 10:24:19 -0700599 SLOGE("Hash of '%s' failed (%s)", id, strerror(errno));
San Mehatd9a4e352010-03-12 13:32:47 -0800600 return -1;
601 }
Kenny Root7b18a7b2010-03-15 13:13:41 -0700602
San Mehata19b2502010-01-06 10:33:53 -0800603 char loopDevice[255];
San Mehatd9a4e352010-03-12 13:32:47 -0800604 if (Loop::lookupActive(idHash, loopDevice, sizeof(loopDevice))) {
605 if (Loop::create(idHash, asecFileName, loopDevice, sizeof(loopDevice))) {
San Mehat97ac40e2010-03-24 10:24:19 -0700606 SLOGE("ASEC loop device creation failed (%s)", strerror(errno));
San Mehata19b2502010-01-06 10:33:53 -0800607 return -1;
608 }
San Mehatd9a4e352010-03-12 13:32:47 -0800609 if (mDebug) {
San Mehat97ac40e2010-03-24 10:24:19 -0700610 SLOGD("New loop device created at %s", loopDevice);
San Mehatd9a4e352010-03-12 13:32:47 -0800611 }
San Mehatb78a32c2010-01-10 13:02:12 -0800612 } else {
San Mehatd9a4e352010-03-12 13:32:47 -0800613 if (mDebug) {
San Mehat97ac40e2010-03-24 10:24:19 -0700614 SLOGD("Found active loopback for %s at %s", asecFileName, loopDevice);
San Mehatd9a4e352010-03-12 13:32:47 -0800615 }
San Mehatb78a32c2010-01-10 13:02:12 -0800616 }
617
618 char dmDevice[255];
619 bool cleanupDm = false;
San Mehatfcf24fe2010-03-03 12:37:32 -0800620 int fd;
621 unsigned int nr_sec = 0;
622
623 if ((fd = open(loopDevice, O_RDWR)) < 0) {
San Mehat97ac40e2010-03-24 10:24:19 -0700624 SLOGE("Failed to open loopdevice (%s)", strerror(errno));
San Mehatfcf24fe2010-03-03 12:37:32 -0800625 Loop::destroyByDevice(loopDevice);
626 return -1;
627 }
628
629 if (ioctl(fd, BLKGETSIZE, &nr_sec)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700630 SLOGE("Failed to get loop size (%s)", strerror(errno));
San Mehatfcf24fe2010-03-03 12:37:32 -0800631 Loop::destroyByDevice(loopDevice);
632 close(fd);
633 return -1;
634 }
635
636 /*
637 * Validate superblock
638 */
639 struct asec_superblock sb;
640 memset(&sb, 0, sizeof(sb));
641 if (lseek(fd, ((nr_sec-1) * 512), SEEK_SET) < 0) {
San Mehat97ac40e2010-03-24 10:24:19 -0700642 SLOGE("lseek failed (%s)", strerror(errno));
San Mehatfcf24fe2010-03-03 12:37:32 -0800643 close(fd);
644 Loop::destroyByDevice(loopDevice);
645 return -1;
646 }
647 if (read(fd, &sb, sizeof(sb)) != sizeof(sb)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700648 SLOGE("superblock read failed (%s)", strerror(errno));
San Mehatfcf24fe2010-03-03 12:37:32 -0800649 close(fd);
650 Loop::destroyByDevice(loopDevice);
651 return -1;
652 }
653
654 close(fd);
655
San Mehatd9a4e352010-03-12 13:32:47 -0800656 if (mDebug) {
San Mehat97ac40e2010-03-24 10:24:19 -0700657 SLOGD("Container sb magic/ver (%.8x/%.2x)", sb.magic, sb.ver);
San Mehatd9a4e352010-03-12 13:32:47 -0800658 }
San Mehatfcf24fe2010-03-03 12:37:32 -0800659 if (sb.magic != ASEC_SB_MAGIC || sb.ver != ASEC_SB_VER) {
San Mehat97ac40e2010-03-24 10:24:19 -0700660 SLOGE("Bad container magic/version (%.8x/%.2x)", sb.magic, sb.ver);
San Mehatfcf24fe2010-03-03 12:37:32 -0800661 Loop::destroyByDevice(loopDevice);
662 errno = EMEDIUMTYPE;
663 return -1;
664 }
665 nr_sec--; // We don't want the devmapping to extend onto our superblock
666
San Mehatb78a32c2010-01-10 13:02:12 -0800667 if (strcmp(key, "none")) {
San Mehatd9a4e352010-03-12 13:32:47 -0800668 if (Devmapper::lookupActive(idHash, dmDevice, sizeof(dmDevice))) {
669 if (Devmapper::create(idHash, loopDevice, key, nr_sec,
San Mehatb78a32c2010-01-10 13:02:12 -0800670 dmDevice, sizeof(dmDevice))) {
San Mehat97ac40e2010-03-24 10:24:19 -0700671 SLOGE("ASEC device mapping failed (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800672 Loop::destroyByDevice(loopDevice);
673 return -1;
674 }
San Mehatd9a4e352010-03-12 13:32:47 -0800675 if (mDebug) {
San Mehat97ac40e2010-03-24 10:24:19 -0700676 SLOGD("New devmapper instance created at %s", dmDevice);
San Mehatd9a4e352010-03-12 13:32:47 -0800677 }
San Mehatb78a32c2010-01-10 13:02:12 -0800678 } else {
San Mehatd9a4e352010-03-12 13:32:47 -0800679 if (mDebug) {
San Mehat97ac40e2010-03-24 10:24:19 -0700680 SLOGD("Found active devmapper for %s at %s", asecFileName, dmDevice);
San Mehatd9a4e352010-03-12 13:32:47 -0800681 }
San Mehatb78a32c2010-01-10 13:02:12 -0800682 }
683 cleanupDm = true;
684 } else {
685 strcpy(dmDevice, loopDevice);
San Mehata19b2502010-01-06 10:33:53 -0800686 }
687
688 if (mkdir(mountPoint, 0777)) {
San Mehatb78a32c2010-01-10 13:02:12 -0800689 if (errno != EEXIST) {
San Mehat97ac40e2010-03-24 10:24:19 -0700690 SLOGE("Mountpoint creation failed (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800691 if (cleanupDm) {
San Mehatd9a4e352010-03-12 13:32:47 -0800692 Devmapper::destroy(idHash);
San Mehatb78a32c2010-01-10 13:02:12 -0800693 }
694 Loop::destroyByDevice(loopDevice);
695 return -1;
696 }
San Mehata19b2502010-01-06 10:33:53 -0800697 }
698
Kenny Roota3e06082010-08-27 08:31:35 -0700699 if (Fat::doMount(dmDevice, mountPoint, true, false, true, ownerUid, 0,
San Mehatcff5ec32010-01-08 12:31:44 -0800700 0222, false)) {
701// 0227, false)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700702 SLOGE("ASEC mount failed (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800703 if (cleanupDm) {
San Mehatd9a4e352010-03-12 13:32:47 -0800704 Devmapper::destroy(idHash);
San Mehatb78a32c2010-01-10 13:02:12 -0800705 }
706 Loop::destroyByDevice(loopDevice);
San Mehata19b2502010-01-06 10:33:53 -0800707 return -1;
708 }
709
Kenny Rootcbacf782010-09-24 15:11:48 -0700710 mActiveContainers->push_back(new ContainerData(strdup(id), ASEC));
San Mehatd9a4e352010-03-12 13:32:47 -0800711 if (mDebug) {
San Mehat97ac40e2010-03-24 10:24:19 -0700712 SLOGD("ASEC %s mounted", id);
San Mehatd9a4e352010-03-12 13:32:47 -0800713 }
San Mehata19b2502010-01-06 10:33:53 -0800714 return 0;
715}
716
Kenny Rootfb7c4d52010-06-30 18:48:41 -0700717/**
718 * Mounts an image file <code>img</code>.
719 */
Kenny Root508c0e12010-07-12 09:59:49 -0700720int VolumeManager::mountObb(const char *img, const char *key, int ownerUid) {
Kenny Rootfb7c4d52010-06-30 18:48:41 -0700721 char mountPoint[255];
722
Kenny Rootfb7c4d52010-06-30 18:48:41 -0700723 char idHash[33];
724 if (!asecHash(img, idHash, sizeof(idHash))) {
725 SLOGE("Hash of '%s' failed (%s)", img, strerror(errno));
726 return -1;
727 }
728
729 snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::LOOPDIR, idHash);
730
731 if (isMountpointMounted(mountPoint)) {
732 SLOGE("Image %s already mounted", img);
733 errno = EBUSY;
734 return -1;
735 }
736
737 char loopDevice[255];
738 if (Loop::lookupActive(idHash, loopDevice, sizeof(loopDevice))) {
739 if (Loop::create(idHash, img, loopDevice, sizeof(loopDevice))) {
740 SLOGE("Image loop device creation failed (%s)", strerror(errno));
741 return -1;
742 }
743 if (mDebug) {
744 SLOGD("New loop device created at %s", loopDevice);
745 }
746 } else {
747 if (mDebug) {
748 SLOGD("Found active loopback for %s at %s", img, loopDevice);
749 }
750 }
751
752 char dmDevice[255];
753 bool cleanupDm = false;
754 int fd;
755 unsigned int nr_sec = 0;
756
757 if ((fd = open(loopDevice, O_RDWR)) < 0) {
758 SLOGE("Failed to open loopdevice (%s)", strerror(errno));
759 Loop::destroyByDevice(loopDevice);
760 return -1;
761 }
762
763 if (ioctl(fd, BLKGETSIZE, &nr_sec)) {
764 SLOGE("Failed to get loop size (%s)", strerror(errno));
765 Loop::destroyByDevice(loopDevice);
766 close(fd);
767 return -1;
768 }
769
770 close(fd);
771
772 if (strcmp(key, "none")) {
773 if (Devmapper::lookupActive(idHash, dmDevice, sizeof(dmDevice))) {
774 if (Devmapper::create(idHash, loopDevice, key, nr_sec,
775 dmDevice, sizeof(dmDevice))) {
776 SLOGE("ASEC device mapping failed (%s)", strerror(errno));
777 Loop::destroyByDevice(loopDevice);
778 return -1;
779 }
780 if (mDebug) {
781 SLOGD("New devmapper instance created at %s", dmDevice);
782 }
783 } else {
784 if (mDebug) {
785 SLOGD("Found active devmapper for %s at %s", img, dmDevice);
786 }
787 }
788 cleanupDm = true;
789 } else {
790 strcpy(dmDevice, loopDevice);
791 }
792
793 if (mkdir(mountPoint, 0755)) {
794 if (errno != EEXIST) {
795 SLOGE("Mountpoint creation failed (%s)", strerror(errno));
796 if (cleanupDm) {
797 Devmapper::destroy(idHash);
798 }
799 Loop::destroyByDevice(loopDevice);
800 return -1;
801 }
802 }
803
Kenny Roota3e06082010-08-27 08:31:35 -0700804 if (Fat::doMount(dmDevice, mountPoint, true, false, true, ownerUid, 0,
Kenny Rootfb7c4d52010-06-30 18:48:41 -0700805 0227, false)) {
806 SLOGE("Image mount failed (%s)", strerror(errno));
807 if (cleanupDm) {
808 Devmapper::destroy(idHash);
809 }
810 Loop::destroyByDevice(loopDevice);
811 return -1;
812 }
813
Kenny Rootcbacf782010-09-24 15:11:48 -0700814 mActiveContainers->push_back(new ContainerData(strdup(img), OBB));
Kenny Rootfb7c4d52010-06-30 18:48:41 -0700815 if (mDebug) {
816 SLOGD("Image %s mounted", img);
817 }
818 return 0;
819}
820
San Mehat49e2bce2009-10-12 16:29:01 -0700821int VolumeManager::mountVolume(const char *label) {
822 Volume *v = lookupVolume(label);
823
824 if (!v) {
825 errno = ENOENT;
826 return -1;
827 }
828
San Mehata2677e42009-12-13 10:40:18 -0800829 return v->mountVol();
830}
831
Kenny Root508c0e12010-07-12 09:59:49 -0700832int VolumeManager::listMountedObbs(SocketClient* cli) {
833 char device[256];
834 char mount_path[256];
835 char rest[256];
836 FILE *fp;
837 char line[1024];
838
839 if (!(fp = fopen("/proc/mounts", "r"))) {
840 SLOGE("Error opening /proc/mounts (%s)", strerror(errno));
841 return -1;
842 }
843
844 // Create a string to compare against that has a trailing slash
845 int loopDirLen = sizeof(Volume::LOOPDIR);
846 char loopDir[loopDirLen + 2];
847 strcpy(loopDir, Volume::LOOPDIR);
848 loopDir[loopDirLen++] = '/';
849 loopDir[loopDirLen] = '\0';
850
851 while(fgets(line, sizeof(line), fp)) {
852 line[strlen(line)-1] = '\0';
853
854 /*
855 * Should look like:
856 * /dev/block/loop0 /mnt/obb/fc99df1323fd36424f864dcb76b76d65 ...
857 */
858 sscanf(line, "%255s %255s %255s\n", device, mount_path, rest);
859
860 if (!strncmp(mount_path, loopDir, loopDirLen)) {
861 int fd = open(device, O_RDONLY);
862 if (fd >= 0) {
863 struct loop_info64 li;
864 if (ioctl(fd, LOOP_GET_STATUS64, &li) >= 0) {
865 cli->sendMsg(ResponseCode::AsecListResult,
866 (const char*) li.lo_file_name, false);
867 }
868 close(fd);
869 }
870 }
871 }
872
873 fclose(fp);
874 return 0;
875}
876
San Mehateba65e92010-01-29 05:15:16 -0800877int VolumeManager::shareEnabled(const char *label, const char *method, bool *enabled) {
878 Volume *v = lookupVolume(label);
879
880 if (!v) {
881 errno = ENOENT;
882 return -1;
883 }
884
885 if (strcmp(method, "ums")) {
886 errno = ENOSYS;
887 return -1;
888 }
889
890 if (v->getState() != Volume::State_Shared) {
San Mehateba65e92010-01-29 05:15:16 -0800891 *enabled = false;
San Mehatb9aed742010-02-04 15:07:01 -0800892 } else {
893 *enabled = true;
San Mehateba65e92010-01-29 05:15:16 -0800894 }
895 return 0;
896}
897
San Mehata2677e42009-12-13 10:40:18 -0800898int VolumeManager::shareVolume(const char *label, const char *method) {
899 Volume *v = lookupVolume(label);
900
901 if (!v) {
902 errno = ENOENT;
903 return -1;
904 }
905
906 /*
907 * Eventually, we'll want to support additional share back-ends,
908 * some of which may work while the media is mounted. For now,
909 * we just support UMS
910 */
911 if (strcmp(method, "ums")) {
912 errno = ENOSYS;
913 return -1;
914 }
915
916 if (v->getState() == Volume::State_NoMedia) {
917 errno = ENODEV;
918 return -1;
919 }
920
San Mehat49e2bce2009-10-12 16:29:01 -0700921 if (v->getState() != Volume::State_Idle) {
San Mehata2677e42009-12-13 10:40:18 -0800922 // You need to unmount manually befoe sharing
San Mehat49e2bce2009-10-12 16:29:01 -0700923 errno = EBUSY;
924 return -1;
925 }
926
Mike Lockwood2dfe2972010-09-17 18:50:51 -0400927 dev_t d = v->getShareDevice();
San Mehata2677e42009-12-13 10:40:18 -0800928 if ((MAJOR(d) == 0) && (MINOR(d) == 0)) {
929 // This volume does not support raw disk access
930 errno = EINVAL;
931 return -1;
932 }
933
934 int fd;
935 char nodepath[255];
936 snprintf(nodepath,
937 sizeof(nodepath), "/dev/block/vold/%d:%d",
938 MAJOR(d), MINOR(d));
939
San Mehat0cde53c2009-12-22 08:32:33 -0800940 if ((fd = open("/sys/devices/platform/usb_mass_storage/lun0/file",
941 O_WRONLY)) < 0) {
San Mehat97ac40e2010-03-24 10:24:19 -0700942 SLOGE("Unable to open ums lunfile (%s)", strerror(errno));
San Mehata2677e42009-12-13 10:40:18 -0800943 return -1;
944 }
945
946 if (write(fd, nodepath, strlen(nodepath)) < 0) {
San Mehat97ac40e2010-03-24 10:24:19 -0700947 SLOGE("Unable to write to ums lunfile (%s)", strerror(errno));
San Mehata2677e42009-12-13 10:40:18 -0800948 close(fd);
949 return -1;
950 }
951
952 close(fd);
953 v->handleVolumeShared();
Mike Lockwooda28056b2010-10-28 15:21:24 -0400954 if (mUmsSharingCount++ == 0) {
955 FILE* fp;
956 mSavedDirtyRatio = -1; // in case we fail
957 if ((fp = fopen("/proc/sys/vm/dirty_ratio", "r+"))) {
958 char line[16];
959 if (fgets(line, sizeof(line), fp) && sscanf(line, "%d", &mSavedDirtyRatio)) {
960 fprintf(fp, "%d\n", mUmsDirtyRatio);
961 } else {
962 SLOGE("Failed to read dirty_ratio (%s)", strerror(errno));
963 }
964 fclose(fp);
965 } else {
966 SLOGE("Failed to open /proc/sys/vm/dirty_ratio (%s)", strerror(errno));
967 }
968 }
San Mehata2677e42009-12-13 10:40:18 -0800969 return 0;
970}
971
972int VolumeManager::unshareVolume(const char *label, const char *method) {
973 Volume *v = lookupVolume(label);
974
975 if (!v) {
976 errno = ENOENT;
977 return -1;
978 }
979
980 if (strcmp(method, "ums")) {
981 errno = ENOSYS;
982 return -1;
983 }
984
985 if (v->getState() != Volume::State_Shared) {
986 errno = EINVAL;
987 return -1;
988 }
989
San Mehata2677e42009-12-13 10:40:18 -0800990 int fd;
San Mehat0cde53c2009-12-22 08:32:33 -0800991 if ((fd = open("/sys/devices/platform/usb_mass_storage/lun0/file", O_WRONLY)) < 0) {
San Mehat97ac40e2010-03-24 10:24:19 -0700992 SLOGE("Unable to open ums lunfile (%s)", strerror(errno));
San Mehata2677e42009-12-13 10:40:18 -0800993 return -1;
994 }
995
996 char ch = 0;
997 if (write(fd, &ch, 1) < 0) {
San Mehat97ac40e2010-03-24 10:24:19 -0700998 SLOGE("Unable to write to ums lunfile (%s)", strerror(errno));
San Mehata2677e42009-12-13 10:40:18 -0800999 close(fd);
1000 return -1;
1001 }
1002
1003 close(fd);
1004 v->handleVolumeUnshared();
Mike Lockwooda28056b2010-10-28 15:21:24 -04001005 if (--mUmsSharingCount == 0 && mSavedDirtyRatio != -1) {
1006 FILE* fp;
1007 if ((fp = fopen("/proc/sys/vm/dirty_ratio", "r+"))) {
1008 fprintf(fp, "%d\n", mSavedDirtyRatio);
1009 fclose(fp);
1010 } else {
1011 SLOGE("Failed to open /proc/sys/vm/dirty_ratio (%s)", strerror(errno));
1012 }
1013 mSavedDirtyRatio = -1;
1014 }
San Mehata2677e42009-12-13 10:40:18 -08001015 return 0;
San Mehat49e2bce2009-10-12 16:29:01 -07001016}
1017
Ken Sumrall29d8da82011-05-18 17:20:07 -07001018extern "C" int vold_unmountVol(const char *label) {
1019 VolumeManager *vm = VolumeManager::Instance();
1020 return vm->unmountVolume(label, true);
1021}
1022
1023extern "C" int vold_getNumDirectVolumes(void) {
1024 VolumeManager *vm = VolumeManager::Instance();
1025 return vm->getNumDirectVolumes();
1026}
1027
1028int VolumeManager::getNumDirectVolumes(void) {
1029 VolumeCollection::iterator i;
1030 int n=0;
1031
1032 for (i = mVolumes->begin(); i != mVolumes->end(); ++i) {
1033 if ((*i)->getShareDevice() != (dev_t)0) {
1034 n++;
1035 }
1036 }
1037 return n;
1038}
1039
1040extern "C" int vold_getDirectVolumeList(struct volume_info *vol_list) {
1041 VolumeManager *vm = VolumeManager::Instance();
1042 return vm->getDirectVolumeList(vol_list);
1043}
1044
1045int VolumeManager::getDirectVolumeList(struct volume_info *vol_list) {
1046 VolumeCollection::iterator i;
1047 int n=0;
1048 dev_t d;
1049
1050 for (i = mVolumes->begin(); i != mVolumes->end(); ++i) {
1051 if ((d=(*i)->getShareDevice()) != (dev_t)0) {
1052 (*i)->getVolInfo(&vol_list[n]);
1053 snprintf(vol_list[n].blk_dev, sizeof(vol_list[n].blk_dev),
1054 "/dev/block/vold/%d:%d",MAJOR(d), MINOR(d));
1055 n++;
1056 }
1057 }
1058
1059 return 0;
1060}
1061
San Mehat4ba89482010-02-18 09:00:18 -08001062int VolumeManager::unmountVolume(const char *label, bool force) {
San Mehat49e2bce2009-10-12 16:29:01 -07001063 Volume *v = lookupVolume(label);
1064
1065 if (!v) {
1066 errno = ENOENT;
1067 return -1;
1068 }
1069
San Mehata2677e42009-12-13 10:40:18 -08001070 if (v->getState() == Volume::State_NoMedia) {
1071 errno = ENODEV;
1072 return -1;
1073 }
1074
San Mehat49e2bce2009-10-12 16:29:01 -07001075 if (v->getState() != Volume::State_Mounted) {
San Mehat97ac40e2010-03-24 10:24:19 -07001076 SLOGW("Attempt to unmount volume which isn't mounted (%d)\n",
San Mehata2677e42009-12-13 10:40:18 -08001077 v->getState());
San Mehat49e2bce2009-10-12 16:29:01 -07001078 errno = EBUSY;
Ken Sumrall319b1042011-06-14 14:01:55 -07001079 return UNMOUNT_NOT_MOUNTED_ERR;
San Mehat49e2bce2009-10-12 16:29:01 -07001080 }
1081
San Mehat1a06eda2010-04-15 12:58:50 -07001082 cleanupAsec(v, force);
San Mehat88705162010-01-15 09:26:28 -08001083
San Mehat4ba89482010-02-18 09:00:18 -08001084 return v->unmountVol(force);
San Mehat49e2bce2009-10-12 16:29:01 -07001085}
1086
San Mehata2677e42009-12-13 10:40:18 -08001087/*
1088 * Looks up a volume by it's label or mount-point
1089 */
San Mehat49e2bce2009-10-12 16:29:01 -07001090Volume *VolumeManager::lookupVolume(const char *label) {
1091 VolumeCollection::iterator i;
1092
1093 for (i = mVolumes->begin(); i != mVolumes->end(); ++i) {
San Mehata2677e42009-12-13 10:40:18 -08001094 if (label[0] == '/') {
1095 if (!strcmp(label, (*i)->getMountpoint()))
1096 return (*i);
1097 } else {
1098 if (!strcmp(label, (*i)->getLabel()))
1099 return (*i);
1100 }
San Mehat49e2bce2009-10-12 16:29:01 -07001101 }
1102 return NULL;
1103}
San Mehata19b2502010-01-06 10:33:53 -08001104
1105bool VolumeManager::isMountpointMounted(const char *mp)
1106{
1107 char device[256];
1108 char mount_path[256];
1109 char rest[256];
1110 FILE *fp;
1111 char line[1024];
1112
1113 if (!(fp = fopen("/proc/mounts", "r"))) {
San Mehat97ac40e2010-03-24 10:24:19 -07001114 SLOGE("Error opening /proc/mounts (%s)", strerror(errno));
San Mehata19b2502010-01-06 10:33:53 -08001115 return false;
1116 }
1117
1118 while(fgets(line, sizeof(line), fp)) {
1119 line[strlen(line)-1] = '\0';
1120 sscanf(line, "%255s %255s %255s\n", device, mount_path, rest);
1121 if (!strcmp(mount_path, mp)) {
1122 fclose(fp);
1123 return true;
1124 }
San Mehata19b2502010-01-06 10:33:53 -08001125 }
1126
1127 fclose(fp);
1128 return false;
1129}
1130
San Mehat1a06eda2010-04-15 12:58:50 -07001131int VolumeManager::cleanupAsec(Volume *v, bool force) {
1132 while(mActiveContainers->size()) {
1133 AsecIdCollection::iterator it = mActiveContainers->begin();
Kenny Rootcbacf782010-09-24 15:11:48 -07001134 ContainerData* cd = *it;
1135 SLOGI("Unmounting ASEC %s (dependant on %s)", cd->id, v->getMountpoint());
1136 if (cd->type == ASEC) {
1137 if (unmountAsec(cd->id, force)) {
1138 SLOGE("Failed to unmount ASEC %s (%s)", cd->id, strerror(errno));
1139 return -1;
1140 }
1141 } else if (cd->type == OBB) {
1142 if (unmountObb(cd->id, force)) {
1143 SLOGE("Failed to unmount OBB %s (%s)", cd->id, strerror(errno));
1144 return -1;
1145 }
1146 } else {
1147 SLOGE("Unknown container type %d!", cd->type);
San Mehat1a06eda2010-04-15 12:58:50 -07001148 return -1;
1149 }
1150 }
1151 return 0;
1152}
1153