MoveTask.cpp \
Benchmark.cpp \
TrimTask.cpp \
+ main.cpp
common_c_includes := \
system/extras/ext4_utils \
hardware/libhardware/include/hardware \
system/security/softkeymaster/include/keymaster
-common_shared_libraries := \
+common_libraries := \
libsysutils \
libbinder \
libcutils \
liblog \
libdiskconfig \
- libhardware_legacy \
liblogwrap \
- libext4_utils \
libf2fs_sparseblock \
- libcrypto \
libselinux \
- libutils \
+ libutils
+
+common_shared_libraries := \
+ $(common_libraries) \
+ libhardware_legacy \
+ libext4_utils \
+ libcrypto \
libhardware \
libsoftkeymaster \
libbase \
- libext2_blkid
+ libext2_blkid
common_static_libraries := \
libfs_mgr \
+ libext4_utils_static \
+ libsparse_static \
libsquashfs_utils \
libscrypt_static \
libmincrypt \
libbatteryservice \
- libext2_blkid \
- libext2_uuid_static
+ libext2_blkid \
+ libext2_uuid_static \
+ libz
vold_conlyflags := -std=c11
vold_cflags := -Werror -Wall -Wno-missing-field-initializers -Wno-unused-variable -Wno-unused-parameter
LOCAL_MODULE:= vold
LOCAL_CLANG := true
LOCAL_SRC_FILES := \
- main.cpp \
- $(common_src_files)
+ vold.c
LOCAL_C_INCLUDES := $(common_c_includes)
LOCAL_CFLAGS := $(vold_cflags)
endif
LOCAL_SHARED_LIBRARIES := $(common_shared_libraries)
-LOCAL_STATIC_LIBRARIES := $(common_static_libraries)
+LOCAL_STATIC_LIBRARIES := libvold $(common_static_libraries)
include $(BUILD_EXECUTABLE)
LOCAL_CONLYFLAGS := $(vold_conlyflags)
include $(BUILD_EXECUTABLE)
+
+include $(CLEAR_VARS)
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+LOCAL_MODULE := libminivold
+LOCAL_CLANG := true
+LOCAL_SRC_FILES := $(common_src_files)
+LOCAL_C_INCLUDES := $(common_c_includes) system/core/fs_mgr/include system/core/logwrapper/include
+LOCAL_SHARED_LIBRARIES := $(common_shared_libraries)
+LOCAL_STATIC_LIBRARIES := $(common_static_libraries)
+LOCAL_MODULE_TAGS := eng tests
+LOCAL_CFLAGS := $(vold_cflags) -DMINIVOLD -DHELPER_PATH=\"/sbin/\"
+LOCAL_CONLYFLAGS := $(vold_conlyflags)
+include $(BUILD_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+LOCAL_MODULE := minivold
+LOCAL_CLANG := true
+LOCAL_SRC_FILES := vold.c
+LOCAL_C_INCLUDES := $(common_c_includes)
+LOCAL_CFLAGS := $(vold_cflags) -DMINIVOLD
+LOCAL_CONLYFLAGS := $(vold_conlyflags)
+LOCAL_STATIC_LIBRARIES := libminivold
+LOCAL_STATIC_LIBRARIES += libc libc++_static libm
+LOCAL_STATIC_LIBRARIES += libbase
+LOCAL_STATIC_LIBRARIES += $(common_static_libraries) $(common_libraries)
+LOCAL_STATIC_LIBRARIES += libcrypto_static libext2_uuid libvold
+LOCAL_STATIC_LIBRARIES += libnl
+LOCAL_SHARED_LIBRARIES := $(common_shared_libraries)
+LOCAL_FORCE_STATIC_EXECUTABLE := true
+LOCAL_PACK_MODULE_RELOCATIONS := false
+LOCAL_MODULE_CLASS := RECOVERY_EXECUTABLES
+LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin
+LOCAL_MODULE_TAGS := optional
+include $(BUILD_EXECUTABLE)
return sendGenericOkFail(cli, res);
} else if (cmd == "unmount" && argc > 2) {
- // unmount [volId]
+ // unmount [volId] [detach]
std::string id(argv[2]);
auto vol = vm->findVolume(id);
if (vol == nullptr) {
return cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown volume", false);
}
+ bool detach = (argc > 3 && !strcmp(argv[3], "detach"));
- return sendGenericOkFail(cli, vol->unmount());
+ return sendGenericOkFail(cli, vol->unmount(detach));
} else if (cmd == "format" && argc > 3) {
// format [volId] [fsType|auto]
namespace android {
namespace vold {
+#ifdef MINIVOLD
+static const char* kSgdiskPath = "/sbin/sgdisk";
+#else
static const char* kSgdiskPath = "/system/bin/sgdisk";
+#endif
static const char* kSgdiskToken = " \t\n";
static const char* kSysfsMmcMaxMinors = "/sys/module/mmcblk/parameters/perdev_minors";
}
void Disk::createPublicVolume(dev_t device) {
- auto vol = std::shared_ptr<VolumeBase>(new PublicVolume(device));
+ auto vol = std::shared_ptr<VolumeBase>(new PublicVolume(device, mNickname));
if (mJustPartitioned) {
LOG(DEBUG) << "Device just partitioned; silently formatting";
vol->setSilent(true);
#include "EmulatedVolume.h"
#include "Utils.h"
+#include "ResponseCode.h"
#include <base/stringprintf.h>
#include <base/logging.h>
namespace android {
namespace vold {
+#ifdef MINIVOLD
+static const char* kFusePath = "/sbin/sdcard";
+#else
static const char* kFusePath = "/system/bin/sdcard";
+#endif
EmulatedVolume::EmulatedVolume(const std::string& rawPath) :
VolumeBase(Type::kEmulated), mFusePid(0) {
EmulatedVolume::~EmulatedVolume() {
}
+status_t EmulatedVolume::doCreate() {
+ if (mLabel.size() > 0) {
+ notifyEvent(ResponseCode::VolumeFsLabelChanged, mLabel);
+ }
+ return OK;
+}
+
status_t EmulatedVolume::doMount() {
// We could have migrated storage to an adopted private volume, so always
// call primary storage "emulated" to avoid media rescans.
return OK;
}
-status_t EmulatedVolume::doUnmount() {
+status_t EmulatedVolume::doUnmount(bool detach /* = false */) {
if (mFusePid > 0) {
kill(mFusePid, SIGTERM);
TEMP_FAILURE_RETRY(waitpid(mFusePid, nullptr, 0));
virtual ~EmulatedVolume();
protected:
+ status_t doCreate() override;
status_t doMount() override;
- status_t doUnmount() override;
+ status_t doUnmount(bool detach = false) override;
private:
std::string mRawPath;
return OK;
}
-status_t PrivateVolume::doUnmount() {
+status_t PrivateVolume::doUnmount(bool detach /* = false */) {
ForceUnmount(mPath);
if (TEMP_FAILURE_RETRY(rmdir(mPath.c_str()))) {
status_t doCreate() override;
status_t doDestroy() override;
status_t doMount() override;
- status_t doUnmount() override;
+ status_t doUnmount(bool detach = false) override;
status_t doFormat(const std::string& fsType) override;
status_t readMetadata();
namespace android {
namespace vold {
+#ifdef MINIVOLD
+static const char* kFusePath = "/sbin/sdcard";
+#else
static const char* kFusePath = "/system/bin/sdcard";
+#endif
static const char* kAsecPath = "/mnt/secure/asec";
-PublicVolume::PublicVolume(dev_t device) :
- VolumeBase(Type::kPublic), mDevice(device), mFusePid(0) {
+PublicVolume::PublicVolume(dev_t device, const std::string& nickname) :
+ VolumeBase(Type::kPublic), mDevice(device), mFusePid(0), mFsLabel(nickname) {
setId(StringPrintf("public:%u,%u", major(device), minor(device)));
mDevPath = StringPrintf("/dev/block/vold/%s", getId().c_str());
}
}
status_t PublicVolume::doCreate() {
+ if (mFsLabel.size() > 0) {
+ notifyEvent(ResponseCode::VolumeFsLabelChanged, mFsLabel);
+ }
return CreateDeviceNode(mDevPath, mDevice);
}
stableName = mFsUuid;
}
+#ifdef MINIVOLD
+ // In recovery, directly mount to /storage/* since we have no fuse daemon
+ mRawPath = StringPrintf("/storage/%s", stableName.c_str());
+ mFuseDefault = StringPrintf("/storage/%s", stableName.c_str());
+ mFuseRead = StringPrintf("/storage/%s", stableName.c_str());
+ mFuseWrite = StringPrintf("/storage/%s", stableName.c_str());
+#else
mRawPath = StringPrintf("/mnt/media_rw/%s", stableName.c_str());
-
mFuseDefault = StringPrintf("/mnt/runtime/default/%s", stableName.c_str());
mFuseRead = StringPrintf("/mnt/runtime/read/%s", stableName.c_str());
mFuseWrite = StringPrintf("/mnt/runtime/write/%s", stableName.c_str());
+#endif
setInternalPath(mRawPath);
if (getMountFlags() & MountFlags::kVisible) {
return -EIO;
}
+#ifdef MINIVOLD
+ // In recovery, don't setup ASEC or FUSE
+ return OK;
+#endif
+
if (getMountFlags() & MountFlags::kPrimary) {
initAsecStage();
}
return OK;
}
-status_t PublicVolume::doUnmount() {
+status_t PublicVolume::doUnmount(bool detach /* = false */) {
if (mFusePid > 0) {
kill(mFusePid, SIGTERM);
TEMP_FAILURE_RETRY(waitpid(mFusePid, nullptr, 0));
ForceUnmount(mFuseDefault);
ForceUnmount(mFuseRead);
ForceUnmount(mFuseWrite);
- ForceUnmount(mRawPath);
+ ForceUnmount(mRawPath, detach);
rmdir(mFuseDefault.c_str());
rmdir(mFuseRead.c_str());
*/
class PublicVolume : public VolumeBase {
public:
- explicit PublicVolume(dev_t device);
+ explicit PublicVolume(dev_t device, const std::string& nickname);
virtual ~PublicVolume();
protected:
status_t doCreate() override;
status_t doDestroy() override;
status_t doMount() override;
- status_t doUnmount() override;
+ status_t doUnmount(bool detach = false) override;
status_t doFormat(const std::string& fsType) override;
status_t readMetadata();
security_context_t sFsckContext = nullptr;
security_context_t sFsckUntrustedContext = nullptr;
+#ifdef MINIVOLD
+static const char* kBlkidPath = "/sbin/blkid";
+#else
static const char* kBlkidPath = "/system/bin/blkid";
+#endif
static const char* kKeyPath = "/data/misc/vold";
static const char* kProcFilesystems = "/proc/filesystems";
}
}
-status_t ForceUnmount(const std::string& path) {
+status_t ForceUnmount(const std::string& path, bool detach /* = false */) {
const char* cpath = path.c_str();
+ if (detach) {
+ if (!umount2(path.c_str(), UMOUNT_NOFOLLOW | MNT_DETACH) || errno == EINVAL || errno == ENOENT) {
+ return OK;
+ }
+ PLOG(WARNING) << "Failed to unmount " << path;
+ return -errno;
+ }
if (!umount2(cpath, UMOUNT_NOFOLLOW) || errno == EINVAL || errno == ENOENT) {
return OK;
}
std::vector<std::string> cmd;
cmd.push_back(kBlkidPath);
+#ifndef MINIVOLD
cmd.push_back("-c");
cmd.push_back("/dev/null");
cmd.push_back("-s");
cmd.push_back("UUID");
cmd.push_back("-s");
cmd.push_back("LABEL");
+#endif
cmd.push_back(path);
std::vector<std::string> output;
status_t PrepareDir(const std::string& path, mode_t mode, uid_t uid, gid_t gid);
/* Really unmounts the path, killing active processes along the way */
-status_t ForceUnmount(const std::string& path);
+status_t ForceUnmount(const std::string& path, bool detach = false);
/* Creates bind mount from source to target */
status_t BindMount(const std::string& source, const std::string& target);
CHECK(!mCreated);
mCreated = true;
- status_t res = doCreate();
notifyEvent(ResponseCode::VolumeCreated,
StringPrintf("%d \"%s\" \"%s\"", mType, mDiskId.c_str(), mPartGuid.c_str()));
+ status_t res = doCreate();
setState(State::kUnmounted);
return res;
}
return res;
}
-status_t VolumeBase::unmount() {
+status_t VolumeBase::unmount(bool detach /* = false */) {
if (mState != State::kMounted) {
LOG(WARNING) << getId() << " unmount requires state mounted";
return -EBUSY;
}
mVolumes.clear();
- status_t res = doUnmount();
+ status_t res = doUnmount(detach);
setState(State::kUnmounted);
return res;
}
status_t create();
status_t destroy();
status_t mount();
- status_t unmount();
+ status_t unmount(bool detach = false);
status_t format(const std::string& fsType);
protected:
virtual status_t doCreate();
virtual status_t doDestroy();
virtual status_t doMount() = 0;
- virtual status_t doUnmount() = 0;
+ virtual status_t doUnmount(bool detach = false) = 0;
virtual status_t doFormat(const std::string& fsType);
status_t setId(const std::string& id);
static int previous_type;
+#ifdef MINIVOLD
+inline int release_wake_lock(const char* id) { return 0; }
+inline int acquire_wake_lock(int lock, const char* id) { return 0; }
+#endif
+
#ifdef CONFIG_HW_DISK_ENCRYPTION
static int scrypt_keymaster(const char *passwd, const unsigned char *salt,
unsigned char *ikey, void *params);
}
#endif
+#ifndef MINIVOLD // no HALs in recovery...
static int keymaster_init(keymaster0_device_t **keymaster0_dev,
keymaster1_device_t **keymaster1_dev)
{
*keymaster1_dev = NULL;
return rc;
}
+#endif
/* Should we use keymaster? */
static int keymaster_check_compatibility()
{
+#ifdef MINIVOLD
+ return -1;
+#else
keymaster0_device_t *keymaster0_dev = 0;
keymaster1_device_t *keymaster1_dev = 0;
int rc = 0;
keymaster0_close(keymaster0_dev);
}
return rc;
+#endif
}
/* Create a new keymaster key and store it in this footer */
static int keymaster_create_key(struct crypt_mnt_ftr *ftr)
{
+#ifdef MINIVOLD // no HALs in recovery...
+ return -1;
+#else
uint8_t* key = 0;
keymaster0_device_t *keymaster0_dev = 0;
keymaster1_device_t *keymaster1_dev = 0;
keymaster1_close(keymaster1_dev);
free(key);
return rc;
+#endif
}
/* This signs the given object using the keymaster key. */
unsigned char **signature,
size_t *signature_size)
{
+#ifdef MINIVOLD // no HALs in recovery...
+ return -1;
+#else
int rc = 0;
keymaster0_device_t *keymaster0_dev = 0;
keymaster1_device_t *keymaster1_dev = 0;
keymaster0_close(keymaster0_dev);
return rc;
+#endif
}
/* Store password when userdata is successfully decrypted and mounted.
namespace vold {
namespace ext4 {
+#ifdef MINIVOLD
+static const char* kResizefsPath = "/sbin/resize2fs";
+static const char* kMkfsPath = "/sbin/mke2fs";
+static const char* kFsckPath = "/sbin/e2fsck";
+#else
static const char* kResizefsPath = "/system/bin/resize2fs";
static const char* kMkfsPath = "/system/bin/make_ext4fs";
static const char* kFsckPath = "/system/bin/e2fsck";
+#endif
bool IsSupported() {
return access(kMkfsPath, X_OK) == 0
using android::base::StringPrintf;
-int main(int argc, char** argv) {
+extern "C" int vold_main(int argc, char** argv) {
setenv("ANDROID_LOG_TAGS", "*:v", 1);
android::base::InitLogging(argv, android::base::LogdLogger(android::base::SYSTEM));
static int do_monitor(int sock, int stop_after_cmd);
static int do_cmd(int sock, int argc, char **argv);
-int main(int argc, char **argv) {
+int vdc_main(int argc, char **argv) {
int sock;
int wait_for_socket;
char *progname;
fprintf(stderr,
"Usage: %s [--wait] <monitor>|<cmd> [arg1] [arg2...]\n", progname);
}
+
+#ifndef MINIVOLD
+int main(int argc, char **argv) {
+ return vdc_main(argc, argv);
+}
+#endif
--- /dev/null
+/*
+ * Copyright (C) 2015 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "vold.h"
+
+int main(int argc, char **argv) {
+ return vold_main();
+}
--- /dev/null
+/*
+ * Copyright (C) 2015 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _VOLD_H
+#define _VOLD_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int vold_main();
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+