1deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey/* 2deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey * Copyright (C) 2015 The Android Open Source Project 3deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey * 4deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License"); 5deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey * you may not use this file except in compliance with the License. 6deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey * You may obtain a copy of the License at 7deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey * 8deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey * http://www.apache.org/licenses/LICENSE-2.0 9deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey * 10deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey * Unless required by applicable law or agreed to in writing, software 11deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS, 12deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey * See the License for the specific language governing permissions and 14deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey * limitations under the License. 15deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey */ 16deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey 17deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey#include "EmulatedVolume.h" 18deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey#include "Utils.h" 19deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey 207e128fbe212c64492afa98bfd6d7fab6f1956831Elliott Hughes#include <android-base/stringprintf.h> 217e128fbe212c64492afa98bfd6d7fab6f1956831Elliott Hughes#include <android-base/logging.h> 22deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey#include <cutils/fs.h> 23deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey#include <private/android_filesystem_config.h> 24deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey 25deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey#include <fcntl.h> 26deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey#include <stdlib.h> 27deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey#include <sys/mount.h> 28deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey#include <sys/stat.h> 29deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey#include <sys/types.h> 300e08e84df0d0b555cf20e3bbe68bb4da7c287012Elliott Hughes#include <sys/sysmacros.h> 31deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey#include <sys/wait.h> 32deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey 33ae9e8903375e13028b140e86fcc68c6e152b6f43Dan Albertusing android::base::StringPrintf; 34ae9e8903375e13028b140e86fcc68c6e152b6f43Dan Albert 35deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkeynamespace android { 36deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkeynamespace vold { 37deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey 38deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkeystatic const char* kFusePath = "/system/bin/sdcard"; 39deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey 403161fb3702830b586b2e36fa9ca4519f59f951b4Jeff SharkeyEmulatedVolume::EmulatedVolume(const std::string& rawPath) : 413161fb3702830b586b2e36fa9ca4519f59f951b4Jeff Sharkey VolumeBase(Type::kEmulated), mFusePid(0) { 423161fb3702830b586b2e36fa9ca4519f59f951b4Jeff Sharkey setId("emulated"); 433161fb3702830b586b2e36fa9ca4519f59f951b4Jeff Sharkey mRawPath = rawPath; 4466270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey mLabel = "emulated"; 453161fb3702830b586b2e36fa9ca4519f59f951b4Jeff Sharkey} 46deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey 473161fb3702830b586b2e36fa9ca4519f59f951b4Jeff SharkeyEmulatedVolume::EmulatedVolume(const std::string& rawPath, dev_t device, 483161fb3702830b586b2e36fa9ca4519f59f951b4Jeff Sharkey const std::string& fsUuid) : VolumeBase(Type::kEmulated), mFusePid(0) { 493161fb3702830b586b2e36fa9ca4519f59f951b4Jeff Sharkey setId(StringPrintf("emulated:%u,%u", major(device), minor(device))); 50deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey mRawPath = rawPath; 5166270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey mLabel = fsUuid; 52deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey} 53deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey 54deb240573754daf36fa8ea10a05240f9f31e7b2cJeff SharkeyEmulatedVolume::~EmulatedVolume() { 55deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey} 56deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey 57deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkeystatus_t EmulatedVolume::doMount() { 5881f55c6dc1a14ed68e404fa3a2c244dd343e4990Jeff Sharkey // We could have migrated storage to an adopted private volume, so always 5981f55c6dc1a14ed68e404fa3a2c244dd343e4990Jeff Sharkey // call primary storage "emulated" to avoid media rescans. 6081f55c6dc1a14ed68e404fa3a2c244dd343e4990Jeff Sharkey std::string label = mLabel; 6181f55c6dc1a14ed68e404fa3a2c244dd343e4990Jeff Sharkey if (getMountFlags() & MountFlags::kPrimary) { 6281f55c6dc1a14ed68e404fa3a2c244dd343e4990Jeff Sharkey label = "emulated"; 6381f55c6dc1a14ed68e404fa3a2c244dd343e4990Jeff Sharkey } 6481f55c6dc1a14ed68e404fa3a2c244dd343e4990Jeff Sharkey 651bd078fa7b5ca613cb3e793d67ccd86d2602787dJeff Sharkey mFuseDefault = StringPrintf("/mnt/runtime/default/%s", label.c_str()); 661bd078fa7b5ca613cb3e793d67ccd86d2602787dJeff Sharkey mFuseRead = StringPrintf("/mnt/runtime/read/%s", label.c_str()); 671bd078fa7b5ca613cb3e793d67ccd86d2602787dJeff Sharkey mFuseWrite = StringPrintf("/mnt/runtime/write/%s", label.c_str()); 6866270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey 6966270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey setInternalPath(mRawPath); 7081f55c6dc1a14ed68e404fa3a2c244dd343e4990Jeff Sharkey setPath(StringPrintf("/storage/%s", label.c_str())); 7166270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey 7266270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey if (fs_prepare_dir(mFuseDefault.c_str(), 0700, AID_ROOT, AID_ROOT) || 7366270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey fs_prepare_dir(mFuseRead.c_str(), 0700, AID_ROOT, AID_ROOT) || 7466270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey fs_prepare_dir(mFuseWrite.c_str(), 0700, AID_ROOT, AID_ROOT)) { 7566270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey PLOG(ERROR) << getId() << " failed to create mount points"; 76deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey return -errno; 77deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey } 78deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey 7966270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey dev_t before = GetDevice(mFuseWrite); 8036801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey 81deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey if (!(mFusePid = fork())) { 8236801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey if (execl(kFusePath, kFusePath, 83deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey "-u", "1023", // AID_MEDIA_RW 84deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey "-g", "1023", // AID_MEDIA_RW 8566270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey "-m", 8666270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey "-w", 8775ae529bf86c33106e6a716ad054c6eea6deabc5Rom Lemarchand "-G", 88deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey mRawPath.c_str(), 8981f55c6dc1a14ed68e404fa3a2c244dd343e4990Jeff Sharkey label.c_str(), 9036801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey NULL)) { 9136801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey PLOG(ERROR) << "Failed to exec"; 92deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey } 9336801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey 94c7b5b570bd05ed3bc921b0c2dc346416a52b4e3eJeff Sharkey LOG(ERROR) << "FUSE exiting"; 95deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey _exit(1); 96deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey } 97deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey 98deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey if (mFusePid == -1) { 999c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey PLOG(ERROR) << getId() << " failed to fork"; 100deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey return -errno; 101deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey } 102deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey 10366270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey while (before == GetDevice(mFuseWrite)) { 10466270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey LOG(VERBOSE) << "Waiting for FUSE to spin up..."; 10566270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey usleep(50000); // 50ms 10666270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey } 1071d79d1014e481c92c3f802bbaf174409d191571fDaniel Rosenberg /* sdcardfs will have exited already. FUSE will still be running */ 1081d79d1014e481c92c3f802bbaf174409d191571fDaniel Rosenberg TEMP_FAILURE_RETRY(waitpid(mFusePid, nullptr, WNOHANG)); 10966270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey 110deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey return OK; 111deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey} 112deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey 113deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkeystatus_t EmulatedVolume::doUnmount() { 114ea243a3015edc86428167e97a1ab50c85cf409f2Narayan Kamath // Unmount the storage before we kill the FUSE process. If we kill 115ea243a3015edc86428167e97a1ab50c85cf409f2Narayan Kamath // the FUSE process first, most file system operations will return 116ea243a3015edc86428167e97a1ab50c85cf409f2Narayan Kamath // ENOTCONN until the unmount completes. This is an exotic and unusual 117ea243a3015edc86428167e97a1ab50c85cf409f2Narayan Kamath // error code and might cause broken behaviour in applications. 118ea243a3015edc86428167e97a1ab50c85cf409f2Narayan Kamath KillProcessesUsingPath(getPath()); 119ea243a3015edc86428167e97a1ab50c85cf409f2Narayan Kamath ForceUnmount(mFuseDefault); 120ea243a3015edc86428167e97a1ab50c85cf409f2Narayan Kamath ForceUnmount(mFuseRead); 121ea243a3015edc86428167e97a1ab50c85cf409f2Narayan Kamath ForceUnmount(mFuseWrite); 122ea243a3015edc86428167e97a1ab50c85cf409f2Narayan Kamath 123deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey if (mFusePid > 0) { 124deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey kill(mFusePid, SIGTERM); 125deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey TEMP_FAILURE_RETRY(waitpid(mFusePid, nullptr, 0)); 126deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey mFusePid = 0; 127deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey } 128deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey 12966270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey rmdir(mFuseDefault.c_str()); 13066270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey rmdir(mFuseRead.c_str()); 13166270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey rmdir(mFuseWrite.c_str()); 13266270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey 13366270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey mFuseDefault.clear(); 13466270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey mFuseRead.clear(); 13566270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey mFuseWrite.clear(); 136deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey 137deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey return OK; 138deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey} 139deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey 140deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey} // namespace vold 141deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey} // namespace android 142