bool PlatformUdisks2::unmountDevice(QString path) { bool res = true; QStringList partitions = getPartitionList(path); if (partitions.empty()) { res = doUnmount(QString("/org/freedesktop/UDisks2/block_devices/") + path); } else { foreach(QString partition, partitions) { if (isPartitionMounted(partition) && !doUnmount(partition)) { res = false; break; } } } return(res); }
bool PlatformUdisks2::unmountDevice(QString path) { bool res = true; QStringList partitions = getPartitionList(path); foreach(QString partition, partitions) { if (!doUnmount(partition)) { res = false; break; } } return(res); }
int Volume::unmountVol(bool force, bool revert) { int i, rc; if (getState() != Volume::State_Mounted) { SLOGE("Volume %s unmount request when not mounted", getLabel()); errno = EINVAL; return UNMOUNT_NOT_MOUNTED_ERR; } setState(Volume::State_Unmounting); usleep(1000 * 1000); // Give the framework some time to react /* * First move the mountpoint back to our internal staging point * so nobody else can muck with it while we work. */ if (doMoveMount(getMountpoint(), SEC_STGDIR, force)) { SLOGE("Failed to move mount %s => %s (%s)", getMountpoint(), SEC_STGDIR, strerror(errno)); setState(Volume::State_Mounted); return -1; } protectFromAutorunStupidity(); /* * Unmount the tmpfs which was obscuring the asec image directory * from non root users */ if (doUnmount(Volume::SEC_STG_SECIMGDIR, force)) { SLOGE("Failed to unmount tmpfs on %s (%s)", SEC_STG_SECIMGDIR, strerror(errno)); goto fail_republish; } /* * Remove the bindmount we were using to keep a reference to * the previously obscured directory. */ if (doUnmount(Volume::SEC_ASECDIR, force)) { SLOGE("Failed to remove bindmount on %s (%s)", SEC_ASECDIR, strerror(errno)); goto fail_remount_tmpfs; } /* * Finally, unmount the actual block device from the staging dir */ if (doUnmount(Volume::SEC_STGDIR, force)) { SLOGE("Failed to unmount %s (%s)", SEC_STGDIR, strerror(errno)); goto fail_recreate_bindmount; } SLOGI("%s unmounted sucessfully", getMountpoint()); /* If this is an encrypted volume, and we've been asked to undo * the crypto mapping, then revert the dm-crypt mapping, and revert * the device info to the original values. */ if (revert && isDecrypted()) { cryptfs_revert_volume(getLabel()); revertDeviceInfo(); SLOGI("Encrypted volume %s reverted successfully", getMountpoint()); } setState(Volume::State_Idle); mCurrentlyMountedKdev = -1; return 0; /* * Failure handling - try to restore everything back the way it was */ fail_recreate_bindmount: if (mount(SEC_STG_SECIMGDIR, SEC_ASECDIR, "", MS_BIND, NULL)) { SLOGE("Failed to restore bindmount after failure! - Storage will appear offline!"); goto out_nomedia; } fail_remount_tmpfs: if (mount("tmpfs", SEC_STG_SECIMGDIR, "tmpfs", MS_RDONLY, "size=0,mode=0,uid=0,gid=0")) { SLOGE("Failed to restore tmpfs after failure! - Storage will appear offline!"); goto out_nomedia; } fail_republish: if (doMoveMount(SEC_STGDIR, getMountpoint(), force)) { SLOGE("Failed to republish mount after failure! - Storage will appear offline!"); goto out_nomedia; } setState(Volume::State_Mounted); return -1; out_nomedia: setState(Volume::State_NoMedia); return -1; }
int Volume::unmountVol(bool force, bool revert) { int i, rc; int flags = getFlags(); bool providesAsec = (flags & VOL_PROVIDES_ASEC) != 0; bool is_emulated_sd = false; #ifdef MTK_SHARED_SDCARD if (IsEmmcStorage()) { providesAsec = false; is_emulated_sd = true; } #endif if (getState() != Volume::State_Mounted) { SLOGE("Volume %s unmount request when not mounted", getLabel()); errno = EINVAL; return UNMOUNT_NOT_MOUNTED_ERR; } #ifdef MTK_MULTI_PARTITION_MOUNT_ONLY_SUPPORT if (false == isMountpointMounted(getFuseMountpoint())) { SLOGD("usbotg: Volume unmountVol %s is already unmounted", getFuseMountpoint()); goto unmount_success; } #endif setState(Volume::State_Unmounting); usleep(1000 * 100); // Give the framework some time to react char service[64]; char service_id[64]; strcpy(service_id, getMountpoint()+strlen(Volume::MEDIA_DIR)+1); snprintf(service, 64, "fuse_%s", service_id); if (is_emulated_sd) { snprintf(service, 64, "sdcard"); } #ifdef MTK_MULTI_PARTITION_MOUNT_ONLY_SUPPORT if (0 == strcmp(getLabel(), "usbotg")) { sPid = mPid; SLOGD("usbotg: Volume unmountVol ,mPid=%d",mPid); if(-1 != mPid) { kill(mPid,SIGKILL); } SLOGD("usbotg: Volume unmountVol ,mountpoint=%s",getFuseMountpoint()); if (doUnmount(getFuseMountpoint(), force)) { SLOGE("Failed to unmount %s (%s)", getFuseMountpoint(), strerror(errno)); goto fail_remount_secure; } if (doUnmount(getMountpoint(), force)) { SLOGE("Failed to unmount %s (%s)", getMountpoint(), strerror(errno)); goto fail_remount_secure; } SLOGI("usbotg: Volume unmounted sucessfully"); } else { property_set("ctl.stop", service); /* Give it a chance to stop. I wish we had a synchronous way to determine this... */ //sleep(1); waitForServiceState(service, "stopped"); // TODO: determine failure mode if FUSE times out if (providesAsec && doUnmount(Volume::SEC_ASECDIR_EXT, force) != 0) { SLOGE("Failed to unmount secure area on %s (%s)", getMountpoint(), strerror(errno)); goto out_mounted; } /* Now that the fuse daemon is dead, unmount it */ if (doUnmount(getFuseMountpoint(), force) != 0) { SLOGE("Failed to unmount %s (%s)", getFuseMountpoint(), strerror(errno)); goto fail_remount_secure; } /* Unmount the real sd card */ if (!is_emulated_sd) { if (doUnmount(getMountpoint(), force) != 0) { SLOGE("Failed to unmount %s (%s)", getMountpoint(), strerror(errno)); goto fail_remount_secure; } SLOGI("%s unmounted successfully", getMountpoint()); } } #else { #define MAX_NEED_TO_WAIT 10 bool need_to_wait = false; int need_to_wait_count = 0; do { Process::killProcessesWithOpenFiles(getFuseMountpoint(), 0, "mdlogger", &need_to_wait); if(need_to_wait) { need_to_wait_count++; SLOGI("need_to_wait=%d, need_to_wait_count=%d,", need_to_wait, need_to_wait_count); usleep(1000*1000); } else { break; } } while (need_to_wait && need_to_wait_count < MAX_NEED_TO_WAIT); property_set("ctl.stop", service); /* Give it a chance to stop. I wish we had a synchronous way to determine this... */ //sleep(1); waitForServiceState(service, "stopped"); // TODO: determine failure mode if FUSE times out if (providesAsec && doUnmount(Volume::SEC_ASECDIR_EXT, force) != 0) { SLOGE("Failed to unmount secure area on %s (%s)", getMountpoint(), strerror(errno)); goto out_mounted; } /* Now that the fuse daemon is dead, unmount it */ if (doUnmount(getFuseMountpoint(), force) != 0) { SLOGE("Failed to unmount %s (%s)", getFuseMountpoint(), strerror(errno)); goto fail_remount_secure; } /* Unmount the real sd card */ if (!is_emulated_sd) { if (doUnmount(getMountpoint(), force) != 0) { SLOGE("Failed to unmount %s (%s)", getMountpoint(), strerror(errno)); goto fail_remount_secure; } SLOGI("%s unmounted successfully", getMountpoint()); } } #endif /* If this is an encrypted volume, and we've been asked to undo * the crypto mapping, then revert the dm-crypt mapping, and revert * the device info to the original values. */ if (revert && isDecrypted()) { cryptfs_revert_volume(getLabel()); revertDeviceInfo(); SLOGI("Encrypted volume %s reverted successfully", getMountpoint()); } setUuid(NULL); setUserLabel(NULL); setState(Volume::State_Idle); unmount_success: mCurrentlyMountedKdev = -1; #ifdef MTK_MULTI_PARTITION_MOUNT_ONLY_SUPPORT if (0 == strcmp(getLabel(), "usbotg")) { char cmd[255] = {0}; sprintf(cmd, "/system/bin/sh -c \"rm -r %s\"", getFuseMountpoint()); system(cmd); SLOGD("usbotg: Volume unmountVol cmd = %s !!!", cmd); sprintf(cmd, "/system/bin/sh -c \"rm -r %s\"", getMountpoint()); system(cmd); SLOGD("usbotg: Volume unmountVol cmd = %s !!!", cmd); //remove(getMountpoint()); } #endif return 0; fail_remount_secure: if (providesAsec && mountAsecExternal() != 0) { SLOGE("Failed to remount secure area (%s)", strerror(errno)); goto out_nomedia; } out_mounted: property_set("ctl.start", service); waitForServiceState(service, "running"); setState(Volume::State_Mounted); return -1; out_nomedia: setState(Volume::State_NoMedia); return -1; }
void DirectVolume::handlePartitionRemoved(const char *devpath, NetlinkEvent *evt) { int major = atoi(evt->findParam("MAJOR")); int minor = atoi(evt->findParam("MINOR")); char msg[255]; int state; SLOGD("Volume %s %s partition %d:%d removed\n", getLabel(), getMountpoint(), major, minor); char voldpath[255]; sprintf(voldpath,"/dev/block/vold/%d:%d",major,minor); sem_wait(udisk_sem); for(int i=0;i<EXTRA_UDISK_NUM;i++){ //SLOGD("extra_udisk_valid[%d] %d %s\n",i,extra_udisk_valid[i],extra_udisk_devpath[i]); if(extra_udisk_valid[i]!=0&&!strcmp(voldpath,extra_udisk_devpath[i])){ SLOGD("doUnmount extra_udisk_path %s\n",extra_udisk_mountpath[i]); if (doUnmount(extra_udisk_mountpath[i], true)) { SLOGE("Failed to remove bindmount on %s (%s)", SEC_ASECDIR_EXT, strerror(errno)); sem_post(udisk_sem); return; } extra_udisk_valid[i] = 0; udiskSetState(State_Unmounting,i,extra_udisk_mountpath[i]); udiskSetState(State_Idle,i,extra_udisk_mountpath[i]); udiskSetState(State_NoMedia,i,extra_udisk_mountpath[i]); snprintf(msg, sizeof(msg), "Volume Udisk%d %s disk removed (%d:%d)", i, extra_udisk_mountpath[i], major, minor); mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeDiskRemoved, msg, false); sem_post(udisk_sem); return; } } sem_post(udisk_sem); /* * The framework doesn't need to get notified of * partition removal unless it's mounted. Otherwise * the removal notification will be sent on the Disk * itself */ state = getState(); /* Remove event interrupted the add event, if state is checking, * let remove event sleep, add event complete than remove event. */ while (state == Volume::State_Checking) { sleep(1); SLOGD("code from tp,Fail removed state =%d", state); state = getState(); SLOGD("code from tp,new removed state =%d", state); } if (state != Volume::State_Mounted && state != Volume::State_Shared) { return; } if ((dev_t) MKDEV(major, minor) == mCurrentlyMountedKdev) { /* * Yikes, our mounted partition is going away! */ snprintf(msg, sizeof(msg), "Volume %s %s bad removal (%d:%d)", getLabel(), getMountpoint(), major, minor); mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeBadRemoval, msg, false); if (mVm->cleanupAsec(this, true)) { SLOGE("Failed to cleanup ASEC - unmount will probably fail!"); } if (Volume::unmountVol(true, false)) { SLOGE("Failed to unmount volume on bad removal (%s)", strerror(errno)); // XXX: At this point we're screwed for now } else { SLOGD("Crisis averted"); } } else if (state == Volume::State_Shared) { /* removed during mass storage */ snprintf(msg, sizeof(msg), "Volume %s bad removal (%d:%d)", getLabel(), major, minor); mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeBadRemoval, msg, false); if (mVm->unshareVolume(getLabel(), "ums")) { SLOGE("Failed to unshare volume on bad removal (%s)", strerror(errno)); } else { SLOGD("Crisis averted"); } } }
int Volume::unmountVol(bool force) { int i, rc; if (getState() != Volume::State_Mounted) { SLOGE("Volume %s unmount request when not mounted", getLabel()); errno = EINVAL; return -1; } setState(Volume::State_Unmounting); usleep(1000 * 1000); // Give the framework some time to react /* * First move the mountpoint back to our internal staging point * so nobody else can muck with it while we work. */ if (doMoveMount(getMountpoint(), SEC_STGDIR, force)) { SLOGE("Failed to move mount %s => %s (%s)", getMountpoint(), SEC_STGDIR, strerror(errno)); setState(Volume::State_Mounted); return -1; } protectFromAutorunStupidity(); /* Undo createBindMounts(), which is only called for EXTERNAL_STORAGE */ const char *externalPath = getenv("EXTERNAL_STORAGE") ?: "/mnt/sdcard"; if (0 == strcmp(getMountpoint(), externalPath)) { /* * Unmount the tmpfs which was obscuring the asec image directory * from non root users */ if (doUnmount(Volume::SEC_STG_SECIMGDIR, force)) { SLOGE("Failed to unmount tmpfs on %s (%s)", SEC_STG_SECIMGDIR, strerror(errno)); goto fail_republish; } /* * Remove the bindmount we were using to keep a reference to * the previously obscured directory. */ if (doUnmount(Volume::SEC_ASECDIR, force)) { SLOGE("Failed to remove bindmount on %s (%s)", SEC_ASECDIR, strerror(errno)); goto fail_remount_tmpfs; } } /* * Finally, unmount the actual block device from the staging dir */ if (doUnmount(Volume::SEC_STGDIR, force)) { SLOGE("Failed to unmount %s (%s)", SEC_STGDIR, strerror(errno)); goto fail_recreate_bindmount; } SLOGI("%s unmounted sucessfully", getMountpoint()); setState(Volume::State_Idle); mCurrentlyMountedKdev = -1; return 0; /* * Failure handling - try to restore everything back the way it was */ fail_recreate_bindmount: if (mount(SEC_STG_SECIMGDIR, SEC_ASECDIR, "", MS_BIND, NULL)) { SLOGE("Failed to restore bindmount after failure! - Storage will appear offline!"); goto out_nomedia; } fail_remount_tmpfs: if (mount("tmpfs", SEC_STG_SECIMGDIR, "tmpfs", MS_RDONLY, "size=0,mode=0,uid=0,gid=0")) { SLOGE("Failed to restore tmpfs after failure! - Storage will appear offline!"); goto out_nomedia; } fail_republish: if (doMoveMount(SEC_STGDIR, getMountpoint(), force)) { SLOGE("Failed to republish mount after failure! - Storage will appear offline!"); goto out_nomedia; } setState(Volume::State_Mounted); return -1; out_nomedia: setState(Volume::State_NoMedia); return -1; }
int Volume::mountVol() { dev_t deviceNodes[4]; int n, i, rc = 0; char errmsg[255]; if (getState() == Volume::State_NoMedia) { snprintf(errmsg, sizeof(errmsg), "Volume %s %s mount failed - no media", getLabel(), getMountpoint()); mVm->getBroadcaster()->sendBroadcast( ResponseCode::VolumeMountFailedNoMedia, errmsg, false); errno = ENODEV; return -1; } else if ((getState() != Volume::State_Idle) && (getState() != Volume::State_Pending)) { errno = EBUSY; return -1; } if (isMountpointMounted(getMountpoint())) { SLOGW("Volume is idle but appears to be mounted - fixing"); if(doUnmount(getMountpoint(), true)) { SLOGW("Still unmount failure, set mount state"); setState(Volume::State_Mounted); //mCurrentlyMountedKdev = XXX return 0; } } n = getDeviceNodes((dev_t *) &deviceNodes, 6); if (!n) { SLOGE("Failed to get device nodes (%s)\n", strerror(errno)); return -1; } for (i = 0; i < n; i++) { sprintf(devicePath, "/dev/block/vold/%d:%d", MAJOR(deviceNodes[i]), MINOR(deviceNodes[i])); SLOGI("%s is checking for volume %s\n", devicePath, getLabel()); errno = 0; setState(Volume::State_Checking); if (Fat::check(devicePath)) { if ((errno == ENODATA) || (errno == ENOEXEC)) { SLOGW("%s does not contain a FAT filesystem\n", devicePath); continue; } errno = EIO; /* Badness - abort the mount */ SLOGE("%s failed FS checks (%s)", devicePath, strerror(errno)); setState(Volume::State_Idle); return -1; } if (!strcmp(getLabel(), "sdcard")) { /* * Mount the device on our internal staging mountpoint so we can * muck with it before exposing it to non priviledged users. */ errno = 0; if (Fat::doMount(devicePath, "/mnt/secure/staging", false, false, false, 1000, 1015, 0002, true)) { SLOGE("%s failed to mount via VFAT (%s)\n", devicePath, strerror(errno)); continue; } SLOGI("Device %s, target %s mounted @ /mnt/secure/staging", devicePath, getMountpoint()); protectFromAutorunStupidity(); if (createBindMounts()) { SLOGE("Failed to create bindmounts (%s)", strerror(errno)); umount("/mnt/secure/staging"); setState(Volume::State_Idle); return -1; } /* * Now that the bindmount trickery is done, atomically move the * whole subtree to expose it to non priviledged users. */ if (doMoveMount("/mnt/secure/staging", getMountpoint(), false)) { SLOGE("Failed to move mount (%s)", strerror(errno)); umount("/mnt/secure/staging"); setState(Volume::State_Idle); return -1; } } else { int fd = open(getMountpoint(), O_DIRECTORY, O_RDWR); if (fd == -1) { if(mkdir(getMountpoint(), 0777) == -1) { SLOGE("Can't create the mount path: %s, error:%d.", getMountpoint(), errno); break; } } close(fd); //if ( !isMountpointMounted("/mnt/sdcard") ) { //break; //} if (Fat::doMount(devicePath, getMountpoint(), false, false, false, 1000, 1015, 0002, true)) { SLOGE("%s failed to mount via VFAT (%s)\n", devicePath, strerror(errno)); continue; } } setState(Volume::State_Mounted); mCurrentlyMountedKdev = deviceNodes[i]; return 0; } SLOGE("Volume %s found no suitable devices for mounting :(\n", getLabel()); setState(Volume::State_Idle); return -1; }