Port the current code to new IncFS
Bug: 146080380
Test: manual, "cmd incremental install-start"
Change-Id: I6761c3f0e58b6d4de1ae3c4b31c23204fba9f740
diff --git a/services/incremental/Android.bp b/services/incremental/Android.bp
index ddf4dd5..323e7f1 100644
--- a/services/incremental/Android.bp
+++ b/services/incremental/Android.bp
@@ -47,6 +47,8 @@
shared_libs: [
"libandroidfw",
"libbinder",
+ "libcrypto",
+ "libcutils",
"libincfs",
"liblog",
"libz",
diff --git a/services/incremental/BinderIncrementalService.cpp b/services/incremental/BinderIncrementalService.cpp
index bb26c1f..f1b637f 100644
--- a/services/incremental/BinderIncrementalService.cpp
+++ b/services/incremental/BinderIncrementalService.cpp
@@ -46,10 +46,10 @@
return incfs::enabled();
}
-static bool incFsVersionValid(const sp<IVold>& vold) {
- int version = -1;
- auto status = vold->incFsVersion(&version);
- if (!status.isOk() || version <= 0) {
+static bool incFsValid(const sp<IVold>& vold) {
+ bool enabled = false;
+ auto status = vold->incFsEnabled(&enabled);
+ if (!status.isOk() || !enabled) {
return false;
}
return true;
@@ -74,7 +74,7 @@
return nullptr;
}
sp<IVold> vold = interface_cast<IVold>(voldBinder);
- if (!incFsVersionValid(vold)) {
+ if (!incFsValid(vold)) {
return nullptr;
}
@@ -86,6 +86,7 @@
sp<ProcessState> ps(ProcessState::self());
ps->startThreadPool();
ps->giveThreadPoolName();
+ // sm->addService increments the reference count, and now we're OK with returning the pointer.
return self.get();
}
@@ -107,9 +108,9 @@
return ok();
}
-binder::Status BinderIncrementalService::createStorage(
- const std::string& path, const DataLoaderParamsParcel& params,
- int32_t createMode, int32_t* _aidl_return) {
+binder::Status BinderIncrementalService::createStorage(const std::string& path,
+ const DataLoaderParamsParcel& params,
+ int32_t createMode, int32_t* _aidl_return) {
*_aidl_return =
mImpl.createStorage(path, const_cast<DataLoaderParamsParcel&&>(params),
android::incremental::IncrementalService::CreateOptions(
@@ -129,10 +130,10 @@
}
binder::Status BinderIncrementalService::makeBindMount(int32_t storageId,
- const std::string& pathUnderStorage,
+ const std::string& sourcePath,
const std::string& targetFullPath,
int32_t bindType, int32_t* _aidl_return) {
- *_aidl_return = mImpl.bind(storageId, pathUnderStorage, targetFullPath,
+ *_aidl_return = mImpl.bind(storageId, sourcePath, targetFullPath,
android::incremental::IncrementalService::BindKind(bindType));
return ok();
}
@@ -149,75 +150,127 @@
return ok();
}
-binder::Status BinderIncrementalService::makeDirectory(int32_t storageId,
- const std::string& pathUnderStorage,
+binder::Status BinderIncrementalService::makeDirectory(int32_t storageId, const std::string& path,
int32_t* _aidl_return) {
- auto inode = mImpl.makeDir(storageId, pathUnderStorage);
- *_aidl_return = inode < 0 ? inode : 0;
+ *_aidl_return = mImpl.makeDir(storageId, path);
return ok();
}
-binder::Status BinderIncrementalService::makeDirectories(int32_t storageId,
- const std::string& pathUnderStorage,
- int32_t* _aidl_return) {
- auto inode = mImpl.makeDirs(storageId, pathUnderStorage);
- *_aidl_return = inode < 0 ? inode : 0;
- return ok();
+static std::tuple<int, incfs::FileId, incfs::NewFileParams> toMakeFileParams(
+ const android::os::incremental::IncrementalNewFileParams& params) {
+ incfs::FileId id;
+ if (params.fileId.empty()) {
+ if (params.metadata.empty()) {
+ return {EINVAL, {}, {}};
+ }
+ id = IncrementalService::idFromMetadata(params.metadata);
+ } else if (params.fileId.size() != sizeof(id)) {
+ return {EINVAL, {}, {}};
+ } else {
+ memcpy(&id, params.fileId.data(), sizeof(id));
+ }
+ incfs::NewFileParams nfp;
+ nfp.size = params.size;
+ nfp.metadata = {(const char*)params.metadata.data(), (IncFsSize)params.metadata.size()};
+ if (!params.signature) {
+ nfp.verification = {};
+ } else {
+ nfp.verification.hashAlgorithm = IncFsHashAlgortithm(params.signature->hashAlgorithm);
+ nfp.verification.rootHash = {(const char*)params.signature->rootHash.data(),
+ (IncFsSize)params.signature->rootHash.size()};
+ nfp.verification.additionalData = {(const char*)params.signature->additionalData.data(),
+ (IncFsSize)params.signature->additionalData.size()};
+ nfp.verification.signature = {(const char*)params.signature->signature.data(),
+ (IncFsSize)params.signature->signature.size()};
+ }
+ return {0, id, nfp};
}
-binder::Status BinderIncrementalService::makeFile(int32_t storageId,
- const std::string& pathUnderStorage, int64_t size,
- const std::vector<uint8_t>& metadata,
- int32_t* _aidl_return) {
- auto inode = mImpl.makeFile(storageId, pathUnderStorage, size,
- {(const char*)metadata.data(), metadata.size()}, {});
- *_aidl_return = inode < 0 ? inode : 0;
+binder::Status BinderIncrementalService::makeFile(
+ int32_t storageId, const std::string& path,
+ const ::android::os::incremental::IncrementalNewFileParams& params, int32_t* _aidl_return) {
+ auto [err, fileId, nfp] = toMakeFileParams(params);
+ if (err) {
+ *_aidl_return = err;
+ return ok();
+ }
+
+ *_aidl_return = mImpl.makeFile(storageId, path, 0555, fileId, nfp);
return ok();
}
-binder::Status BinderIncrementalService::makeFileFromRange(
- int32_t storageId, const std::string& pathUnderStorage,
- const std::string& sourcePathUnderStorage, int64_t start, int64_t end,
- int32_t* _aidl_return) {
- // TODO(b/136132412): implement this
- *_aidl_return = -1;
- return ok();
-}
-binder::Status BinderIncrementalService::makeLink(int32_t sourceStorageId,
- const std::string& relativeSourcePath,
- int32_t destStorageId,
- const std::string& relativeDestPath,
- int32_t* _aidl_return) {
- auto sourceInode = mImpl.nodeFor(sourceStorageId, relativeSourcePath);
- auto [targetParentInode, name] = mImpl.parentAndNameFor(destStorageId, relativeDestPath);
- *_aidl_return = mImpl.link(sourceStorageId, sourceInode, targetParentInode, name);
- return ok();
-}
-binder::Status BinderIncrementalService::unlink(int32_t storageId,
- const std::string& pathUnderStorage,
- int32_t* _aidl_return) {
- auto [parentNode, name] = mImpl.parentAndNameFor(storageId, pathUnderStorage);
- *_aidl_return = mImpl.unlink(storageId, parentNode, name);
- return ok();
-}
-binder::Status BinderIncrementalService::isFileRangeLoaded(int32_t storageId,
- const std::string& relativePath,
+binder::Status BinderIncrementalService::makeFileFromRange(int32_t storageId,
+ const std::string& targetPath,
+ const std::string& sourcePath,
int64_t start, int64_t end,
- bool* _aidl_return) {
+ int32_t* _aidl_return) {
+ // TODO(b/136132412): implement this
+ *_aidl_return = ENOSYS; // not implemented
+ return ok();
+}
+
+binder::Status BinderIncrementalService::makeLink(int32_t sourceStorageId,
+ const std::string& sourcePath,
+ int32_t destStorageId,
+ const std::string& destPath,
+ int32_t* _aidl_return) {
+ *_aidl_return = mImpl.link(sourceStorageId, sourcePath, destStorageId, destPath);
+ return ok();
+}
+
+binder::Status BinderIncrementalService::unlink(int32_t storageId, const std::string& path,
+ int32_t* _aidl_return) {
+ *_aidl_return = mImpl.unlink(storageId, path);
+ return ok();
+}
+
+binder::Status BinderIncrementalService::isFileRangeLoaded(int32_t storageId,
+ const std::string& path, int64_t start,
+ int64_t end, bool* _aidl_return) {
+ // TODO: implement
*_aidl_return = false;
return ok();
}
-binder::Status BinderIncrementalService::getFileMetadata(int32_t storageId,
- const std::string& relativePath,
+
+binder::Status BinderIncrementalService::getMetadataByPath(int32_t storageId,
+ const std::string& path,
+ std::vector<uint8_t>* _aidl_return) {
+ auto fid = mImpl.nodeFor(storageId, path);
+ if (fid != kIncFsInvalidFileId) {
+ auto metadata = mImpl.getMetadata(storageId, fid);
+ _aidl_return->assign(metadata.begin(), metadata.end());
+ }
+ return ok();
+}
+
+static FileId toFileId(const std::vector<uint8_t>& id) {
+ FileId fid;
+ memcpy(&fid, id.data(), id.size());
+ return fid;
+}
+
+binder::Status BinderIncrementalService::getMetadataById(int32_t storageId,
+ const std::vector<uint8_t>& id,
std::vector<uint8_t>* _aidl_return) {
- auto inode = mImpl.nodeFor(storageId, relativePath);
- auto metadata = mImpl.getMetadata(storageId, inode);
+ if (id.size() != sizeof(incfs::FileId)) {
+ return ok();
+ }
+ auto fid = toFileId(id);
+ auto metadata = mImpl.getMetadata(storageId, fid);
_aidl_return->assign(metadata.begin(), metadata.end());
return ok();
}
+
+binder::Status BinderIncrementalService::makeDirectories(int32_t storageId, const std::string& path,
+ int32_t* _aidl_return) {
+ *_aidl_return = mImpl.makeDirs(storageId, path);
+ return ok();
+}
+
binder::Status BinderIncrementalService::startLoading(int32_t storageId, bool* _aidl_return) {
*_aidl_return = mImpl.startLoading(storageId);
return ok();
}
+
} // namespace android::os::incremental
jlong Incremental_IncrementalService_Start() {
diff --git a/services/incremental/BinderIncrementalService.h b/services/incremental/BinderIncrementalService.h
index 37c9661d..a94a75a 100644
--- a/services/incremental/BinderIncrementalService.h
+++ b/services/incremental/BinderIncrementalService.h
@@ -37,38 +37,39 @@
void onSystemReady();
void onInvalidStorage(int mountId);
- binder::Status openStorage(const std::string &path, int32_t *_aidl_return) final;
- binder::Status createStorage(
- const std::string &path,
- const ::android::content::pm::DataLoaderParamsParcel ¶ms,
- int32_t createMode, int32_t *_aidl_return) final;
- binder::Status createLinkedStorage(const std::string &path, int32_t otherStorageId,
- int32_t createMode, int32_t *_aidl_return) final;
- binder::Status makeBindMount(int32_t storageId, const std::string &pathUnderStorage,
- const std::string &targetFullPath, int32_t bindType,
- int32_t *_aidl_return) final;
- binder::Status deleteBindMount(int32_t storageId, const std::string &targetFullPath,
- int32_t *_aidl_return) final;
+ binder::Status openStorage(const std::string& path, int32_t* _aidl_return) final;
+ binder::Status createStorage(const std::string& path,
+ const ::android::content::pm::DataLoaderParamsParcel& params,
+ int32_t createMode, int32_t* _aidl_return) final;
+ binder::Status createLinkedStorage(const std::string& path, int32_t otherStorageId,
+ int32_t createMode, int32_t* _aidl_return) final;
+ binder::Status makeBindMount(int32_t storageId, const std::string& sourcePath,
+ const std::string& targetFullPath, int32_t bindType,
+ int32_t* _aidl_return) final;
+ binder::Status deleteBindMount(int32_t storageId, const std::string& targetFullPath,
+ int32_t* _aidl_return) final;
+ binder::Status makeDirectory(int32_t storageId, const std::string& path,
+ int32_t* _aidl_return) final;
+ binder::Status makeDirectories(int32_t storageId, const std::string& path,
+ int32_t* _aidl_return) final;
+ binder::Status makeFile(int32_t storageId, const std::string& path,
+ const ::android::os::incremental::IncrementalNewFileParams& params,
+ int32_t* _aidl_return) final;
+ binder::Status makeFileFromRange(int32_t storageId, const std::string& targetPath,
+ const std::string& sourcePath, int64_t start, int64_t end,
+ int32_t* _aidl_return) final;
+ binder::Status makeLink(int32_t sourceStorageId, const std::string& sourcePath,
+ int32_t destStorageId, const std::string& destPath,
+ int32_t* _aidl_return) final;
+ binder::Status unlink(int32_t storageId, const std::string& path, int32_t* _aidl_return) final;
+ binder::Status isFileRangeLoaded(int32_t storageId, const std::string& path, int64_t start,
+ int64_t end, bool* _aidl_return) final;
+ binder::Status getMetadataByPath(int32_t storageId, const std::string& path,
+ std::vector<uint8_t>* _aidl_return) final;
+ binder::Status getMetadataById(int32_t storageId, const std::vector<uint8_t>& id,
+ std::vector<uint8_t>* _aidl_return) final;
+ binder::Status startLoading(int32_t storageId, bool* _aidl_return) final;
binder::Status deleteStorage(int32_t storageId) final;
- binder::Status makeDirectory(int32_t storageId, const std::string &pathUnderStorage,
- int32_t *_aidl_return) final;
- binder::Status makeDirectories(int32_t storageId, const std::string &pathUnderStorage,
- int32_t *_aidl_return) final;
- binder::Status makeFile(int32_t storageId, const std::string &pathUnderStorage, int64_t size,
- const std::vector<uint8_t> &metadata, int32_t *_aidl_return) final;
- binder::Status makeFileFromRange(int32_t storageId, const std::string &pathUnderStorage,
- const std::string &sourcePathUnderStorage, int64_t start,
- int64_t end, int32_t *_aidl_return);
- binder::Status makeLink(int32_t sourceStorageId, const std::string &relativeSourcePath,
- int32_t destStorageId, const std::string &relativeDestPath,
- int32_t *_aidl_return) final;
- binder::Status unlink(int32_t storageId, const std::string &pathUnderStorage,
- int32_t *_aidl_return) final;
- binder::Status isFileRangeLoaded(int32_t storageId, const std::string &relativePath,
- int64_t start, int64_t end, bool *_aidl_return) final;
- binder::Status getFileMetadata(int32_t storageId, const std::string &relativePath,
- std::vector<uint8_t> *_aidl_return) final;
- binder::Status startLoading(int32_t storageId, bool *_aidl_return) final;
private:
android::incremental::IncrementalService mImpl;
diff --git a/services/incremental/IncrementalService.cpp b/services/incremental/IncrementalService.cpp
index afce260..414c66c 100644
--- a/services/incremental/IncrementalService.cpp
+++ b/services/incremental/IncrementalService.cpp
@@ -30,6 +30,8 @@
#include <binder/BinderService.h>
#include <binder/ParcelFileDescriptor.h>
#include <binder/Status.h>
+
+#include <openssl/sha.h>
#include <sys/stat.h>
#include <uuid/uuid.h>
#include <zlib.h>
@@ -55,7 +57,6 @@
struct Constants {
static constexpr auto backing = "backing_store"sv;
static constexpr auto mount = "mount"sv;
- static constexpr auto image = "incfs.img"sv;
static constexpr auto storagePrefix = "st"sv;
static constexpr auto mountpointMdPrefix = ".mountpoint."sv;
static constexpr auto infoMdName = ".info"sv;
@@ -70,7 +71,7 @@
bool mkdirOrLog(std::string_view name, int mode = 0770, bool allowExisting = true) {
auto cstr = path::c_str(name);
if (::mkdir(cstr, mode)) {
- if (errno != EEXIST) {
+ if (!allowExisting || errno != EEXIST) {
PLOG(level) << "Can't create directory '" << name << '\'';
return false;
}
@@ -80,6 +81,11 @@
return false;
}
}
+ if (::chmod(cstr, mode)) {
+ PLOG(level) << "Changing permission failed for '" << name << '\'';
+ return false;
+ }
+
return true;
}
@@ -106,7 +112,7 @@
for (int counter = 0; counter < 1000;
mountKey.resize(prefixSize), base::StringAppendF(&mountKey, "%d", counter++)) {
auto mountRoot = path::join(incrementalDir, mountKey);
- if (mkdirOrLog(mountRoot, 0770, false)) {
+ if (mkdirOrLog(mountRoot, 0777, false)) {
return {mountKey, mountRoot};
}
}
@@ -116,11 +122,7 @@
template <class ProtoMessage, class Control>
static ProtoMessage parseFromIncfs(const IncFsWrapper* incfs, Control&& control,
std::string_view path) {
- struct stat st;
- if (::stat(path::c_str(path), &st)) {
- return {};
- }
- auto md = incfs->getMetadata(control, st.st_ino);
+ auto md = incfs->getMetadata(control, path);
ProtoMessage message;
return message.ParseFromArray(md.data(), md.size()) ? message : ProtoMessage{};
}
@@ -161,35 +163,66 @@
}
auto IncrementalService::IncFsMount::makeStorage(StorageId id) -> StorageMap::iterator {
- metadata::Storage st;
- st.set_id(id);
- auto metadata = st.SerializeAsString();
-
std::string name;
for (int no = nextStorageDirNo.fetch_add(1, std::memory_order_relaxed), i = 0;
i < 1024 && no >= 0; no = nextStorageDirNo.fetch_add(1, std::memory_order_relaxed), ++i) {
name.clear();
- base::StringAppendF(&name, "%.*s%d", int(constants().storagePrefix.size()),
- constants().storagePrefix.data(), no);
- if (auto node =
- incrementalService.mIncFs->makeDir(control, name, INCFS_ROOT_INODE, metadata);
- node >= 0) {
+ base::StringAppendF(&name, "%.*s_%d_%d", int(constants().storagePrefix.size()),
+ constants().storagePrefix.data(), id, no);
+ auto fullName = path::join(root, constants().mount, name);
+ if (auto err = incrementalService.mIncFs->makeDir(control, fullName); !err) {
std::lock_guard l(lock);
- return storages.insert_or_assign(id, Storage{std::move(name), node}).first;
+ return storages.insert_or_assign(id, Storage{std::move(fullName)}).first;
+ } else if (err != EEXIST) {
+ LOG(ERROR) << __func__ << "(): failed to create dir |" << fullName << "| " << err;
+ break;
}
}
nextStorageDirNo = 0;
return storages.end();
}
+static std::unique_ptr<DIR, decltype(&::closedir)> openDir(const char* path) {
+ return {::opendir(path), ::closedir};
+}
+
+static int rmDirContent(const char* path) {
+ auto dir = openDir(path);
+ if (!dir) {
+ return -EINVAL;
+ }
+ while (auto entry = ::readdir(dir.get())) {
+ if (entry->d_name == "."sv || entry->d_name == ".."sv) {
+ continue;
+ }
+ auto fullPath = android::base::StringPrintf("%s/%s", path, entry->d_name);
+ if (entry->d_type == DT_DIR) {
+ if (const auto err = rmDirContent(fullPath.c_str()); err != 0) {
+ PLOG(WARNING) << "Failed to delete " << fullPath << " content";
+ return err;
+ }
+ if (const auto err = ::rmdir(fullPath.c_str()); err != 0) {
+ PLOG(WARNING) << "Failed to rmdir " << fullPath;
+ return err;
+ }
+ } else {
+ if (const auto err = ::unlink(fullPath.c_str()); err != 0) {
+ PLOG(WARNING) << "Failed to delete " << fullPath;
+ return err;
+ }
+ }
+ }
+ return 0;
+}
+
void IncrementalService::IncFsMount::cleanupFilesystem(std::string_view root) {
- ::unlink(path::join(root, constants().backing, constants().image).c_str());
+ rmDirContent(path::join(root, constants().backing).c_str());
::rmdir(path::join(root, constants().backing).c_str());
::rmdir(path::join(root, constants().mount).c_str());
::rmdir(path::c_str(root));
}
-IncrementalService::IncrementalService(const ServiceManagerWrapper& sm, std::string_view rootDir)
+IncrementalService::IncrementalService(ServiceManagerWrapper&& sm, std::string_view rootDir)
: mVold(sm.getVoldService()),
mIncrementalManager(sm.getIncrementalManager()),
mIncFs(sm.getIncFs()),
@@ -205,6 +238,23 @@
// mountExistingImages();
}
+FileId IncrementalService::idFromMetadata(std::span<const uint8_t> metadata) {
+ incfs::FileId id = {};
+ if (size_t(metadata.size()) <= sizeof(id)) {
+ memcpy(&id, metadata.data(), metadata.size());
+ } else {
+ uint8_t buffer[SHA_DIGEST_LENGTH];
+ static_assert(sizeof(buffer) >= sizeof(id));
+
+ SHA_CTX ctx;
+ SHA1_Init(&ctx);
+ SHA1_Update(&ctx, metadata.data(), metadata.size());
+ SHA1_Final(buffer, &ctx);
+ memcpy(&id, buffer, sizeof(id));
+ }
+ return id;
+}
+
IncrementalService::~IncrementalService() = default;
std::optional<std::future<void>> IncrementalService::onSystemReady() {
@@ -300,26 +350,36 @@
std::unique_ptr<std::string, decltype(firstCleanup)>(&mountRoot, firstCleanup);
auto mountTarget = path::join(mountRoot, constants().mount);
- if (!mkdirOrLog(path::join(mountRoot, constants().backing)) || !mkdirOrLog(mountTarget)) {
+ const auto backing = path::join(mountRoot, constants().backing);
+ if (!mkdirOrLog(backing, 0777) || !mkdirOrLog(mountTarget)) {
return kInvalidStorageId;
}
- const auto image = path::join(mountRoot, constants().backing, constants().image);
IncFsMount::Control control;
{
std::lock_guard l(mMountOperationLock);
IncrementalFileSystemControlParcel controlParcel;
- auto status = mVold->mountIncFs(image, mountTarget, incfs::truncate, &controlParcel);
+
+ if (auto err = rmDirContent(backing.c_str())) {
+ LOG(ERROR) << "Coudn't clean the backing directory " << backing << ": " << err;
+ return kInvalidStorageId;
+ }
+ if (!mkdirOrLog(path::join(backing, ".index"), 0777)) {
+ return kInvalidStorageId;
+ }
+ auto status = mVold->mountIncFs(backing, mountTarget, 0, &controlParcel);
if (!status.isOk()) {
LOG(ERROR) << "Vold::mountIncFs() failed: " << status.toString8();
return kInvalidStorageId;
}
- if (!controlParcel.cmd || !controlParcel.log) {
+ if (controlParcel.cmd.get() < 0 || controlParcel.pendingReads.get() < 0 ||
+ controlParcel.log.get() < 0) {
LOG(ERROR) << "Vold::mountIncFs() returned invalid control parcel.";
return kInvalidStorageId;
}
- control.cmdFd = controlParcel.cmd->release();
- control.logFd = controlParcel.log->release();
+ control.cmd = controlParcel.cmd.release().release();
+ control.pendingReads = controlParcel.pendingReads.release().release();
+ control.logs = controlParcel.log.release().release();
}
std::unique_lock l(mLock);
@@ -344,7 +404,7 @@
const auto storageIt = ifs->makeStorage(ifs->mountId);
if (storageIt == ifs->storages.end()) {
- LOG(ERROR) << "Can't create default storage directory";
+ LOG(ERROR) << "Can't create a default storage directory";
return kInvalidStorageId;
}
@@ -359,9 +419,12 @@
m.mutable_loader()->release_arguments();
m.mutable_loader()->release_class_name();
m.mutable_loader()->release_package_name();
- if (auto err = mIncFs->makeFile(ifs->control, constants().infoMdName, INCFS_ROOT_INODE, 0,
- metadata);
- err < 0) {
+ if (auto err =
+ mIncFs->makeFile(ifs->control,
+ path::join(ifs->root, constants().mount,
+ constants().infoMdName),
+ 0777, idFromMetadata(metadata),
+ {.metadata = {metadata.data(), (IncFsSize)metadata.size()}})) {
LOG(ERROR) << "Saving mount metadata failed: " << -err;
return kInvalidStorageId;
}
@@ -369,8 +432,8 @@
const auto bk =
(options & CreateOptions::PermanentBind) ? BindKind::Permanent : BindKind::Temporary;
- if (auto err = addBindMount(*ifs, storageIt->first, std::string(storageIt->second.name),
- std::move(mountNorm), bk, l);
+ if (auto err = addBindMount(*ifs, storageIt->first, storageIt->second.name,
+ std::string(storageIt->second.name), std::move(mountNorm), bk, l);
err < 0) {
LOG(ERROR) << "adding bind mount failed: " << -err;
return kInvalidStorageId;
@@ -419,8 +482,9 @@
const auto bk =
(options & CreateOptions::PermanentBind) ? BindKind::Permanent : BindKind::Temporary;
- if (auto err = addBindMount(*ifs, storageIt->first, std::string(storageIt->second.name),
- path::normalize(mountPoint), bk, l);
+ if (auto err = addBindMount(*ifs, storageIt->first, storageIt->second.name,
+ std::string(storageIt->second.name), path::normalize(mountPoint),
+ bk, l);
err < 0) {
LOG(ERROR) << "bindMount failed with error: " << err;
return kInvalidStorageId;
@@ -492,40 +556,36 @@
return findStorageId(path::normalize(pathInMount));
}
-Inode IncrementalService::nodeFor(StorageId storage, std::string_view subpath) const {
+FileId IncrementalService::nodeFor(StorageId storage, std::string_view subpath) const {
const auto ifs = getIfs(storage);
if (!ifs) {
- return -1;
+ return kIncFsInvalidFileId;
}
std::unique_lock l(ifs->lock);
auto storageIt = ifs->storages.find(storage);
if (storageIt == ifs->storages.end()) {
- return -1;
+ return kIncFsInvalidFileId;
}
if (subpath.empty() || subpath == "."sv) {
- return storageIt->second.node;
+ return kIncFsInvalidFileId;
}
auto path = path::join(ifs->root, constants().mount, storageIt->second.name, subpath);
l.unlock();
- struct stat st;
- if (::stat(path.c_str(), &st)) {
- return -1;
- }
- return st.st_ino;
+ return mIncFs->getFileId(ifs->control, path);
}
-std::pair<Inode, std::string_view> IncrementalService::parentAndNameFor(
+std::pair<FileId, std::string_view> IncrementalService::parentAndNameFor(
StorageId storage, std::string_view subpath) const {
auto name = path::basename(subpath);
if (name.empty()) {
- return {-1, {}};
+ return {kIncFsInvalidFileId, {}};
}
auto dir = path::dirname(subpath);
if (dir.empty() || dir == "/"sv) {
- return {-1, {}};
+ return {kIncFsInvalidFileId, {}};
}
- auto inode = nodeFor(storage, dir);
- return {inode, name};
+ auto id = nodeFor(storage, dir);
+ return {id, name};
}
IncrementalService::IfsMountPtr IncrementalService::getIfs(StorageId storage) const {
@@ -542,8 +602,8 @@
return it->second;
}
-int IncrementalService::bind(StorageId storage, std::string_view sourceSubdir,
- std::string_view target, BindKind kind) {
+int IncrementalService::bind(StorageId storage, std::string_view source, std::string_view target,
+ BindKind kind) {
if (!isValidMountTarget(target)) {
return -EINVAL;
}
@@ -552,15 +612,20 @@
if (!ifs) {
return -EINVAL;
}
+ auto normSource = path::normalize(source);
+
std::unique_lock l(ifs->lock);
const auto storageInfo = ifs->storages.find(storage);
if (storageInfo == ifs->storages.end()) {
return -EINVAL;
}
- auto source = path::join(storageInfo->second.name, sourceSubdir);
+ if (!path::startsWith(normSource, storageInfo->second.name)) {
+ return -EINVAL;
+ }
l.unlock();
std::unique_lock l2(mLock, std::defer_lock);
- return addBindMount(*ifs, storage, std::move(source), path::normalize(target), kind, l2);
+ return addBindMount(*ifs, storage, storageInfo->second.name, std::move(normSource),
+ path::normalize(target), kind, l2);
}
int IncrementalService::unbind(StorageId storage, std::string_view target) {
@@ -599,90 +664,72 @@
ifs->bindPoints.erase(bindIt);
l2.unlock();
if (!savedFile.empty()) {
- mIncFs->unlink(ifs->control, INCFS_ROOT_INODE, savedFile);
+ mIncFs->unlink(ifs->control, path::join(ifs->root, constants().mount, savedFile));
}
}
return 0;
}
-Inode IncrementalService::makeFile(StorageId storageId, std::string_view pathUnderStorage,
- long size, std::string_view metadata,
- std::string_view signature) {
- (void)signature;
- auto [parentInode, name] = parentAndNameFor(storageId, pathUnderStorage);
- if (parentInode < 0) {
- return -EINVAL;
- }
- if (auto ifs = getIfs(storageId)) {
- auto inode = mIncFs->makeFile(ifs->control, name, parentInode, size, metadata);
- if (inode < 0) {
- return inode;
+int IncrementalService::makeFile(StorageId storage, std::string_view path, int mode, FileId id,
+ incfs::NewFileParams params) {
+ if (auto ifs = getIfs(storage)) {
+ auto err = mIncFs->makeFile(ifs->control, path, mode, id, params);
+ if (err) {
+ return err;
}
- auto metadataBytes = std::vector<uint8_t>();
- if (metadata.data() != nullptr && metadata.size() > 0) {
- metadataBytes.insert(metadataBytes.end(), &metadata.data()[0],
- &metadata.data()[metadata.size()]);
+ std::vector<uint8_t> metadataBytes;
+ if (params.metadata.data && params.metadata.size > 0) {
+ metadataBytes.assign(params.metadata.data, params.metadata.data + params.metadata.size);
}
- mIncrementalManager->newFileForDataLoader(ifs->mountId, inode, metadataBytes);
- return inode;
+ mIncrementalManager->newFileForDataLoader(ifs->mountId, id, metadataBytes);
+ return 0;
}
return -EINVAL;
}
-Inode IncrementalService::makeDir(StorageId storageId, std::string_view pathUnderStorage,
- std::string_view metadata) {
- auto [parentInode, name] = parentAndNameFor(storageId, pathUnderStorage);
- if (parentInode < 0) {
- return -EINVAL;
- }
+int IncrementalService::makeDir(StorageId storageId, std::string_view path, int mode) {
if (auto ifs = getIfs(storageId)) {
- return mIncFs->makeDir(ifs->control, name, parentInode, metadata);
+ return mIncFs->makeDir(ifs->control, path, mode);
}
return -EINVAL;
}
-Inode IncrementalService::makeDirs(StorageId storageId, std::string_view pathUnderStorage,
- std::string_view metadata) {
+int IncrementalService::makeDirs(StorageId storageId, std::string_view path, int mode) {
const auto ifs = getIfs(storageId);
if (!ifs) {
return -EINVAL;
}
- std::string_view parentDir(pathUnderStorage);
- auto p = parentAndNameFor(storageId, pathUnderStorage);
- std::stack<std::string> pathsToCreate;
- while (p.first < 0) {
- parentDir = path::dirname(parentDir);
- pathsToCreate.emplace(parentDir);
- p = parentAndNameFor(storageId, parentDir);
+
+ auto err = mIncFs->makeDir(ifs->control, path, mode);
+ if (err == -EEXIST) {
+ return 0;
+ } else if (err != -ENOENT) {
+ return err;
}
- Inode inode;
- while (!pathsToCreate.empty()) {
- p = parentAndNameFor(storageId, pathsToCreate.top());
- pathsToCreate.pop();
- inode = mIncFs->makeDir(ifs->control, p.second, p.first, metadata);
- if (inode < 0) {
- return inode;
- }
+ if (auto err = makeDirs(storageId, path::dirname(path), mode)) {
+ return err;
}
- return mIncFs->makeDir(ifs->control, path::basename(pathUnderStorage), inode, metadata);
+ return mIncFs->makeDir(ifs->control, path, mode);
}
-int IncrementalService::link(StorageId storage, Inode item, Inode newParent,
- std::string_view newName) {
- if (auto ifs = getIfs(storage)) {
- return mIncFs->link(ifs->control, item, newParent, newName);
+int IncrementalService::link(StorageId sourceStorageId, std::string_view oldPath,
+ StorageId destStorageId, std::string_view newPath) {
+ if (auto ifsSrc = getIfs(sourceStorageId), ifsDest = getIfs(destStorageId);
+ ifsSrc && ifsSrc == ifsDest) {
+ return mIncFs->link(ifsSrc->control, oldPath, newPath);
}
return -EINVAL;
}
-int IncrementalService::unlink(StorageId storage, Inode parent, std::string_view name) {
+int IncrementalService::unlink(StorageId storage, std::string_view path) {
if (auto ifs = getIfs(storage)) {
- return mIncFs->unlink(ifs->control, parent, name);
+ return mIncFs->unlink(ifs->control, path);
}
return -EINVAL;
}
-int IncrementalService::addBindMount(IncFsMount& ifs, StorageId storage, std::string&& sourceSubdir,
+int IncrementalService::addBindMount(IncFsMount& ifs, StorageId storage,
+ std::string_view storageRoot, std::string&& source,
std::string&& target, BindKind kind,
std::unique_lock<std::mutex>& mainLock) {
if (!isValidMountTarget(target)) {
@@ -694,30 +741,30 @@
metadata::BindPoint bp;
bp.set_storage_id(storage);
bp.set_allocated_dest_path(&target);
- bp.set_allocated_source_subdir(&sourceSubdir);
+ bp.set_source_subdir(std::string(path::relativize(storageRoot, source)));
const auto metadata = bp.SerializeAsString();
- bp.release_source_subdir();
bp.release_dest_path();
mdFileName = makeBindMdName();
- auto node = mIncFs->makeFile(ifs.control, mdFileName, INCFS_ROOT_INODE, 0, metadata);
- if (node < 0) {
+ auto node =
+ mIncFs->makeFile(ifs.control, path::join(ifs.root, constants().mount, mdFileName),
+ 0444, idFromMetadata(metadata),
+ {.metadata = {metadata.data(), (IncFsSize)metadata.size()}});
+ if (node) {
return int(node);
}
}
- return addBindMountWithMd(ifs, storage, std::move(mdFileName), std::move(sourceSubdir),
+ return addBindMountWithMd(ifs, storage, std::move(mdFileName), std::move(source),
std::move(target), kind, mainLock);
}
int IncrementalService::addBindMountWithMd(IncrementalService::IncFsMount& ifs, StorageId storage,
- std::string&& metadataName, std::string&& sourceSubdir,
+ std::string&& metadataName, std::string&& source,
std::string&& target, BindKind kind,
std::unique_lock<std::mutex>& mainLock) {
- LOG(INFO) << "Adding bind mount: " << sourceSubdir << " -> " << target;
{
- auto path = path::join(ifs.root, constants().mount, sourceSubdir);
std::lock_guard l(mMountOperationLock);
- const auto status = mVold->bindMount(path, target);
+ const auto status = mVold->bindMount(source, target);
if (!status.isOk()) {
LOG(ERROR) << "Calling Vold::bindMount() failed: " << status.toString8();
return status.exceptionCode() == binder::Status::EX_SERVICE_SPECIFIC
@@ -736,12 +783,12 @@
const auto [it, _] =
ifs.bindPoints.insert_or_assign(target,
IncFsMount::Bind{storage, std::move(metadataName),
- std::move(sourceSubdir), kind});
+ std::move(source), kind});
mBindsByPath[std::move(target)] = it;
return 0;
}
-RawMetadata IncrementalService::getMetadata(StorageId storage, Inode node) const {
+RawMetadata IncrementalService::getMetadata(StorageId storage, FileId node) const {
const auto ifs = getIfs(storage);
if (!ifs) {
return {};
@@ -831,21 +878,18 @@
LOG(INFO) << "Trying to mount: " << key;
auto mountTarget = path::join(root, constants().mount);
- const auto image = path::join(root, constants().backing, constants().image);
+ const auto backing = path::join(root, constants().backing);
IncFsMount::Control control;
IncrementalFileSystemControlParcel controlParcel;
- auto status = mVold->mountIncFs(image, mountTarget, 0, &controlParcel);
+ auto status = mVold->mountIncFs(backing, mountTarget, 0, &controlParcel);
if (!status.isOk()) {
LOG(ERROR) << "Vold::mountIncFs() failed: " << status.toString8();
return false;
}
- if (controlParcel.cmd) {
- control.cmdFd = controlParcel.cmd->release();
- }
- if (controlParcel.log) {
- control.logFd = controlParcel.log->release();
- }
+ control.cmd = controlParcel.cmd.release().release();
+ control.pendingReads = controlParcel.pendingReads.release().release();
+ control.logs = controlParcel.log.release().release();
auto ifs = std::make_shared<IncFsMount>(std::string(root), -1, std::move(control), *this);
@@ -860,8 +904,7 @@
mNextId = std::max(mNextId, ifs->mountId + 1);
std::vector<std::pair<std::string, metadata::BindPoint>> bindPoints;
- auto d = std::unique_ptr<DIR, decltype(&::closedir)>(::opendir(path::c_str(mountTarget)),
- ::closedir);
+ auto d = openDir(path::c_str(mountTarget));
while (auto e = ::readdir(d.get())) {
if (e->d_type == DT_REG) {
auto name = std::string_view(e->d_name);
@@ -874,7 +917,7 @@
if (bindPoints.back().second.dest_path().empty() ||
bindPoints.back().second.source_subdir().empty()) {
bindPoints.pop_back();
- mIncFs->unlink(ifs->control, INCFS_ROOT_INODE, name);
+ mIncFs->unlink(ifs->control, path::join(ifs->root, constants().mount, name));
}
}
} else if (e->d_type == DT_DIR) {
@@ -891,9 +934,7 @@
<< " for mount " << root;
continue;
}
- ifs->storages.insert_or_assign(md.id(),
- IncFsMount::Storage{std::string(name),
- Inode(e->d_ino)});
+ ifs->storages.insert_or_assign(md.id(), IncFsMount::Storage{std::string(name)});
mNextId = std::max(mNextId, md.id() + 1);
}
}
@@ -973,10 +1014,10 @@
}
FileSystemControlParcel fsControlParcel;
fsControlParcel.incremental = std::make_unique<IncrementalFileSystemControlParcel>();
- fsControlParcel.incremental->cmd =
- std::make_unique<os::ParcelFileDescriptor>(base::unique_fd(::dup(ifs.control.cmdFd)));
- fsControlParcel.incremental->log =
- std::make_unique<os::ParcelFileDescriptor>(base::unique_fd(::dup(ifs.control.logFd)));
+ fsControlParcel.incremental->cmd.reset(base::unique_fd(::dup(ifs.control.cmd)));
+ fsControlParcel.incremental->pendingReads.reset(
+ base::unique_fd(::dup(ifs.control.pendingReads)));
+ fsControlParcel.incremental->log.reset(base::unique_fd(::dup(ifs.control.logs)));
sp<IncrementalDataLoaderListener> listener = new IncrementalDataLoaderListener(*this);
bool created = false;
auto status = mIncrementalManager->prepareDataLoader(ifs.mountId, fsControlParcel, *dlp,
diff --git a/services/incremental/IncrementalService.h b/services/incremental/IncrementalService.h
index a03ffa0..ca5e4db 100644
--- a/services/incremental/IncrementalService.h
+++ b/services/incremental/IncrementalService.h
@@ -52,16 +52,16 @@
using MountId = int;
using StorageId = int;
-using Inode = incfs::Inode;
+using FileId = incfs::FileId;
using BlockIndex = incfs::BlockIndex;
using RawMetadata = incfs::RawMetadata;
using Clock = std::chrono::steady_clock;
using TimePoint = std::chrono::time_point<Clock>;
using Seconds = std::chrono::seconds;
-class IncrementalService {
+class IncrementalService final {
public:
- explicit IncrementalService(const ServiceManagerWrapper& sm, std::string_view rootDir);
+ explicit IncrementalService(ServiceManagerWrapper&& sm, std::string_view rootDir);
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
@@ -85,6 +85,11 @@
Permanent = 1,
};
+ static FileId idFromMetadata(std::span<const uint8_t> metadata);
+ static inline FileId idFromMetadata(std::span<const char> metadata) {
+ return idFromMetadata({(const uint8_t*)metadata.data(), metadata.size()});
+ }
+
std::optional<std::future<void>> onSystemReady();
StorageId createStorage(std::string_view mountPoint,
@@ -92,30 +97,31 @@
CreateOptions options = CreateOptions::Default);
StorageId createLinkedStorage(std::string_view mountPoint, StorageId linkedStorage,
CreateOptions options = CreateOptions::Default);
- StorageId openStorage(std::string_view pathInMount);
+ StorageId openStorage(std::string_view path);
- Inode nodeFor(StorageId storage, std::string_view subpath) const;
- std::pair<Inode, std::string_view> parentAndNameFor(StorageId storage,
- std::string_view subpath) const;
+ FileId nodeFor(StorageId storage, std::string_view path) const;
+ std::pair<FileId, std::string_view> parentAndNameFor(StorageId storage,
+ std::string_view path) const;
- int bind(StorageId storage, std::string_view subdir, std::string_view target, BindKind kind);
+ int bind(StorageId storage, std::string_view source, std::string_view target, BindKind kind);
int unbind(StorageId storage, std::string_view target);
void deleteStorage(StorageId storage);
- Inode makeFile(StorageId storage, std::string_view name, long size, std::string_view metadata,
- std::string_view signature);
- Inode makeDir(StorageId storage, std::string_view name, std::string_view metadata = {});
- Inode makeDirs(StorageId storage, std::string_view name, std::string_view metadata = {});
+ int makeFile(StorageId storage, std::string_view path, int mode, FileId id,
+ incfs::NewFileParams params);
+ int makeDir(StorageId storage, std::string_view path, int mode = 0555);
+ int makeDirs(StorageId storage, std::string_view path, int mode = 0555);
- int link(StorageId storage, Inode item, Inode newParent, std::string_view newName);
- int unlink(StorageId storage, Inode parent, std::string_view name);
+ int link(StorageId sourceStorageId, std::string_view oldPath, StorageId destStorageId,
+ std::string_view newPath);
+ int unlink(StorageId storage, std::string_view path);
- bool isRangeLoaded(StorageId storage, Inode file, std::pair<BlockIndex, BlockIndex> range) {
+ bool isRangeLoaded(StorageId storage, FileId file, std::pair<BlockIndex, BlockIndex> range) {
return false;
}
- RawMetadata getMetadata(StorageId storage, Inode node) const;
- std::string getSigngatureData(StorageId storage, Inode node) const { return {}; }
+ RawMetadata getMetadata(StorageId storage, FileId node) const;
+ std::string getSignatureData(StorageId storage, FileId node) const;
std::vector<std::string> listFiles(StorageId storage) const;
bool startLoading(StorageId storage) const;
@@ -142,19 +148,9 @@
struct Storage {
std::string name;
- Inode node;
};
- struct Control {
- operator IncFsControl() const { return {cmdFd, logFd}; }
- void reset() {
- cmdFd.reset();
- logFd.reset();
- }
-
- base::unique_fd cmdFd;
- base::unique_fd logFd;
- };
+ using Control = incfs::UniqueControl;
using BindMap = std::map<std::string, Bind>;
using StorageMap = std::unordered_map<StorageId, Storage>;
@@ -196,11 +192,12 @@
IfsMountPtr getIfs(StorageId storage) const;
const IfsMountPtr& getIfsLocked(StorageId storage) const;
- int addBindMount(IncFsMount& ifs, StorageId storage, std::string&& sourceSubdir,
- std::string&& target, BindKind kind, std::unique_lock<std::mutex>& mainLock);
+ int addBindMount(IncFsMount& ifs, StorageId storage, std::string_view storageRoot,
+ std::string&& source, std::string&& target, BindKind kind,
+ std::unique_lock<std::mutex>& mainLock);
int addBindMountWithMd(IncFsMount& ifs, StorageId storage, std::string&& metadataName,
- std::string&& sourceSubdir, std::string&& target, BindKind kind,
+ std::string&& source, std::string&& target, BindKind kind,
std::unique_lock<std::mutex>& mainLock);
bool prepareDataLoader(IncFsMount& ifs, DataLoaderParamsParcel* params);
@@ -212,10 +209,9 @@
MountMap::iterator getStorageSlotLocked();
// Member variables
- // These are shared pointers for the sake of unit testing
- std::shared_ptr<VoldServiceWrapper> mVold;
- std::shared_ptr<IncrementalManagerWrapper> mIncrementalManager;
- std::shared_ptr<IncFsWrapper> mIncFs;
+ std::unique_ptr<VoldServiceWrapper> mVold;
+ std::unique_ptr<IncrementalManagerWrapper> mIncrementalManager;
+ std::unique_ptr<IncFsWrapper> mIncFs;
const std::string mIncrementalDir;
mutable std::mutex mLock;
diff --git a/services/incremental/ServiceWrappers.cpp b/services/incremental/ServiceWrappers.cpp
index a79b26a..5d978a1c 100644
--- a/services/incremental/ServiceWrappers.cpp
+++ b/services/incremental/ServiceWrappers.cpp
@@ -16,14 +16,8 @@
#include "ServiceWrappers.h"
-#include <android-base/strings.h>
-#include <android-base/unique_fd.h>
-#include <binder/IServiceManager.h>
#include <utils/String16.h>
-#include <string>
-#include <string_view>
-
using namespace std::literals;
namespace android::os::incremental {
@@ -31,37 +25,38 @@
static constexpr auto kVoldServiceName = "vold"sv;
static constexpr auto kIncrementalManagerName = "incremental"sv;
-RealServiceManager::RealServiceManager(const sp<IServiceManager>& serviceManager)
- : mServiceManager(serviceManager) {}
+RealServiceManager::RealServiceManager(sp<IServiceManager> serviceManager)
+ : mServiceManager(std::move(serviceManager)) {}
template <class INTERFACE>
sp<INTERFACE> RealServiceManager::getRealService(std::string_view serviceName) const {
- sp<IBinder> binder = mServiceManager->getService(String16(serviceName.data()));
- if (binder == 0) {
- return 0;
+ sp<IBinder> binder =
+ mServiceManager->getService(String16(serviceName.data(), serviceName.size()));
+ if (!binder) {
+ return nullptr;
}
return interface_cast<INTERFACE>(binder);
}
-std::shared_ptr<VoldServiceWrapper> RealServiceManager::getVoldService() const {
+std::unique_ptr<VoldServiceWrapper> RealServiceManager::getVoldService() {
sp<os::IVold> vold = RealServiceManager::getRealService<os::IVold>(kVoldServiceName);
if (vold != 0) {
- return std::make_shared<RealVoldService>(vold);
+ return std::make_unique<RealVoldService>(vold);
}
return nullptr;
}
-std::shared_ptr<IncrementalManagerWrapper> RealServiceManager::getIncrementalManager() const {
+std::unique_ptr<IncrementalManagerWrapper> RealServiceManager::getIncrementalManager() {
sp<IIncrementalManager> manager =
RealServiceManager::getRealService<IIncrementalManager>(kIncrementalManagerName);
- if (manager != 0) {
- return std::make_shared<RealIncrementalManager>(manager);
+ if (manager) {
+ return std::make_unique<RealIncrementalManager>(manager);
}
return nullptr;
}
-std::shared_ptr<IncFsWrapper> RealServiceManager::getIncFs() const {
- return std::make_shared<RealIncFs>();
+std::unique_ptr<IncFsWrapper> RealServiceManager::getIncFs() {
+ return std::make_unique<RealIncFs>();
}
} // namespace android::os::incremental
diff --git a/services/incremental/ServiceWrappers.h b/services/incremental/ServiceWrappers.h
index 5704582..ae3739d 100644
--- a/services/incremental/ServiceWrappers.h
+++ b/services/incremental/ServiceWrappers.h
@@ -26,6 +26,7 @@
#include <binder/IServiceManager.h>
#include <incfs.h>
+#include <memory>
#include <string>
#include <string_view>
@@ -36,10 +37,12 @@
// --- Wrapper interfaces ---
+using MountId = int32_t;
+
class VoldServiceWrapper {
public:
- virtual ~VoldServiceWrapper(){};
- virtual binder::Status mountIncFs(const std::string& imagePath, const std::string& targetDir,
+ virtual ~VoldServiceWrapper() = default;
+ virtual binder::Status mountIncFs(const std::string& backingPath, const std::string& targetDir,
int32_t flags,
IncrementalFileSystemControlParcel* _aidl_return) const = 0;
virtual binder::Status unmountIncFs(const std::string& dir) const = 0;
@@ -49,52 +52,52 @@
class IncrementalManagerWrapper {
public:
- virtual ~IncrementalManagerWrapper() {}
- virtual binder::Status prepareDataLoader(
- int32_t mountId, const FileSystemControlParcel& control,
- const DataLoaderParamsParcel& params,
- const sp<IDataLoaderStatusListener>& listener,
- bool* _aidl_return) const = 0;
- virtual binder::Status startDataLoader(int32_t mountId, bool* _aidl_return) const = 0;
- virtual binder::Status destroyDataLoader(int32_t mountId) const = 0;
- virtual binder::Status newFileForDataLoader(int32_t mountId, int64_t inode,
- const ::std::vector<uint8_t>& metadata) const = 0;
- virtual binder::Status showHealthBlockedUI(int32_t mountId) const = 0;
+ virtual ~IncrementalManagerWrapper() = default;
+ virtual binder::Status prepareDataLoader(MountId mountId,
+ const FileSystemControlParcel& control,
+ const DataLoaderParamsParcel& params,
+ const sp<IDataLoaderStatusListener>& listener,
+ bool* _aidl_return) const = 0;
+ virtual binder::Status startDataLoader(MountId mountId, bool* _aidl_return) const = 0;
+ virtual binder::Status destroyDataLoader(MountId mountId) const = 0;
+ virtual binder::Status newFileForDataLoader(MountId mountId, FileId fileid,
+ const std::vector<uint8_t>& metadata) const = 0;
+ virtual binder::Status showHealthBlockedUI(MountId mountId) const = 0;
};
class IncFsWrapper {
public:
- virtual ~IncFsWrapper() {}
- virtual Inode makeFile(Control control, std::string_view name, Inode parent, Size size,
- std::string_view metadata) const = 0;
- virtual Inode makeDir(Control control, std::string_view name, Inode parent,
- std::string_view metadata, int mode = 0555) const = 0;
- virtual RawMetadata getMetadata(Control control, Inode inode) const = 0;
- virtual ErrorCode link(Control control, Inode item, Inode targetParent,
- std::string_view name) const = 0;
- virtual ErrorCode unlink(Control control, Inode parent, std::string_view name) const = 0;
- virtual ErrorCode writeBlocks(Control control, const incfs_new_data_block blocks[],
- int blocksCount) const = 0;
+ virtual ~IncFsWrapper() = default;
+ virtual ErrorCode makeFile(Control control, std::string_view path, int mode, FileId id,
+ NewFileParams params) const = 0;
+ virtual ErrorCode makeDir(Control control, std::string_view path, int mode = 0555) const = 0;
+ virtual RawMetadata getMetadata(Control control, FileId fileid) const = 0;
+ virtual RawMetadata getMetadata(Control control, std::string_view path) const = 0;
+ virtual FileId getFileId(Control control, std::string_view path) const = 0;
+ virtual ErrorCode link(Control control, std::string_view from, std::string_view to) const = 0;
+ virtual ErrorCode unlink(Control control, std::string_view path) const = 0;
+ virtual base::unique_fd openWrite(Control control, FileId id) const = 0;
+ virtual ErrorCode writeBlocks(std::span<const DataBlock> blocks) const = 0;
};
class ServiceManagerWrapper {
public:
- virtual ~ServiceManagerWrapper() {}
- virtual std::shared_ptr<VoldServiceWrapper> getVoldService() const = 0;
- virtual std::shared_ptr<IncrementalManagerWrapper> getIncrementalManager() const = 0;
- virtual std::shared_ptr<IncFsWrapper> getIncFs() const = 0;
+ virtual ~ServiceManagerWrapper() = default;
+ virtual std::unique_ptr<VoldServiceWrapper> getVoldService() = 0;
+ virtual std::unique_ptr<IncrementalManagerWrapper> getIncrementalManager() = 0;
+ virtual std::unique_ptr<IncFsWrapper> getIncFs() = 0;
};
// --- Real stuff ---
class RealVoldService : public VoldServiceWrapper {
public:
- RealVoldService(const sp<os::IVold> vold) : mInterface(vold) {}
+ RealVoldService(const sp<os::IVold> vold) : mInterface(std::move(vold)) {}
~RealVoldService() = default;
- binder::Status mountIncFs(const std::string& imagePath, const std::string& targetDir,
+ binder::Status mountIncFs(const std::string& backingPath, const std::string& targetDir,
int32_t flags,
IncrementalFileSystemControlParcel* _aidl_return) const override {
- return mInterface->mountIncFs(imagePath, targetDir, flags, _aidl_return);
+ return mInterface->mountIncFs(backingPath, targetDir, flags, _aidl_return);
}
binder::Status unmountIncFs(const std::string& dir) const override {
return mInterface->unmountIncFs(dir);
@@ -113,24 +116,26 @@
RealIncrementalManager(const sp<os::incremental::IIncrementalManager> manager)
: mInterface(manager) {}
~RealIncrementalManager() = default;
- binder::Status prepareDataLoader(
- int32_t mountId, const FileSystemControlParcel& control,
- const DataLoaderParamsParcel& params,
- const sp<IDataLoaderStatusListener>& listener,
- bool* _aidl_return) const override {
+ binder::Status prepareDataLoader(MountId mountId, const FileSystemControlParcel& control,
+ const DataLoaderParamsParcel& params,
+ const sp<IDataLoaderStatusListener>& listener,
+ bool* _aidl_return) const override {
return mInterface->prepareDataLoader(mountId, control, params, listener, _aidl_return);
}
- binder::Status startDataLoader(int32_t mountId, bool* _aidl_return) const override {
+ binder::Status startDataLoader(MountId mountId, bool* _aidl_return) const override {
return mInterface->startDataLoader(mountId, _aidl_return);
}
- binder::Status destroyDataLoader(int32_t mountId) const override {
+ binder::Status destroyDataLoader(MountId mountId) const override {
return mInterface->destroyDataLoader(mountId);
}
- binder::Status newFileForDataLoader(int32_t mountId, int64_t inode,
- const ::std::vector<uint8_t>& metadata) const override {
- return mInterface->newFileForDataLoader(mountId, inode, metadata);
+ binder::Status newFileForDataLoader(MountId mountId, FileId fileid,
+ const std::vector<uint8_t>& metadata) const override {
+ return mInterface->newFileForDataLoader(mountId,
+ {(const uint8_t*)fileid.data,
+ (const uint8_t*)fileid.data + sizeof(fileid.data)},
+ metadata);
}
- binder::Status showHealthBlockedUI(int32_t mountId) const override {
+ binder::Status showHealthBlockedUI(MountId mountId) const override {
return mInterface->showHealthBlockedUI(mountId);
}
@@ -140,11 +145,11 @@
class RealServiceManager : public ServiceManagerWrapper {
public:
- RealServiceManager(const sp<IServiceManager>& serviceManager);
+ RealServiceManager(sp<IServiceManager> serviceManager);
~RealServiceManager() = default;
- std::shared_ptr<VoldServiceWrapper> getVoldService() const override;
- std::shared_ptr<IncrementalManagerWrapper> getIncrementalManager() const override;
- std::shared_ptr<IncFsWrapper> getIncFs() const override;
+ std::unique_ptr<VoldServiceWrapper> getVoldService() override;
+ std::unique_ptr<IncrementalManagerWrapper> getIncrementalManager() override;
+ std::unique_ptr<IncFsWrapper> getIncFs() override;
private:
template <class INTERFACE>
@@ -156,27 +161,33 @@
public:
RealIncFs() = default;
~RealIncFs() = default;
- Inode makeFile(Control control, std::string_view name, Inode parent, Size size,
- std::string_view metadata) const override {
- return incfs::makeFile(control, name, parent, size, metadata);
+ ErrorCode makeFile(Control control, std::string_view path, int mode, FileId id,
+ NewFileParams params) const override {
+ return incfs::makeFile(control, path, mode, id, params);
}
- Inode makeDir(Control control, std::string_view name, Inode parent, std::string_view metadata,
- int mode) const override {
- return incfs::makeDir(control, name, parent, metadata, mode);
+ ErrorCode makeDir(Control control, std::string_view path, int mode) const override {
+ return incfs::makeDir(control, path, mode);
}
- RawMetadata getMetadata(Control control, Inode inode) const override {
- return incfs::getMetadata(control, inode);
+ RawMetadata getMetadata(Control control, FileId fileid) const override {
+ return incfs::getMetadata(control, fileid);
}
- ErrorCode link(Control control, Inode item, Inode targetParent,
- std::string_view name) const override {
- return incfs::link(control, item, targetParent, name);
+ RawMetadata getMetadata(Control control, std::string_view path) const override {
+ return incfs::getMetadata(control, path);
}
- ErrorCode unlink(Control control, Inode parent, std::string_view name) const override {
- return incfs::unlink(control, parent, name);
+ FileId getFileId(Control control, std::string_view path) const override {
+ return incfs::getFileId(control, path);
}
- ErrorCode writeBlocks(Control control, const incfs_new_data_block blocks[],
- int blocksCount) const override {
- return incfs::writeBlocks(control, blocks, blocksCount);
+ ErrorCode link(Control control, std::string_view from, std::string_view to) const override {
+ return incfs::link(control, from, to);
+ }
+ ErrorCode unlink(Control control, std::string_view path) const override {
+ return incfs::unlink(control, path);
+ }
+ base::unique_fd openWrite(Control control, FileId id) const override {
+ return base::unique_fd{incfs::openWrite(control, id)};
+ }
+ ErrorCode writeBlocks(std::span<const DataBlock> blocks) const override {
+ return incfs::writeBlocks(blocks);
}
};
diff --git a/services/incremental/path.cpp b/services/incremental/path.cpp
index c529d61..0d86f2a 100644
--- a/services/incremental/path.cpp
+++ b/services/incremental/path.cpp
@@ -44,16 +44,45 @@
PathCharsLess());
}
+static void preparePathComponent(std::string_view path, bool trimFront) {
+ if (trimFront) {
+ while (!path.empty() && path.front() == '/') {
+ path.remove_prefix(1);
+ }
+ }
+ while (!path.empty() && path.back() == '/') {
+ path.remove_suffix(1);
+ }
+}
+
void details::append_next_path(std::string& target, std::string_view path) {
+ preparePathComponent(path, true);
if (path.empty()) {
return;
}
- if (!target.empty()) {
+ if (!target.empty() && !target.ends_with('/')) {
target.push_back('/');
}
target += path;
}
+std::string_view relativize(std::string_view parent, std::string_view nested) {
+ if (!nested.starts_with(parent)) {
+ return nested;
+ }
+ if (nested.size() == parent.size()) {
+ return {};
+ }
+ if (nested[parent.size()] != '/') {
+ return nested;
+ }
+ auto relative = nested.substr(parent.size());
+ while (relative.front() == '/') {
+ relative.remove_prefix(1);
+ }
+ return relative;
+}
+
bool isAbsolute(std::string_view path) {
return !path.empty() && path[0] == '/';
}
diff --git a/services/incremental/path.h b/services/incremental/path.h
index a1f4b8e..3e5fd21 100644
--- a/services/incremental/path.h
+++ b/services/incremental/path.h
@@ -67,6 +67,20 @@
return {sv};
}
+std::string_view relativize(std::string_view parent, std::string_view nested);
+inline std::string_view relativize(const char* parent, const char* nested) {
+ return relativize(std::string_view(parent), std::string_view(nested));
+}
+inline std::string_view relativize(std::string_view parent, const char* nested) {
+ return relativize(parent, std::string_view(nested));
+}
+inline std::string_view relativize(const char* parent, std::string_view nested) {
+ return relativize(std::string_view(parent), nested);
+}
+
+std::string_view relativize(std::string&& parent, std::string_view nested) = delete;
+std::string_view relativize(std::string_view parent, std::string&& nested) = delete;
+
bool isAbsolute(std::string_view path);
std::string normalize(std::string_view path);
std::string_view dirname(std::string_view path);
diff --git a/services/incremental/test/IncrementalServiceTest.cpp b/services/incremental/test/IncrementalServiceTest.cpp
index ca1e1a9..2826818 100644
--- a/services/incremental/test/IncrementalServiceTest.cpp
+++ b/services/incremental/test/IncrementalServiceTest.cpp
@@ -46,7 +46,7 @@
class MockVoldService : public VoldServiceWrapper {
public:
MOCK_CONST_METHOD4(mountIncFs,
- binder::Status(const std::string& imagePath, const std::string& targetDir,
+ binder::Status(const std::string& backingPath, const std::string& targetDir,
int32_t flags,
IncrementalFileSystemControlParcel* _aidl_return));
MOCK_CONST_METHOD1(unmountIncFs, binder::Status(const std::string& dir));
@@ -77,22 +77,20 @@
binder::Status getInvalidControlParcel(const std::string& imagePath,
const std::string& targetDir, int32_t flags,
IncrementalFileSystemControlParcel* _aidl_return) {
- _aidl_return->cmd = nullptr;
- _aidl_return->log = nullptr;
+ _aidl_return = {};
return binder::Status::ok();
}
binder::Status incFsSuccess(const std::string& imagePath, const std::string& targetDir,
int32_t flags, IncrementalFileSystemControlParcel* _aidl_return) {
- _aidl_return->cmd = std::make_unique<os::ParcelFileDescriptor>(std::move(cmdFd));
- _aidl_return->log = std::make_unique<os::ParcelFileDescriptor>(std::move(logFd));
+ _aidl_return->pendingReads.reset(base::unique_fd(dup(STDIN_FILENO)));
+ _aidl_return->cmd.reset(base::unique_fd(dup(STDIN_FILENO)));
+ _aidl_return->log.reset(base::unique_fd(dup(STDIN_FILENO)));
return binder::Status::ok();
}
private:
TemporaryFile cmdFile;
TemporaryFile logFile;
- base::unique_fd cmdFd;
- base::unique_fd logFd;
};
class MockIncrementalManager : public IncrementalManagerWrapper {
@@ -105,7 +103,7 @@
MOCK_CONST_METHOD2(startDataLoader, binder::Status(int32_t mountId, bool* _aidl_return));
MOCK_CONST_METHOD1(destroyDataLoader, binder::Status(int32_t mountId));
MOCK_CONST_METHOD3(newFileForDataLoader,
- binder::Status(int32_t mountId, int64_t inode,
+ binder::Status(int32_t mountId, FileId fileId,
const ::std::vector<uint8_t>& metadata));
MOCK_CONST_METHOD1(showHealthBlockedUI, binder::Status(int32_t mountId));
@@ -152,23 +150,21 @@
class MockIncFs : public IncFsWrapper {
public:
MOCK_CONST_METHOD5(makeFile,
- Inode(Control control, std::string_view name, Inode parent, Size size,
- std::string_view metadata));
- MOCK_CONST_METHOD5(makeDir,
- Inode(Control control, std::string_view name, Inode parent,
- std::string_view metadata, int mode));
- MOCK_CONST_METHOD2(getMetadata, RawMetadata(Control control, Inode inode));
- MOCK_CONST_METHOD4(link,
- ErrorCode(Control control, Inode item, Inode targetParent,
- std::string_view name));
- MOCK_CONST_METHOD3(unlink, ErrorCode(Control control, Inode parent, std::string_view name));
- MOCK_CONST_METHOD3(writeBlocks,
- ErrorCode(Control control, const incfs_new_data_block blocks[],
- int blocksCount));
+ ErrorCode(Control control, std::string_view path, int mode, FileId id,
+ NewFileParams params));
+ MOCK_CONST_METHOD3(makeDir, ErrorCode(Control control, std::string_view path, int mode));
+ MOCK_CONST_METHOD2(getMetadata, RawMetadata(Control control, FileId fileid));
+ MOCK_CONST_METHOD2(getMetadata, RawMetadata(Control control, std::string_view path));
+ MOCK_CONST_METHOD2(getFileId, FileId(Control control, std::string_view path));
+ MOCK_CONST_METHOD3(link,
+ ErrorCode(Control control, std::string_view from, std::string_view to));
+ MOCK_CONST_METHOD2(unlink, ErrorCode(Control control, std::string_view path));
+ MOCK_CONST_METHOD2(openWrite, base::unique_fd(Control control, FileId id));
+ MOCK_CONST_METHOD1(writeBlocks, ErrorCode(std::span<const DataBlock> blocks));
void makeFileFails() { ON_CALL(*this, makeFile(_, _, _, _, _)).WillByDefault(Return(-1)); }
void makeFileSuccess() { ON_CALL(*this, makeFile(_, _, _, _, _)).WillByDefault(Return(0)); }
- RawMetadata getMountInfoMetadata(Control control, Inode inode) {
+ RawMetadata getMountInfoMetadata(Control control, std::string_view path) {
metadata::Mount m;
m.mutable_storage()->set_id(100);
m.mutable_loader()->set_package_name("com.test");
@@ -176,15 +172,15 @@
const auto metadata = m.SerializeAsString();
m.mutable_loader()->release_arguments();
m.mutable_loader()->release_package_name();
- return std::vector<char>(metadata.begin(), metadata.end());
+ return {metadata.begin(), metadata.end()};
}
- RawMetadata getStorageMetadata(Control control, Inode inode) {
+ RawMetadata getStorageMetadata(Control control, std::string_view path) {
metadata::Storage st;
st.set_id(100);
auto metadata = st.SerializeAsString();
- return std::vector<char>(metadata.begin(), metadata.end());
+ return {metadata.begin(), metadata.end()};
}
- RawMetadata getBindPointMetadata(Control control, Inode inode) {
+ RawMetadata getBindPointMetadata(Control control, std::string_view path) {
metadata::BindPoint bp;
std::string destPath = "dest";
std::string srcPath = "src";
@@ -200,40 +196,41 @@
class MockServiceManager : public ServiceManagerWrapper {
public:
- MockServiceManager(std::shared_ptr<MockVoldService> vold,
- std::shared_ptr<MockIncrementalManager> manager,
- std::shared_ptr<MockIncFs> incfs)
- : mVold(vold), mIncrementalManager(manager), mIncFs(incfs) {}
- std::shared_ptr<VoldServiceWrapper> getVoldService() const override { return mVold; }
- std::shared_ptr<IncrementalManagerWrapper> getIncrementalManager() const override {
- return mIncrementalManager;
+ MockServiceManager(std::unique_ptr<MockVoldService> vold,
+ std::unique_ptr<MockIncrementalManager> manager,
+ std::unique_ptr<MockIncFs> incfs)
+ : mVold(std::move(vold)),
+ mIncrementalManager(std::move(manager)),
+ mIncFs(std::move(incfs)) {}
+ std::unique_ptr<VoldServiceWrapper> getVoldService() final { return std::move(mVold); }
+ std::unique_ptr<IncrementalManagerWrapper> getIncrementalManager() final {
+ return std::move(mIncrementalManager);
}
- std::shared_ptr<IncFsWrapper> getIncFs() const override { return mIncFs; }
+ std::unique_ptr<IncFsWrapper> getIncFs() final { return std::move(mIncFs); }
private:
- std::shared_ptr<MockVoldService> mVold;
- std::shared_ptr<MockIncrementalManager> mIncrementalManager;
- std::shared_ptr<MockIncFs> mIncFs;
+ std::unique_ptr<MockVoldService> mVold;
+ std::unique_ptr<MockIncrementalManager> mIncrementalManager;
+ std::unique_ptr<MockIncFs> mIncFs;
};
// --- IncrementalServiceTest ---
-static Inode inode(std::string_view path) {
- struct stat st;
- if (::stat(path::c_str(path), &st)) {
- return -1;
- }
- return st.st_ino;
-}
-
class IncrementalServiceTest : public testing::Test {
public:
void SetUp() override {
- mVold = std::make_shared<NiceMock<MockVoldService>>();
- mIncrementalManager = std::make_shared<NiceMock<MockIncrementalManager>>();
- mIncFs = std::make_shared<NiceMock<MockIncFs>>();
- MockServiceManager serviceManager = MockServiceManager(mVold, mIncrementalManager, mIncFs);
- mIncrementalService = std::make_unique<IncrementalService>(serviceManager, mRootDir.path);
+ auto vold = std::make_unique<NiceMock<MockVoldService>>();
+ mVold = vold.get();
+ auto incrementalManager = std::make_unique<NiceMock<MockIncrementalManager>>();
+ mIncrementalManager = incrementalManager.get();
+ auto incFs = std::make_unique<NiceMock<MockIncFs>>();
+ mIncFs = incFs.get();
+ mIncrementalService =
+ std::make_unique<IncrementalService>(MockServiceManager(std::move(vold),
+ std::move(
+ incrementalManager),
+ std::move(incFs)),
+ mRootDir.path);
mDataLoaderParcel.packageName = "com.test";
mDataLoaderParcel.arguments = "uri";
mIncrementalService->onSystemReady();
@@ -252,20 +249,18 @@
const auto mountPointsFile = rootDir + "/dir1/mount/.mountpoint.abcd";
ASSERT_TRUE(base::WriteStringToFile("info", mountInfoFile));
ASSERT_TRUE(base::WriteStringToFile("mounts", mountPointsFile));
- ASSERT_GE(inode(mountInfoFile), 0);
- ASSERT_GE(inode(mountPointsFile), 0);
- ON_CALL(*mIncFs, getMetadata(_, inode(mountInfoFile)))
- .WillByDefault(Invoke(mIncFs.get(), &MockIncFs::getMountInfoMetadata));
- ON_CALL(*mIncFs, getMetadata(_, inode(mountPointsFile)))
- .WillByDefault(Invoke(mIncFs.get(), &MockIncFs::getBindPointMetadata));
- ON_CALL(*mIncFs, getMetadata(_, inode(rootDir + "/dir1/mount/st0")))
- .WillByDefault(Invoke(mIncFs.get(), &MockIncFs::getStorageMetadata));
+ ON_CALL(*mIncFs, getMetadata(_, std::string_view(mountInfoFile)))
+ .WillByDefault(Invoke(mIncFs, &MockIncFs::getMountInfoMetadata));
+ ON_CALL(*mIncFs, getMetadata(_, std::string_view(mountPointsFile)))
+ .WillByDefault(Invoke(mIncFs, &MockIncFs::getBindPointMetadata));
+ ON_CALL(*mIncFs, getMetadata(_, std::string_view(rootDir + "/dir1/mount/st0")))
+ .WillByDefault(Invoke(mIncFs, &MockIncFs::getStorageMetadata));
}
protected:
- std::shared_ptr<NiceMock<MockVoldService>> mVold;
- std::shared_ptr<NiceMock<MockIncFs>> mIncFs;
- std::shared_ptr<NiceMock<MockIncrementalManager>> mIncrementalManager;
+ NiceMock<MockVoldService>* mVold;
+ NiceMock<MockIncFs>* mIncFs;
+ NiceMock<MockIncrementalManager>* mIncrementalManager;
std::unique_ptr<IncrementalService> mIncrementalService;
TemporaryDir mRootDir;
DataLoaderParamsParcel mDataLoaderParcel;
@@ -412,12 +407,12 @@
mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
IncrementalService::CreateOptions::CreateNew);
std::string_view dir_path("test");
- EXPECT_CALL(*mIncFs, makeDir(_, dir_path, _, _, _));
- int fileIno = mIncrementalService->makeDir(storageId, dir_path, "");
- ASSERT_GE(fileIno, 0);
+ EXPECT_CALL(*mIncFs, makeDir(_, dir_path, _));
+ auto res = mIncrementalService->makeDir(storageId, dir_path, 0555);
+ ASSERT_EQ(res, 0);
}
-TEST_F(IncrementalServiceTest, testMakeDirectoryNoParent) {
+TEST_F(IncrementalServiceTest, testMakeDirectoryNested) {
mVold->mountIncFsSuccess();
mIncFs->makeFileSuccess();
mVold->bindMountSuccess();
@@ -427,13 +422,15 @@
int storageId =
mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
IncrementalService::CreateOptions::CreateNew);
- std::string_view first("first");
- std::string_view second("second");
+ auto first = "first"sv;
+ auto second = "second"sv;
std::string dir_path = std::string(first) + "/" + std::string(second);
- EXPECT_CALL(*mIncFs, makeDir(_, first, _, _, _)).Times(0);
- EXPECT_CALL(*mIncFs, makeDir(_, second, _, _, _)).Times(0);
- int fileIno = mIncrementalService->makeDir(storageId, dir_path, "");
- ASSERT_LT(fileIno, 0);
+ EXPECT_CALL(*mIncFs, makeDir(_, first, _)).Times(0);
+ EXPECT_CALL(*mIncFs, makeDir(_, second, _)).Times(0);
+ EXPECT_CALL(*mIncFs, makeDir(_, std::string_view(dir_path), _)).Times(1);
+
+ auto res = mIncrementalService->makeDir(storageId, dir_path, 0555);
+ ASSERT_EQ(res, 0);
}
TEST_F(IncrementalServiceTest, testMakeDirectories) {
@@ -446,16 +443,18 @@
int storageId =
mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
IncrementalService::CreateOptions::CreateNew);
- std::string_view first("first");
- std::string_view second("second");
- std::string_view third("third");
+ auto first = "first"sv;
+ auto second = "second"sv;
+ auto third = "third"sv;
InSequence seq;
- EXPECT_CALL(*mIncFs, makeDir(_, first, _, _, _));
- EXPECT_CALL(*mIncFs, makeDir(_, second, _, _, _));
- EXPECT_CALL(*mIncFs, makeDir(_, third, _, _, _));
- std::string dir_path =
- std::string(first) + "/" + std::string(second) + "/" + std::string(third);
- int fileIno = mIncrementalService->makeDirs(storageId, dir_path, "");
- ASSERT_GE(fileIno, 0);
+ auto parent_path = std::string(first) + "/" + std::string(second);
+ auto dir_path = parent_path + "/" + std::string(third);
+ EXPECT_CALL(*mIncFs, makeDir(_, std::string_view(dir_path), _)).WillOnce(Return(-ENOENT));
+ EXPECT_CALL(*mIncFs, makeDir(_, std::string_view(parent_path), _)).WillOnce(Return(-ENOENT));
+ EXPECT_CALL(*mIncFs, makeDir(_, first, _)).WillOnce(Return(0));
+ EXPECT_CALL(*mIncFs, makeDir(_, std::string_view(parent_path), _)).WillOnce(Return(0));
+ EXPECT_CALL(*mIncFs, makeDir(_, std::string_view(dir_path), _)).WillOnce(Return(0));
+ auto res = mIncrementalService->makeDirs(storageId, dir_path, 0555);
+ ASSERT_EQ(res, 0);
}
} // namespace android::os::incremental