blob: 251e11c51cf4a3d6f2c73c54a53db3d3df6d7d43 [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
30#include <cutils/log.h>
31
San Mehatfd7f5872009-10-12 11:32:47 -070032#include <sysutils/NetlinkEvent.h>
33
San Mehatf1b736b2009-10-10 17:22:08 -070034#include "VolumeManager.h"
San Mehatae10b912009-10-12 14:57:05 -070035#include "DirectVolume.h"
San Mehata2677e42009-12-13 10:40:18 -080036#include "ResponseCode.h"
San Mehata19b2502010-01-06 10:33:53 -080037#include "Loop.h"
38#include "Fat.h"
San Mehatb78a32c2010-01-10 13:02:12 -080039#include "Devmapper.h"
San Mehat586536c2010-02-16 17:12:00 -080040#include "Process.h"
San Mehat23969932010-01-09 07:08:06 -080041
San Mehatf1b736b2009-10-10 17:22:08 -070042VolumeManager *VolumeManager::sInstance = NULL;
43
44VolumeManager *VolumeManager::Instance() {
45 if (!sInstance)
46 sInstance = new VolumeManager();
47 return sInstance;
48}
49
50VolumeManager::VolumeManager() {
51 mBlockDevices = new BlockDeviceCollection();
52 mVolumes = new VolumeCollection();
San Mehat88705162010-01-15 09:26:28 -080053 mActiveContainers = new AsecIdCollection();
San Mehatf1b736b2009-10-10 17:22:08 -070054 mBroadcaster = NULL;
San Mehata2677e42009-12-13 10:40:18 -080055 mUsbMassStorageConnected = false;
San Mehatf1b736b2009-10-10 17:22:08 -070056}
57
58VolumeManager::~VolumeManager() {
59 delete mBlockDevices;
San Mehat88705162010-01-15 09:26:28 -080060 delete mVolumes;
61 delete mActiveContainers;
San Mehatf1b736b2009-10-10 17:22:08 -070062}
63
64int VolumeManager::start() {
65 return 0;
66}
67
68int VolumeManager::stop() {
69 return 0;
70}
71
72int VolumeManager::addVolume(Volume *v) {
73 mVolumes->push_back(v);
74 return 0;
75}
76
San Mehata2677e42009-12-13 10:40:18 -080077void VolumeManager::notifyUmsConnected(bool connected) {
78 char msg[255];
79
80 if (connected) {
81 mUsbMassStorageConnected = true;
82 } else {
83 mUsbMassStorageConnected = false;
84 }
85 snprintf(msg, sizeof(msg), "Share method ums now %s",
86 (connected ? "available" : "unavailable"));
87
88 getBroadcaster()->sendBroadcast(ResponseCode::ShareAvailabilityChange,
89 msg, false);
90}
91
92void VolumeManager::handleSwitchEvent(NetlinkEvent *evt) {
San Mehat0cde53c2009-12-22 08:32:33 -080093 const char *devpath = evt->findParam("DEVPATH");
San Mehata2677e42009-12-13 10:40:18 -080094 const char *name = evt->findParam("SWITCH_NAME");
95 const char *state = evt->findParam("SWITCH_STATE");
96
San Mehat0cde53c2009-12-22 08:32:33 -080097 if (!name || !state) {
98 LOGW("Switch %s event missing name/state info", devpath);
99 return;
100 }
101
San Mehata2677e42009-12-13 10:40:18 -0800102 if (!strcmp(name, "usb_mass_storage")) {
103
104 if (!strcmp(state, "online")) {
105 notifyUmsConnected(true);
106 } else {
107 notifyUmsConnected(false);
108 }
109 } else {
110 LOGW("Ignoring unknown switch '%s'", name);
111 }
112}
113
San Mehatfd7f5872009-10-12 11:32:47 -0700114void VolumeManager::handleBlockEvent(NetlinkEvent *evt) {
115 const char *devpath = evt->findParam("DEVPATH");
San Mehatf1b736b2009-10-10 17:22:08 -0700116
San Mehatfd7f5872009-10-12 11:32:47 -0700117 /* Lookup a volume to handle this device */
San Mehatf1b736b2009-10-10 17:22:08 -0700118 VolumeCollection::iterator it;
119 bool hit = false;
120 for (it = mVolumes->begin(); it != mVolumes->end(); ++it) {
San Mehatfd7f5872009-10-12 11:32:47 -0700121 if (!(*it)->handleBlockEvent(evt)) {
San Mehata2677e42009-12-13 10:40:18 -0800122#ifdef NETLINK_DEBUG
123 LOGD("Device '%s' event handled by volume %s\n", devpath, (*it)->getLabel());
124#endif
San Mehatf1b736b2009-10-10 17:22:08 -0700125 hit = true;
San Mehatf1b736b2009-10-10 17:22:08 -0700126 break;
127 }
128 }
129
130 if (!hit) {
San Mehata2677e42009-12-13 10:40:18 -0800131#ifdef NETLINK_DEBUG
San Mehatfd7f5872009-10-12 11:32:47 -0700132 LOGW("No volumes handled block event for '%s'", devpath);
San Mehata2677e42009-12-13 10:40:18 -0800133#endif
San Mehatf1b736b2009-10-10 17:22:08 -0700134 }
135}
136
San Mehatf1b736b2009-10-10 17:22:08 -0700137int VolumeManager::listVolumes(SocketClient *cli) {
138 VolumeCollection::iterator i;
139
140 for (i = mVolumes->begin(); i != mVolumes->end(); ++i) {
141 char *buffer;
142 asprintf(&buffer, "%s %s %d",
143 (*i)->getLabel(), (*i)->getMountpoint(),
144 (*i)->getState());
San Mehata2677e42009-12-13 10:40:18 -0800145 cli->sendMsg(ResponseCode::VolumeListResult, buffer, false);
San Mehatf1b736b2009-10-10 17:22:08 -0700146 free(buffer);
147 }
San Mehata2677e42009-12-13 10:40:18 -0800148 cli->sendMsg(ResponseCode::CommandOkay, "Volumes listed.", false);
San Mehatf1b736b2009-10-10 17:22:08 -0700149 return 0;
150}
San Mehat49e2bce2009-10-12 16:29:01 -0700151
San Mehata2677e42009-12-13 10:40:18 -0800152int VolumeManager::formatVolume(const char *label) {
153 Volume *v = lookupVolume(label);
154
155 if (!v) {
156 errno = ENOENT;
157 return -1;
158 }
159
160 return v->formatVol();
161}
162
San Mehata19b2502010-01-06 10:33:53 -0800163int VolumeManager::getAsecMountPath(const char *id, char *buffer, int maxlen) {
164 char mountPoint[255];
165
166 snprintf(mountPoint, sizeof(mountPoint), "/asec/%s", id);
San Mehata19b2502010-01-06 10:33:53 -0800167 snprintf(buffer, maxlen, "/asec/%s", id);
168 return 0;
169}
170
San Mehat8b8f71b2010-01-11 09:17:25 -0800171int VolumeManager::createAsec(const char *id, unsigned int numSectors,
San Mehata19b2502010-01-06 10:33:53 -0800172 const char *fstype, const char *key, int ownerUid) {
173
San Mehatd31e3802010-02-18 08:37:45 -0800174 if (numSectors < ((1024*1024)/512)) {
175 LOGE("Invalid container size specified (%d sectors)", numSectors);
176 errno = EINVAL;
177 return -1;
178 }
179
San Mehata19b2502010-01-06 10:33:53 -0800180 mkdir("/sdcard/android_secure", 0777);
181
182 if (lookupVolume(id)) {
183 LOGE("ASEC volume '%s' currently exists", id);
184 errno = EADDRINUSE;
185 return -1;
186 }
187
188 char asecFileName[255];
189 snprintf(asecFileName, sizeof(asecFileName),
190 "/sdcard/android_secure/%s.asec", id);
191
192 if (!access(asecFileName, F_OK)) {
193 LOGE("ASEC file '%s' currently exists - destroy it first! (%s)",
194 asecFileName, strerror(errno));
195 errno = EADDRINUSE;
196 return -1;
197 }
198
San Mehat8b8f71b2010-01-11 09:17:25 -0800199 if (Loop::createImageFile(asecFileName, numSectors)) {
San Mehata19b2502010-01-06 10:33:53 -0800200 LOGE("ASEC image file creation failed (%s)", strerror(errno));
201 return -1;
202 }
203
204 char loopDevice[255];
San Mehat8da6bcb2010-01-09 12:24:05 -0800205 if (Loop::create(asecFileName, loopDevice, sizeof(loopDevice))) {
San Mehata19b2502010-01-06 10:33:53 -0800206 LOGE("ASEC loop device creation failed (%s)", strerror(errno));
207 unlink(asecFileName);
208 return -1;
209 }
210
San Mehatb78a32c2010-01-10 13:02:12 -0800211 char dmDevice[255];
212 bool cleanupDm = false;
San Mehata19b2502010-01-06 10:33:53 -0800213
San Mehatb78a32c2010-01-10 13:02:12 -0800214 if (strcmp(key, "none")) {
San Mehat8b8f71b2010-01-11 09:17:25 -0800215 if (Devmapper::create(id, loopDevice, key, numSectors, dmDevice,
San Mehatb78a32c2010-01-10 13:02:12 -0800216 sizeof(dmDevice))) {
217 LOGE("ASEC device mapping failed (%s)", strerror(errno));
218 Loop::destroyByDevice(loopDevice);
219 unlink(asecFileName);
220 return -1;
221 }
222 cleanupDm = true;
223 } else {
224 strcpy(dmDevice, loopDevice);
225 }
226
227 if (Fat::format(dmDevice)) {
San Mehata19b2502010-01-06 10:33:53 -0800228 LOGE("ASEC FAT format failed (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800229 if (cleanupDm) {
230 Devmapper::destroy(id);
231 }
San Mehata19b2502010-01-06 10:33:53 -0800232 Loop::destroyByDevice(loopDevice);
233 unlink(asecFileName);
234 return -1;
235 }
236
237 char mountPoint[255];
238
239 snprintf(mountPoint, sizeof(mountPoint), "/asec/%s", id);
240 if (mkdir(mountPoint, 0777)) {
San Mehateb13a902010-01-07 12:12:50 -0800241 if (errno != EEXIST) {
242 LOGE("Mountpoint creation failed (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800243 if (cleanupDm) {
244 Devmapper::destroy(id);
245 }
San Mehateb13a902010-01-07 12:12:50 -0800246 Loop::destroyByDevice(loopDevice);
247 unlink(asecFileName);
248 return -1;
249 }
San Mehata19b2502010-01-06 10:33:53 -0800250 }
251
San Mehatb78a32c2010-01-10 13:02:12 -0800252 if (Fat::doMount(dmDevice, mountPoint, false, false, ownerUid,
San Mehatcff5ec32010-01-08 12:31:44 -0800253 0, 0000, false)) {
254// 0, 0007, false)) {
San Mehata19b2502010-01-06 10:33:53 -0800255 LOGE("ASEC FAT mount failed (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800256 if (cleanupDm) {
257 Devmapper::destroy(id);
258 }
San Mehata19b2502010-01-06 10:33:53 -0800259 Loop::destroyByDevice(loopDevice);
260 unlink(asecFileName);
261 return -1;
262 }
San Mehat88705162010-01-15 09:26:28 -0800263
264 mActiveContainers->push_back(strdup(id));
San Mehata19b2502010-01-06 10:33:53 -0800265 return 0;
266}
267
268int VolumeManager::finalizeAsec(const char *id) {
269 char asecFileName[255];
270 char loopDevice[255];
271 char mountPoint[255];
272
273 snprintf(asecFileName, sizeof(asecFileName),
274 "/sdcard/android_secure/%s.asec", id);
275
276 if (Loop::lookupActive(asecFileName, loopDevice, sizeof(loopDevice))) {
277 LOGE("Unable to finalize %s (%s)", id, strerror(errno));
278 return -1;
279 }
280
281 snprintf(mountPoint, sizeof(mountPoint), "/asec/%s", id);
San Mehatfff0b472010-01-06 19:19:46 -0800282 // XXX:
283 if (Fat::doMount(loopDevice, mountPoint, true, true, 0, 0, 0227, false)) {
San Mehata19b2502010-01-06 10:33:53 -0800284 LOGE("ASEC finalize mount failed (%s)", strerror(errno));
285 return -1;
286 }
287
288 LOGD("ASEC %s finalized", id);
289 return 0;
290}
291
San Mehat048b0802010-01-23 08:17:06 -0800292int VolumeManager::renameAsec(const char *id1, const char *id2) {
293 char *asecFilename1;
294 char *asecFilename2;
295 char mountPoint[255];
296
297 asprintf(&asecFilename1, "/sdcard/android_secure/%s.asec", id1);
298 asprintf(&asecFilename2, "/sdcard/android_secure/%s.asec", id2);
299
300 snprintf(mountPoint, sizeof(mountPoint), "/asec/%s", id1);
301 if (isMountpointMounted(mountPoint)) {
302 LOGW("Rename attempt when src mounted");
303 errno = EBUSY;
304 goto out_err;
305 }
306
307 if (!access(asecFilename2, F_OK)) {
308 LOGE("Rename attempt when dst exists");
309 errno = EADDRINUSE;
310 goto out_err;
311 }
312
313 if (rename(asecFilename1, asecFilename2)) {
314 LOGE("Rename of '%s' to '%s' failed (%s)", asecFilename1, asecFilename2, strerror(errno));
315 goto out_err;
316 }
317
318 free(asecFilename1);
319 free(asecFilename2);
320 return 0;
321
322out_err:
323 free(asecFilename1);
324 free(asecFilename2);
325 return -1;
326}
327
San Mehat8c940ef2010-02-13 14:19:53 -0800328#define ASEC_UNMOUNT_RETRIES 10
San Mehatb78a32c2010-01-10 13:02:12 -0800329int VolumeManager::unmountAsec(const char *id) {
San Mehata19b2502010-01-06 10:33:53 -0800330 char asecFileName[255];
331 char mountPoint[255];
332
333 snprintf(asecFileName, sizeof(asecFileName),
334 "/sdcard/android_secure/%s.asec", id);
335 snprintf(mountPoint, sizeof(mountPoint), "/asec/%s", id);
336
San Mehat0586d542010-01-12 15:38:59 -0800337 if (!isMountpointMounted(mountPoint)) {
San Mehatb78a32c2010-01-10 13:02:12 -0800338 LOGE("Unmount request for ASEC %s when not mounted", id);
339 errno = EINVAL;
340 return -1;
341 }
San Mehat23969932010-01-09 07:08:06 -0800342
San Mehatb78a32c2010-01-10 13:02:12 -0800343 int i, rc;
San Mehat8c940ef2010-02-13 14:19:53 -0800344 for (i = 1; i <= ASEC_UNMOUNT_RETRIES; i++) {
San Mehatb78a32c2010-01-10 13:02:12 -0800345 rc = umount(mountPoint);
346 if (!rc) {
347 break;
San Mehata19b2502010-01-06 10:33:53 -0800348 }
San Mehatb78a32c2010-01-10 13:02:12 -0800349 if (rc && (errno == EINVAL || errno == ENOENT)) {
350 rc = 0;
351 break;
San Mehata19b2502010-01-06 10:33:53 -0800352 }
San Mehatb78a32c2010-01-10 13:02:12 -0800353 LOGW("ASEC %s unmount attempt %d failed (%s)",
San Mehat8c940ef2010-02-13 14:19:53 -0800354 id, i, strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800355
San Mehat8c940ef2010-02-13 14:19:53 -0800356 int action;
357 if (i > (ASEC_UNMOUNT_RETRIES - 2))
358 action = 2; // SIGKILL
359 else if (i > (ASEC_UNMOUNT_RETRIES - 3))
360 action = 1; // SIGHUP
361 else
362 action = 0; // Just complain
363
San Mehat586536c2010-02-16 17:12:00 -0800364 Process::killProcessesWithOpenFiles(mountPoint, action);
San Mehat8c940ef2010-02-13 14:19:53 -0800365 usleep(1000 * 1000);
San Mehatb78a32c2010-01-10 13:02:12 -0800366 }
367
368 if (rc) {
369 LOGE("Failed to unmount ASEC %s", id);
370 return -1;
371 }
372
San Mehatf5c61982010-02-03 11:04:46 -0800373 if (rmdir(mountPoint)) {
374 LOGE("Failed to rmdir mountpoint (%s)", strerror(errno));
375 }
San Mehat88705162010-01-15 09:26:28 -0800376
San Mehatb78a32c2010-01-10 13:02:12 -0800377 if (Devmapper::destroy(id) && errno != ENXIO) {
378 LOGE("Failed to destroy devmapper instance (%s)", strerror(errno));
San Mehata19b2502010-01-06 10:33:53 -0800379 }
380
381 char loopDevice[255];
382 if (!Loop::lookupActive(asecFileName, loopDevice, sizeof(loopDevice))) {
383 Loop::destroyByDevice(loopDevice);
384 }
San Mehat88705162010-01-15 09:26:28 -0800385
386 AsecIdCollection::iterator it;
387 for (it = mActiveContainers->begin(); it != mActiveContainers->end(); ++it) {
388 if (!strcmp(*it, id)) {
389 free(*it);
390 mActiveContainers->erase(it);
391 break;
392 }
393 }
394 if (it == mActiveContainers->end()) {
395 LOGW("mActiveContainers is inconsistent!");
396 }
San Mehatb78a32c2010-01-10 13:02:12 -0800397 return 0;
398}
399
400int VolumeManager::destroyAsec(const char *id) {
401 char asecFileName[255];
402 char mountPoint[255];
403
404 snprintf(asecFileName, sizeof(asecFileName),
405 "/sdcard/android_secure/%s.asec", id);
406 snprintf(mountPoint, sizeof(mountPoint), "/asec/%s", id);
407
San Mehat0586d542010-01-12 15:38:59 -0800408 if (isMountpointMounted(mountPoint)) {
San Mehat68f8ebd2010-01-23 07:21:21 -0800409 LOGD("Unmounting container before destroy");
San Mehat0586d542010-01-12 15:38:59 -0800410 if (unmountAsec(id)) {
411 LOGE("Failed to unmount asec %s for destroy (%s)", id, strerror(errno));
412 return -1;
413 }
414 }
San Mehata19b2502010-01-06 10:33:53 -0800415
San Mehat0586d542010-01-12 15:38:59 -0800416 if (unlink(asecFileName)) {
San Mehat68f8ebd2010-01-23 07:21:21 -0800417 LOGE("Failed to unlink asec '%s' (%s)", asecFileName, strerror(errno));
San Mehat0586d542010-01-12 15:38:59 -0800418 return -1;
419 }
San Mehata19b2502010-01-06 10:33:53 -0800420
421 LOGD("ASEC %s destroyed", id);
422 return 0;
423}
424
425int VolumeManager::mountAsec(const char *id, const char *key, int ownerUid) {
426 char asecFileName[255];
427 char mountPoint[255];
428
429 snprintf(asecFileName, sizeof(asecFileName),
430 "/sdcard/android_secure/%s.asec", id);
431 snprintf(mountPoint, sizeof(mountPoint), "/asec/%s", id);
432
433 if (isMountpointMounted(mountPoint)) {
434 LOGE("ASEC %s already mounted", id);
435 errno = EBUSY;
436 return -1;
437 }
438
439 char loopDevice[255];
440 if (Loop::lookupActive(asecFileName, loopDevice, sizeof(loopDevice))) {
San Mehat8da6bcb2010-01-09 12:24:05 -0800441 if (Loop::create(asecFileName, loopDevice, sizeof(loopDevice))) {
San Mehata19b2502010-01-06 10:33:53 -0800442 LOGE("ASEC loop device creation failed (%s)", strerror(errno));
443 return -1;
444 }
San Mehatb78a32c2010-01-10 13:02:12 -0800445 LOGD("New loop device created at %s", loopDevice);
446 } else {
447 LOGD("Found active loopback for %s at %s", asecFileName, loopDevice);
448 }
449
450 char dmDevice[255];
451 bool cleanupDm = false;
452 if (strcmp(key, "none")) {
453 if (Devmapper::lookupActive(id, dmDevice, sizeof(dmDevice))) {
454 unsigned int nr_sec = 0;
455 int fd;
456
457 if ((fd = open(loopDevice, O_RDWR)) < 0) {
458 LOGE("Failed to open loopdevice (%s)", strerror(errno));
459 Loop::destroyByDevice(loopDevice);
460 return -1;
461 }
462
463 if (ioctl(fd, BLKGETSIZE, &nr_sec)) {
464 LOGE("Failed to get loop size (%s)", strerror(errno));
465 Loop::destroyByDevice(loopDevice);
466 close(fd);
467 return -1;
468 }
469 close(fd);
San Mehat8b8f71b2010-01-11 09:17:25 -0800470 if (Devmapper::create(id, loopDevice, key, nr_sec,
San Mehatb78a32c2010-01-10 13:02:12 -0800471 dmDevice, sizeof(dmDevice))) {
472 LOGE("ASEC device mapping failed (%s)", strerror(errno));
473 Loop::destroyByDevice(loopDevice);
474 return -1;
475 }
476 LOGD("New devmapper instance created at %s", dmDevice);
477 } else {
478 LOGD("Found active devmapper for %s at %s", asecFileName, dmDevice);
479 }
480 cleanupDm = true;
481 } else {
482 strcpy(dmDevice, loopDevice);
San Mehata19b2502010-01-06 10:33:53 -0800483 }
484
485 if (mkdir(mountPoint, 0777)) {
San Mehatb78a32c2010-01-10 13:02:12 -0800486 if (errno != EEXIST) {
487 LOGE("Mountpoint creation failed (%s)", strerror(errno));
488 if (cleanupDm) {
489 Devmapper::destroy(id);
490 }
491 Loop::destroyByDevice(loopDevice);
492 return -1;
493 }
San Mehata19b2502010-01-06 10:33:53 -0800494 }
495
San Mehatb78a32c2010-01-10 13:02:12 -0800496 if (Fat::doMount(dmDevice, mountPoint, true, false, ownerUid, 0,
San Mehatcff5ec32010-01-08 12:31:44 -0800497 0222, false)) {
498// 0227, false)) {
San Mehata19b2502010-01-06 10:33:53 -0800499 LOGE("ASEC mount failed (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800500 if (cleanupDm) {
501 Devmapper::destroy(id);
502 }
503 Loop::destroyByDevice(loopDevice);
San Mehata19b2502010-01-06 10:33:53 -0800504 return -1;
505 }
506
San Mehat88705162010-01-15 09:26:28 -0800507 mActiveContainers->push_back(strdup(id));
San Mehata19b2502010-01-06 10:33:53 -0800508 LOGD("ASEC %s mounted", id);
509 return 0;
510}
511
San Mehat49e2bce2009-10-12 16:29:01 -0700512int VolumeManager::mountVolume(const char *label) {
513 Volume *v = lookupVolume(label);
514
515 if (!v) {
516 errno = ENOENT;
517 return -1;
518 }
519
San Mehata2677e42009-12-13 10:40:18 -0800520 return v->mountVol();
521}
522
523int VolumeManager::shareAvailable(const char *method, bool *avail) {
524
525 if (strcmp(method, "ums")) {
526 errno = ENOSYS;
527 return -1;
528 }
529
530 if (mUsbMassStorageConnected)
531 *avail = true;
532 else
533 *avail = false;
534 return 0;
535}
536
San Mehateba65e92010-01-29 05:15:16 -0800537int VolumeManager::shareEnabled(const char *label, const char *method, bool *enabled) {
538 Volume *v = lookupVolume(label);
539
540 if (!v) {
541 errno = ENOENT;
542 return -1;
543 }
544
545 if (strcmp(method, "ums")) {
546 errno = ENOSYS;
547 return -1;
548 }
549
550 if (v->getState() != Volume::State_Shared) {
San Mehateba65e92010-01-29 05:15:16 -0800551 *enabled = false;
San Mehatb9aed742010-02-04 15:07:01 -0800552 } else {
553 *enabled = true;
San Mehateba65e92010-01-29 05:15:16 -0800554 }
555 return 0;
556}
557
San Mehata2677e42009-12-13 10:40:18 -0800558int VolumeManager::simulate(const char *cmd, const char *arg) {
559
560 if (!strcmp(cmd, "ums")) {
561 if (!strcmp(arg, "connect")) {
562 notifyUmsConnected(true);
563 } else if (!strcmp(arg, "disconnect")) {
564 notifyUmsConnected(false);
565 } else {
566 errno = EINVAL;
567 return -1;
568 }
569 } else {
570 errno = EINVAL;
571 return -1;
572 }
573 return 0;
574}
575
576int VolumeManager::shareVolume(const char *label, const char *method) {
577 Volume *v = lookupVolume(label);
578
579 if (!v) {
580 errno = ENOENT;
581 return -1;
582 }
583
584 /*
585 * Eventually, we'll want to support additional share back-ends,
586 * some of which may work while the media is mounted. For now,
587 * we just support UMS
588 */
589 if (strcmp(method, "ums")) {
590 errno = ENOSYS;
591 return -1;
592 }
593
594 if (v->getState() == Volume::State_NoMedia) {
595 errno = ENODEV;
596 return -1;
597 }
598
San Mehat49e2bce2009-10-12 16:29:01 -0700599 if (v->getState() != Volume::State_Idle) {
San Mehata2677e42009-12-13 10:40:18 -0800600 // You need to unmount manually befoe sharing
San Mehat49e2bce2009-10-12 16:29:01 -0700601 errno = EBUSY;
602 return -1;
603 }
604
San Mehata2677e42009-12-13 10:40:18 -0800605 dev_t d = v->getDiskDevice();
606 if ((MAJOR(d) == 0) && (MINOR(d) == 0)) {
607 // This volume does not support raw disk access
608 errno = EINVAL;
609 return -1;
610 }
611
612 int fd;
613 char nodepath[255];
614 snprintf(nodepath,
615 sizeof(nodepath), "/dev/block/vold/%d:%d",
616 MAJOR(d), MINOR(d));
617
San Mehat0cde53c2009-12-22 08:32:33 -0800618 if ((fd = open("/sys/devices/platform/usb_mass_storage/lun0/file",
619 O_WRONLY)) < 0) {
San Mehata2677e42009-12-13 10:40:18 -0800620 LOGE("Unable to open ums lunfile (%s)", strerror(errno));
621 return -1;
622 }
623
624 if (write(fd, nodepath, strlen(nodepath)) < 0) {
625 LOGE("Unable to write to ums lunfile (%s)", strerror(errno));
626 close(fd);
627 return -1;
628 }
629
630 close(fd);
631 v->handleVolumeShared();
632 return 0;
633}
634
635int VolumeManager::unshareVolume(const char *label, const char *method) {
636 Volume *v = lookupVolume(label);
637
638 if (!v) {
639 errno = ENOENT;
640 return -1;
641 }
642
643 if (strcmp(method, "ums")) {
644 errno = ENOSYS;
645 return -1;
646 }
647
648 if (v->getState() != Volume::State_Shared) {
649 errno = EINVAL;
650 return -1;
651 }
652
653 dev_t d = v->getDiskDevice();
654
655 int fd;
656 char nodepath[255];
657 snprintf(nodepath,
658 sizeof(nodepath), "/dev/block/vold/%d:%d",
659 MAJOR(d), MINOR(d));
660
San Mehat0cde53c2009-12-22 08:32:33 -0800661 if ((fd = open("/sys/devices/platform/usb_mass_storage/lun0/file", O_WRONLY)) < 0) {
San Mehata2677e42009-12-13 10:40:18 -0800662 LOGE("Unable to open ums lunfile (%s)", strerror(errno));
663 return -1;
664 }
665
666 char ch = 0;
667 if (write(fd, &ch, 1) < 0) {
668 LOGE("Unable to write to ums lunfile (%s)", strerror(errno));
669 close(fd);
670 return -1;
671 }
672
673 close(fd);
674 v->handleVolumeUnshared();
675 return 0;
San Mehat49e2bce2009-10-12 16:29:01 -0700676}
677
678int VolumeManager::unmountVolume(const char *label) {
679 Volume *v = lookupVolume(label);
680
681 if (!v) {
682 errno = ENOENT;
683 return -1;
684 }
685
San Mehata2677e42009-12-13 10:40:18 -0800686 if (v->getState() == Volume::State_NoMedia) {
687 errno = ENODEV;
688 return -1;
689 }
690
San Mehat49e2bce2009-10-12 16:29:01 -0700691 if (v->getState() != Volume::State_Mounted) {
San Mehata2677e42009-12-13 10:40:18 -0800692 LOGW("Attempt to unmount volume which isn't mounted (%d)\n",
693 v->getState());
San Mehat49e2bce2009-10-12 16:29:01 -0700694 errno = EBUSY;
695 return -1;
696 }
697
San Mehat88705162010-01-15 09:26:28 -0800698 while(mActiveContainers->size()) {
699 AsecIdCollection::iterator it = mActiveContainers->begin();
700 LOGI("Unmounting ASEC %s (dependant on %s)", *it, v->getMountpoint());
701 if (unmountAsec(*it)) {
702 LOGE("Failed to unmount ASEC %s (%s) - unmount of %s may fail!", *it,
703 strerror(errno), v->getMountpoint());
704 }
705 }
706
San Mehata2677e42009-12-13 10:40:18 -0800707 return v->unmountVol();
San Mehat49e2bce2009-10-12 16:29:01 -0700708}
709
San Mehata2677e42009-12-13 10:40:18 -0800710/*
711 * Looks up a volume by it's label or mount-point
712 */
San Mehat49e2bce2009-10-12 16:29:01 -0700713Volume *VolumeManager::lookupVolume(const char *label) {
714 VolumeCollection::iterator i;
715
716 for (i = mVolumes->begin(); i != mVolumes->end(); ++i) {
San Mehata2677e42009-12-13 10:40:18 -0800717 if (label[0] == '/') {
718 if (!strcmp(label, (*i)->getMountpoint()))
719 return (*i);
720 } else {
721 if (!strcmp(label, (*i)->getLabel()))
722 return (*i);
723 }
San Mehat49e2bce2009-10-12 16:29:01 -0700724 }
725 return NULL;
726}
San Mehata19b2502010-01-06 10:33:53 -0800727
728bool VolumeManager::isMountpointMounted(const char *mp)
729{
730 char device[256];
731 char mount_path[256];
732 char rest[256];
733 FILE *fp;
734 char line[1024];
735
736 if (!(fp = fopen("/proc/mounts", "r"))) {
737 LOGE("Error opening /proc/mounts (%s)", strerror(errno));
738 return false;
739 }
740
741 while(fgets(line, sizeof(line), fp)) {
742 line[strlen(line)-1] = '\0';
743 sscanf(line, "%255s %255s %255s\n", device, mount_path, rest);
744 if (!strcmp(mount_path, mp)) {
745 fclose(fp);
746 return true;
747 }
748
749 }
750
751 fclose(fp);
752 return false;
753}
754