installd: parameterize user data snapshots with snapshot_id
- snapshot_id will be provided by RollbackManagerService and for a given
rollback will be equal to its rollback_id.
- snapshotAppData now creates a folder to snapshot data to, in case it
does not exist.
- removed ceDataInode from restoreAppDataSnapshot API, since it's only
called if users phone is unlocked, meaning that CE data is available and
doesn't require inode to be accessed.
- refactored installd_service_test to reduce test set up boilerplate.
- added a test to cover case when snapshots for different packages have
the same snapshot_id.
Bug: 124029909
Test: installd_utils_test installd_service_test, RollbackTest
Change-Id: I4177a44a60cdfdc5429a28c613ce661b24482b8b
Merged-In: I4177a44a60cdfdc5429a28c613ce661b24482b8b
(cherry picked from commit b68f0d14931905472b93ad08a753a01a33bd315b)
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index ccffd29..a51946d 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -39,6 +39,7 @@
#include <sys/xattr.h>
#include <unistd.h>
+#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/properties.h>
#include <android-base/scopeguard.h>
@@ -80,6 +81,8 @@
// An uuid used in unit tests.
static constexpr const char* kTestUuid = "TEST";
+static constexpr const mode_t kRollbackFolderMode = 0700;
+
static constexpr const char* kCpPath = "/system/bin/cp";
static constexpr const char* kXattrDefault = "user.default";
@@ -784,8 +787,8 @@
binder::Status InstalldNativeService::snapshotAppData(
const std::unique_ptr<std::string>& volumeUuid,
- const std::string& packageName, int32_t user, int32_t storageFlags,
- int64_t* _aidl_return) {
+ const std::string& packageName, int32_t user, int32_t snapshotId,
+ int32_t storageFlags, int64_t* _aidl_return) {
ENFORCE_UID(AID_SYSTEM);
CHECK_ARGUMENT_UUID_IS_TEST_OR_NULL(volumeUuid);
CHECK_ARGUMENT_PACKAGE_NAME(packageName);
@@ -802,16 +805,19 @@
bool clear_ce_on_exit = false;
bool clear_de_on_exit = false;
- auto deleter = [&clear_ce_on_exit, &clear_de_on_exit, &volume_uuid, &user, &package_name] {
+ auto deleter = [&clear_ce_on_exit, &clear_de_on_exit, &volume_uuid, &user, &package_name,
+ &snapshotId] {
if (clear_de_on_exit) {
- auto to = create_data_misc_de_rollback_package_path(volume_uuid, user, package_name);
+ auto to = create_data_misc_de_rollback_package_path(volume_uuid, user, snapshotId,
+ package_name);
if (delete_dir_contents(to.c_str(), 1, nullptr) != 0) {
LOG(WARNING) << "Failed to delete app data snapshot: " << to;
}
}
if (clear_ce_on_exit) {
- auto to = create_data_misc_ce_rollback_package_path(volume_uuid, user, package_name);
+ auto to = create_data_misc_ce_rollback_package_path(volume_uuid, user, snapshotId,
+ package_name);
if (delete_dir_contents(to.c_str(), 1, nullptr) != 0) {
LOG(WARNING) << "Failed to delete app data snapshot: " << to;
}
@@ -847,15 +853,21 @@
if (storageFlags & FLAG_STORAGE_DE) {
auto from = create_data_user_de_package_path(volume_uuid, user, package_name);
- auto to = create_data_misc_de_rollback_path(volume_uuid, user);
+ auto to = create_data_misc_de_rollback_path(volume_uuid, user, snapshotId);
+ auto rollback_package_path = create_data_misc_de_rollback_package_path(volume_uuid, user,
+ snapshotId, package_name);
- int rd = delete_dir_contents(to, true /* ignore_if_missing */);
- if (rd != 0) {
- res = error(rd, "Failed clearing existing snapshot " + to);
- return res;
+ int rc = create_dir_if_needed(to.c_str(), kRollbackFolderMode);
+ if (rc != 0) {
+ return error(rc, "Failed to create folder " + to);
}
- int rc = copy_directory_recursive(from.c_str(), to.c_str());
+ rc = delete_dir_contents(rollback_package_path, true /* ignore_if_missing */);
+ if (rc != 0) {
+ return error(rc, "Failed clearing existing snapshot " + rollback_package_path);
+ }
+
+ rc = copy_directory_recursive(from.c_str(), to.c_str());
if (rc != 0) {
res = error(rc, "Failed copying " + from + " to " + to);
clear_de_on_exit = true;
@@ -865,15 +877,21 @@
if (storageFlags & FLAG_STORAGE_CE) {
auto from = create_data_user_ce_package_path(volume_uuid, user, package_name);
- auto to = create_data_misc_ce_rollback_path(volume_uuid, user);
+ auto to = create_data_misc_ce_rollback_path(volume_uuid, user, snapshotId);
+ auto rollback_package_path = create_data_misc_ce_rollback_package_path(volume_uuid, user,
+ snapshotId, package_name);
- int rd = delete_dir_contents(to, true /* ignore_if_missing */);
- if (rd != 0) {
- res = error(rd, "Failed clearing existing snapshot " + to);
- return res;
+ int rc = create_dir_if_needed(to.c_str(), kRollbackFolderMode);
+ if (rc != 0) {
+ return error(rc, "Failed to create folder " + to);
}
- int rc = copy_directory_recursive(from.c_str(), to.c_str());
+ rc = delete_dir_contents(rollback_package_path, true /* ignore_if_missing */);
+ if (rc != 0) {
+ return error(rc, "Failed clearing existing snapshot " + rollback_package_path);
+ }
+
+ rc = copy_directory_recursive(from.c_str(), to.c_str());
if (rc != 0) {
res = error(rc, "Failed copying " + from + " to " + to);
clear_ce_on_exit = true;
@@ -881,7 +899,7 @@
}
if (_aidl_return != nullptr) {
auto ce_snapshot_path = create_data_misc_ce_rollback_package_path(volume_uuid, user,
- package_name);
+ snapshotId, package_name);
rc = get_path_inode(ce_snapshot_path, reinterpret_cast<ino_t*>(_aidl_return));
if (rc != 0) {
res = error(rc, "Failed to get_path_inode for " + ce_snapshot_path);
@@ -896,8 +914,8 @@
binder::Status InstalldNativeService::restoreAppDataSnapshot(
const std::unique_ptr<std::string>& volumeUuid, const std::string& packageName,
- const int32_t appId, const int64_t ceDataInode, const std::string& seInfo,
- const int32_t user, int32_t storageFlags) {
+ const int32_t appId, const std::string& seInfo, const int32_t user,
+ const int32_t snapshotId, int32_t storageFlags) {
ENFORCE_UID(AID_SYSTEM);
CHECK_ARGUMENT_UUID_IS_TEST_OR_NULL(volumeUuid);
CHECK_ARGUMENT_PACKAGE_NAME(packageName);
@@ -907,9 +925,9 @@
const char* package_name = packageName.c_str();
auto from_ce = create_data_misc_ce_rollback_package_path(volume_uuid,
- user, package_name);
+ user, snapshotId, package_name);
auto from_de = create_data_misc_de_rollback_package_path(volume_uuid,
- user, package_name);
+ user, snapshotId, package_name);
const bool needs_ce_rollback = (storageFlags & FLAG_STORAGE_CE) &&
(access(from_ce.c_str(), F_OK) == 0);
@@ -926,7 +944,11 @@
// app with no data in those cases is arguably better than leaving the app
// with mismatched / stale data.
LOG(INFO) << "Clearing app data for " << packageName << " to restore snapshot.";
- binder::Status res = clearAppData(volumeUuid, packageName, user, storageFlags, ceDataInode);
+ // It's fine to pass 0 as ceDataInode here, because restoreAppDataSnapshot
+ // can only be called when user unlocks the phone, meaning that CE user data
+ // is decrypted.
+ binder::Status res = clearAppData(volumeUuid, packageName, user, storageFlags,
+ 0 /* ceDataInode */);
if (!res.isOk()) {
return res;
}
@@ -962,7 +984,8 @@
binder::Status InstalldNativeService::destroyAppDataSnapshot(
const std::unique_ptr<std::string> &volumeUuid, const std::string& packageName,
- const int32_t user, const int64_t ceSnapshotInode, int32_t storageFlags) {
+ const int32_t user, const int64_t ceSnapshotInode, const int32_t snapshotId,
+ int32_t storageFlags) {
ENFORCE_UID(AID_SYSTEM);
CHECK_ARGUMENT_UUID_IS_TEST_OR_NULL(volumeUuid);
CHECK_ARGUMENT_PACKAGE_NAME(packageName);
@@ -973,7 +996,7 @@
if (storageFlags & FLAG_STORAGE_DE) {
auto de_snapshot_path = create_data_misc_de_rollback_package_path(volume_uuid,
- user, package_name);
+ user, snapshotId, package_name);
int res = delete_dir_contents_and_dir(de_snapshot_path, true /* ignore_if_missing */);
if (res != 0) {
@@ -983,7 +1006,7 @@
if (storageFlags & FLAG_STORAGE_CE) {
auto ce_snapshot_path = create_data_misc_ce_rollback_package_path(volume_uuid,
- user, package_name, ceSnapshotInode);
+ user, snapshotId, package_name, ceSnapshotInode);
int res = delete_dir_contents_and_dir(ce_snapshot_path, true /* ignore_if_missing */);
if (res != 0) {
return error(res, "Failed clearing snapshot " + ce_snapshot_path);
diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h
index 578132d..0e91cb2 100644
--- a/cmds/installd/InstalldNativeService.h
+++ b/cmds/installd/InstalldNativeService.h
@@ -61,14 +61,14 @@
binder::Status fixupAppData(const std::unique_ptr<std::string>& uuid, int32_t flags);
binder::Status snapshotAppData(const std::unique_ptr<std::string>& volumeUuid,
- const std::string& packageName, const int32_t user, int32_t storageFlags,
- int64_t* _aidl_return);
+ const std::string& packageName, const int32_t user, const int32_t snapshotId,
+ int32_t storageFlags, int64_t* _aidl_return);
binder::Status restoreAppDataSnapshot(const std::unique_ptr<std::string>& volumeUuid,
- const std::string& packageName, const int32_t appId, const int64_t ceDataInode,
- const std::string& seInfo, const int32_t user, int32_t storageFlags);
+ const std::string& packageName, const int32_t appId, const std::string& seInfo,
+ const int32_t user, const int32_t snapshotId, int32_t storageFlags);
binder::Status destroyAppDataSnapshot(const std::unique_ptr<std::string> &volumeUuid,
const std::string& packageName, const int32_t user, const int64_t ceSnapshotInode,
- int32_t storageFlags);
+ const int32_t snapshotId, int32_t storageFlags);
binder::Status getAppSize(const std::unique_ptr<std::string>& uuid,
const std::vector<std::string>& packageNames, int32_t userId, int32_t flags,
diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl
index 377074a..51fe66b 100644
--- a/cmds/installd/binder/android/os/IInstalld.aidl
+++ b/cmds/installd/binder/android/os/IInstalld.aidl
@@ -106,11 +106,11 @@
@nullable @utf8InCpp String dexMetadata);
long snapshotAppData(@nullable @utf8InCpp String uuid, in @utf8InCpp String packageName,
- int userId, int storageFlags);
+ int userId, int snapshotId, int storageFlags);
void restoreAppDataSnapshot(@nullable @utf8InCpp String uuid, in @utf8InCpp String packageName,
- int appId, long ceDataInode, @utf8InCpp String seInfo, int user, int storageflags);
+ int appId, @utf8InCpp String seInfo, int user, int snapshotId, int storageflags);
void destroyAppDataSnapshot(@nullable @utf8InCpp String uuid, @utf8InCpp String packageName,
- int userId, long ceSnapshotInode, int storageFlags);
+ int userId, long ceSnapshotInode, int snapshotId, int storageFlags);
const int FLAG_STORAGE_DE = 0x1;
const int FLAG_STORAGE_CE = 0x2;
diff --git a/cmds/installd/tests/installd_service_test.cpp b/cmds/installd/tests/installd_service_test.cpp
index ed1a0f4..cd63931 100644
--- a/cmds/installd/tests/installd_service_test.cpp
+++ b/cmds/installd/tests/installd_service_test.cpp
@@ -259,32 +259,59 @@
return false;
}
- return (::mkdir(path.c_str(), mode) != -1);
+ if (::mkdir(path.c_str(), mode) != 0) {
+ PLOG(DEBUG) << "Failed to create folder " << path;
+ return false;
+ }
+ return true;
}
-TEST_F(ServiceTest, CreateAppDataSnapshot) {
- auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0);
- auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0);
+class AppDataSnapshotTest : public testing::Test {
+private:
+ std::string rollback_ce_base_dir;
+ std::string rollback_de_base_dir;
- ASSERT_TRUE(mkdirs(rollback_ce_dir, 700));
- ASSERT_TRUE(mkdirs(rollback_de_dir, 700));
+protected:
+ InstalldNativeService* service;
- auto fake_package_ce_path = create_data_user_ce_package_path("TEST", 0, "com.foo");
- auto fake_package_de_path = create_data_user_de_package_path("TEST", 0, "com.foo");
+ std::string fake_package_ce_path;
+ std::string fake_package_de_path;
- ASSERT_TRUE(mkdirs(fake_package_ce_path, 700));
- ASSERT_TRUE(mkdirs(fake_package_de_path, 700));
+ virtual void SetUp() {
+ setenv("ANDROID_LOG_TAGS", "*:v", 1);
+ android::base::InitLogging(nullptr);
- auto deleter = [&rollback_ce_dir, &rollback_de_dir,
- &fake_package_ce_path, &fake_package_de_path]() {
- delete_dir_contents(rollback_ce_dir, true);
- delete_dir_contents(rollback_de_dir, true);
- delete_dir_contents(fake_package_ce_path, true);
- delete_dir_contents(fake_package_de_path, true);
- rmdir(rollback_ce_dir.c_str());
- rmdir(rollback_de_dir.c_str());
- };
- auto scope_guard = android::base::make_scope_guard(deleter);
+ service = new InstalldNativeService();
+ ASSERT_TRUE(mkdirs("/data/local/tmp/user/0", 0700));
+
+ init_globals_from_data_and_root();
+
+ rollback_ce_base_dir = create_data_misc_ce_rollback_base_path("TEST", 0);
+ rollback_de_base_dir = create_data_misc_de_rollback_base_path("TEST", 0);
+
+ fake_package_ce_path = create_data_user_ce_package_path("TEST", 0, "com.foo");
+ fake_package_de_path = create_data_user_de_package_path("TEST", 0, "com.foo");
+
+ ASSERT_TRUE(mkdirs(rollback_ce_base_dir, 0700));
+ ASSERT_TRUE(mkdirs(rollback_de_base_dir, 0700));
+ ASSERT_TRUE(mkdirs(fake_package_ce_path, 0700));
+ ASSERT_TRUE(mkdirs(fake_package_de_path, 0700));
+ }
+
+ virtual void TearDown() {
+ ASSERT_EQ(0, delete_dir_contents_and_dir(rollback_ce_base_dir, true));
+ ASSERT_EQ(0, delete_dir_contents_and_dir(rollback_de_base_dir, true));
+ ASSERT_EQ(0, delete_dir_contents(fake_package_ce_path, true));
+ ASSERT_EQ(0, delete_dir_contents(fake_package_de_path, true));
+
+ delete service;
+ ASSERT_EQ(0, delete_dir_contents_and_dir("/data/local/tmp/user/0", true));
+ }
+};
+
+TEST_F(AppDataSnapshotTest, CreateAppDataSnapshot) {
+ auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0, 37);
+ auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0, 37);
ASSERT_TRUE(android::base::WriteStringToFile(
"TEST_CONTENT_CE", fake_package_ce_path + "/file1",
@@ -296,7 +323,7 @@
// Request a snapshot of the CE content but not the DE content.
int64_t ce_snapshot_inode;
ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_unique<std::string>("TEST"),
- "com.foo", 0, FLAG_STORAGE_CE, &ce_snapshot_inode));
+ "com.foo", 0, 37, FLAG_STORAGE_CE, &ce_snapshot_inode));
struct stat buf;
memset(&buf, 0, sizeof(buf));
ASSERT_EQ(0, stat((rollback_ce_dir + "/com.foo").c_str(), &buf));
@@ -318,7 +345,7 @@
// Request a snapshot of the DE content but not the CE content.
ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_unique<std::string>("TEST"),
- "com.foo", 0, FLAG_STORAGE_DE, &ce_snapshot_inode));
+ "com.foo", 0, 37, FLAG_STORAGE_DE, &ce_snapshot_inode));
// Only DE content snapshot was requested.
ASSERT_EQ(ce_snapshot_inode, 0);
@@ -339,7 +366,7 @@
// Request a snapshot of both the CE as well as the DE content.
ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_unique<std::string>("TEST"),
- "com.foo", 0, FLAG_STORAGE_DE | FLAG_STORAGE_CE, nullptr));
+ "com.foo", 0, 37, FLAG_STORAGE_DE | FLAG_STORAGE_CE, nullptr));
ASSERT_TRUE(android::base::ReadFileToString(
rollback_ce_dir + "/com.foo/file1", &ce_content, false /* follow_symlinks */));
@@ -349,27 +376,73 @@
ASSERT_EQ("TEST_CONTENT_DE_MODIFIED", de_content);
}
-TEST_F(ServiceTest, CreateAppDataSnapshot_AppDataAbsent) {
- auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0);
- auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0);
+TEST_F(AppDataSnapshotTest, CreateAppDataSnapshot_TwoSnapshotsWithTheSameId) {
+ auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0, 67);
+ auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0, 67);
- ASSERT_TRUE(mkdirs(rollback_ce_dir, 700));
- ASSERT_TRUE(mkdirs(rollback_de_dir, 700));
+ auto another_fake_package_ce_path = create_data_user_ce_package_path("TEST", 0, "com.bar");
+ auto another_fake_package_de_path = create_data_user_de_package_path("TEST", 0, "com.bar");
- auto deleter = [&rollback_ce_dir, &rollback_de_dir]() {
- delete_dir_contents(rollback_ce_dir, true);
- delete_dir_contents(rollback_de_dir, true);
- rmdir(rollback_ce_dir.c_str());
- rmdir(rollback_de_dir.c_str());
+ // Since this test sets up data for another package, some bookkeeping is required.
+ auto deleter = [&]() {
+ ASSERT_EQ(0, delete_dir_contents_and_dir(another_fake_package_ce_path, true));
+ ASSERT_EQ(0, delete_dir_contents_and_dir(another_fake_package_de_path, true));
};
-
auto scope_guard = android::base::make_scope_guard(deleter);
+ ASSERT_TRUE(mkdirs(another_fake_package_ce_path, 0700));
+ ASSERT_TRUE(mkdirs(another_fake_package_de_path, 0700));
+
+ ASSERT_TRUE(android::base::WriteStringToFile(
+ "TEST_CONTENT_CE", fake_package_ce_path + "/file1",
+ 0700, 10000, 20000, false /* follow_symlinks */));
+ ASSERT_TRUE(android::base::WriteStringToFile(
+ "TEST_CONTENT_DE", fake_package_de_path + "/file1",
+ 0700, 10000, 20000, false /* follow_symlinks */));
+ ASSERT_TRUE(android::base::WriteStringToFile(
+ "ANOTHER_TEST_CONTENT_CE", another_fake_package_ce_path + "/file1",
+ 0700, 10000, 20000, false /* follow_symlinks */));
+ ASSERT_TRUE(android::base::WriteStringToFile(
+ "ANOTHER_TEST_CONTENT_DE", another_fake_package_de_path + "/file1",
+ 0700, 10000, 20000, false /* follow_symlinks */));
+
+ // Request snapshot for the package com.foo.
+ ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_unique<std::string>("TEST"),
+ "com.foo", 0, 67, FLAG_STORAGE_DE | FLAG_STORAGE_CE, nullptr));
+ // Now request snapshot with the same id for the package com.bar
+ ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_unique<std::string>("TEST"),
+ "com.bar", 0, 67, FLAG_STORAGE_DE | FLAG_STORAGE_CE, nullptr));
+
+ // Check that both snapshots have correct data in them.
+ std::string com_foo_ce_content, com_foo_de_content;
+ std::string com_bar_ce_content, com_bar_de_content;
+ ASSERT_TRUE(android::base::ReadFileToString(
+ rollback_ce_dir + "/com.foo/file1", &com_foo_ce_content, false /* follow_symlinks */));
+ ASSERT_TRUE(android::base::ReadFileToString(
+ rollback_de_dir + "/com.foo/file1", &com_foo_de_content, false /* follow_symlinks */));
+ ASSERT_TRUE(android::base::ReadFileToString(
+ rollback_ce_dir + "/com.bar/file1", &com_bar_ce_content, false /* follow_symlinks */));
+ ASSERT_TRUE(android::base::ReadFileToString(
+ rollback_de_dir + "/com.bar/file1", &com_bar_de_content, false /* follow_symlinks */));
+ ASSERT_EQ("TEST_CONTENT_CE", com_foo_ce_content);
+ ASSERT_EQ("TEST_CONTENT_DE", com_foo_de_content);
+ ASSERT_EQ("ANOTHER_TEST_CONTENT_CE", com_bar_ce_content);
+ ASSERT_EQ("ANOTHER_TEST_CONTENT_DE", com_bar_de_content);
+}
+
+TEST_F(AppDataSnapshotTest, CreateAppDataSnapshot_AppDataAbsent) {
+ auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0, 73);
+ auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0, 73);
+
+ // Similuating app data absence.
+ ASSERT_EQ(0, delete_dir_contents_and_dir(fake_package_ce_path, true));
+ ASSERT_EQ(0, delete_dir_contents_and_dir(fake_package_de_path, true));
+
int64_t ce_snapshot_inode;
ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_unique<std::string>("TEST"),
- "com.foo", 0, FLAG_STORAGE_CE, &ce_snapshot_inode));
+ "com.foo", 0, 73, FLAG_STORAGE_CE, &ce_snapshot_inode));
ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_unique<std::string>("TEST"),
- "com.foo", 0, FLAG_STORAGE_DE, nullptr));
+ "com.foo", 0, 73, FLAG_STORAGE_DE, nullptr));
// No CE content snapshot was performed.
ASSERT_EQ(ce_snapshot_inode, 0);
@@ -380,29 +453,12 @@
ASSERT_EQ(-1, stat((rollback_de_dir + "/com.foo").c_str(), &sb));
}
-TEST_F(ServiceTest, CreateAppDataSnapshot_ClearsExistingSnapshot) {
- auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0);
- auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0);
+TEST_F(AppDataSnapshotTest, CreateAppDataSnapshot_ClearsExistingSnapshot) {
+ auto rollback_ce_dir = create_data_misc_ce_rollback_package_path("TEST", 0, 13, "com.foo");
+ auto rollback_de_dir = create_data_misc_de_rollback_package_path("TEST", 0, 13, "com.foo");
- ASSERT_TRUE(mkdirs(rollback_ce_dir, 700));
- ASSERT_TRUE(mkdirs(rollback_de_dir, 700));
-
- auto fake_package_ce_path = create_data_user_ce_package_path("TEST", 0, "com.foo");
- auto fake_package_de_path = create_data_user_de_package_path("TEST", 0, "com.foo");
-
- ASSERT_TRUE(mkdirs(fake_package_ce_path, 700));
- ASSERT_TRUE(mkdirs(fake_package_de_path, 700));
-
- auto deleter = [&rollback_ce_dir, &rollback_de_dir,
- &fake_package_ce_path, &fake_package_de_path]() {
- delete_dir_contents(rollback_ce_dir, true);
- delete_dir_contents(rollback_de_dir, true);
- delete_dir_contents(fake_package_ce_path, true);
- delete_dir_contents(fake_package_de_path, true);
- rmdir(rollback_ce_dir.c_str());
- rmdir(rollback_de_dir.c_str());
- };
- auto scope_guard = android::base::make_scope_guard(deleter);
+ ASSERT_TRUE(mkdirs(rollback_ce_dir, 0700));
+ ASSERT_TRUE(mkdirs(rollback_de_dir, 0700));
// Simulate presence of an existing snapshot
ASSERT_TRUE(android::base::WriteStringToFile(
@@ -421,62 +477,40 @@
0700, 10000, 20000, false /* follow_symlinks */));
ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_unique<std::string>("TEST"),
- "com.foo", 0, FLAG_STORAGE_DE | FLAG_STORAGE_CE, nullptr));
+ "com.foo", 0, 13, FLAG_STORAGE_DE | FLAG_STORAGE_CE, nullptr));
// Previous snapshot (with data for file1) must be cleared.
struct stat sb;
- ASSERT_EQ(-1, stat((rollback_ce_dir + "/com.foo/file1").c_str(), &sb));
- ASSERT_EQ(-1, stat((rollback_de_dir + "/com.foo/file1").c_str(), &sb));
+ ASSERT_EQ(-1, stat((rollback_ce_dir + "/file1").c_str(), &sb));
+ ASSERT_EQ(-1, stat((rollback_de_dir + "/file1").c_str(), &sb));
+ // New snapshot (with data for file2) must be present.
+ ASSERT_NE(-1, stat((rollback_ce_dir + "/file2").c_str(), &sb));
+ ASSERT_NE(-1, stat((rollback_de_dir + "/file2").c_str(), &sb));
}
-TEST_F(ServiceTest, SnapshotAppData_WrongVolumeUuid) {
- // Setup app data to make sure that fails due to wrong volumeUuid being
+TEST_F(AppDataSnapshotTest, SnapshotAppData_WrongVolumeUuid) {
+ // Setup rollback folders to make sure that fails due to wrong volumeUuid being
// passed, not because of some other reason.
- auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0);
- auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0);
+ auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0, 17);
+ auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0, 17);
- ASSERT_TRUE(mkdirs(rollback_ce_dir, 700));
- ASSERT_TRUE(mkdirs(rollback_de_dir, 700));
-
- auto deleter = [&rollback_ce_dir, &rollback_de_dir]() {
- delete_dir_contents(rollback_ce_dir, true);
- delete_dir_contents(rollback_de_dir, true);
- rmdir(rollback_ce_dir.c_str());
- rmdir(rollback_de_dir.c_str());
- };
- auto scope_guard = android::base::make_scope_guard(deleter);
+ ASSERT_TRUE(mkdirs(rollback_ce_dir, 0700));
+ ASSERT_TRUE(mkdirs(rollback_de_dir, 0700));
EXPECT_BINDER_FAIL(service->snapshotAppData(std::make_unique<std::string>("FOO"),
- "com.foo", 0, FLAG_STORAGE_DE, nullptr));
+ "com.foo", 0, 17, FLAG_STORAGE_DE, nullptr));
}
-TEST_F(ServiceTest, CreateAppDataSnapshot_ClearsCache) {
- auto fake_package_ce_path = create_data_user_ce_package_path("TEST", 0, "com.foo");
- auto fake_package_de_path = create_data_user_de_package_path("TEST", 0, "com.foo");
+TEST_F(AppDataSnapshotTest, CreateAppDataSnapshot_ClearsCache) {
auto fake_package_ce_cache_path = fake_package_ce_path + "/cache";
auto fake_package_ce_code_cache_path = fake_package_ce_path + "/code_cache";
auto fake_package_de_cache_path = fake_package_de_path + "/cache";
auto fake_package_de_code_cache_path = fake_package_de_path + "/code_cache";
- auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0);
- auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0);
- ASSERT_TRUE(mkdirs(fake_package_ce_path, 700));
- ASSERT_TRUE(mkdirs(fake_package_de_path, 700));
- ASSERT_TRUE(mkdirs(fake_package_ce_cache_path, 700));
- ASSERT_TRUE(mkdirs(fake_package_ce_code_cache_path, 700));
- ASSERT_TRUE(mkdirs(fake_package_de_cache_path, 700));
- ASSERT_TRUE(mkdirs(fake_package_de_code_cache_path, 700));
- ASSERT_TRUE(mkdirs(rollback_ce_dir, 700));
- ASSERT_TRUE(mkdirs(rollback_de_dir, 700));
-
- auto deleter = [&fake_package_ce_path, &fake_package_de_path,
- &rollback_ce_dir, &rollback_de_dir]() {
- delete_dir_contents(fake_package_ce_path, true);
- delete_dir_contents(fake_package_de_path, true);
- delete_dir_contents_and_dir(rollback_ce_dir, true);
- delete_dir_contents_and_dir(rollback_de_dir, true);
- };
- auto scope_guard = android::base::make_scope_guard(deleter);
+ ASSERT_TRUE(mkdirs(fake_package_ce_cache_path, 0700));
+ ASSERT_TRUE(mkdirs(fake_package_ce_code_cache_path, 0700));
+ ASSERT_TRUE(mkdirs(fake_package_de_cache_path, 0700));
+ ASSERT_TRUE(mkdirs(fake_package_de_code_cache_path, 0700));
ASSERT_TRUE(android::base::WriteStringToFile(
"TEST_CONTENT_CE", fake_package_ce_cache_path + "/file1",
@@ -491,7 +525,7 @@
"TEST_CONTENT_DE", fake_package_de_code_cache_path + "/file1",
0700, 10000, 20000, false /* follow_symlinks */));
ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_unique<std::string>("TEST"),
- "com.foo", 0, FLAG_STORAGE_CE | FLAG_STORAGE_DE, nullptr));
+ "com.foo", 0, 23, FLAG_STORAGE_CE | FLAG_STORAGE_DE, nullptr));
// The snapshot call must clear cache.
struct stat sb;
ASSERT_EQ(-1, stat((fake_package_ce_cache_path + "/file1").c_str(), &sb));
@@ -500,34 +534,17 @@
ASSERT_EQ(-1, stat((fake_package_de_code_cache_path + "/file1").c_str(), &sb));
}
-TEST_F(ServiceTest, RestoreAppDataSnapshot) {
- auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0);
- auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0);
+TEST_F(AppDataSnapshotTest, RestoreAppDataSnapshot) {
+ auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0, 239);
+ auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0, 239);
- ASSERT_TRUE(mkdirs(rollback_ce_dir, 700));
- ASSERT_TRUE(mkdirs(rollback_de_dir, 700));
-
- auto fake_package_ce_path = create_data_user_ce_package_path("TEST", 0, "com.foo");
- auto fake_package_de_path = create_data_user_de_package_path("TEST", 0, "com.foo");
-
- ASSERT_TRUE(mkdirs(fake_package_ce_path, 700));
- ASSERT_TRUE(mkdirs(fake_package_de_path, 700));
-
- auto deleter = [&rollback_ce_dir, &rollback_de_dir,
- &fake_package_ce_path, &fake_package_de_path]() {
- delete_dir_contents(rollback_ce_dir, true);
- delete_dir_contents(rollback_de_dir, true);
- delete_dir_contents(fake_package_ce_path, true);
- delete_dir_contents(fake_package_de_path, true);
- rmdir(rollback_ce_dir.c_str());
- rmdir(rollback_de_dir.c_str());
- };
- auto scope_guard = android::base::make_scope_guard(deleter);
+ ASSERT_TRUE(mkdirs(rollback_ce_dir, 0700));
+ ASSERT_TRUE(mkdirs(rollback_de_dir, 0700));
// Write contents to the rollback location. We'll write the same files to the
// app data location and make sure the restore has overwritten them.
- ASSERT_TRUE(mkdirs(rollback_ce_dir + "/com.foo/", 700));
- ASSERT_TRUE(mkdirs(rollback_de_dir + "/com.foo/", 700));
+ ASSERT_TRUE(mkdirs(rollback_ce_dir + "/com.foo/", 0700));
+ ASSERT_TRUE(mkdirs(rollback_de_dir + "/com.foo/", 0700));
ASSERT_TRUE(android::base::WriteStringToFile(
"CE_RESTORE_CONTENT", rollback_ce_dir + "/com.foo/file1",
0700, 10000, 20000, false /* follow_symlinks */));
@@ -542,7 +559,7 @@
0700, 10000, 20000, false /* follow_symlinks */));
ASSERT_BINDER_SUCCESS(service->restoreAppDataSnapshot(std::make_unique<std::string>("TEST"),
- "com.foo", 10000, -1, "", 0, FLAG_STORAGE_DE | FLAG_STORAGE_CE));
+ "com.foo", 10000, "", 0, 239, FLAG_STORAGE_DE | FLAG_STORAGE_CE));
std::string ce_content, de_content;
ASSERT_TRUE(android::base::ReadFileToString(
@@ -553,29 +570,9 @@
ASSERT_EQ("DE_RESTORE_CONTENT", de_content);
}
-TEST_F(ServiceTest, CreateSnapshotThenDestroyIt) {
- auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0);
- auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0);
-
- ASSERT_TRUE(mkdirs(rollback_ce_dir, 700));
- ASSERT_TRUE(mkdirs(rollback_de_dir, 700));
-
- auto fake_package_ce_path = create_data_user_ce_package_path("TEST", 0, "com.foo");
- auto fake_package_de_path = create_data_user_de_package_path("TEST", 0, "com.foo");
-
- ASSERT_TRUE(mkdirs(fake_package_ce_path, 700));
- ASSERT_TRUE(mkdirs(fake_package_de_path, 700));
-
- auto deleter = [&rollback_ce_dir, &rollback_de_dir,
- &fake_package_ce_path, &fake_package_de_path]() {
- delete_dir_contents(rollback_ce_dir, true);
- delete_dir_contents(rollback_de_dir, true);
- delete_dir_contents(fake_package_ce_path, true);
- delete_dir_contents(fake_package_de_path, true);
- rmdir(rollback_ce_dir.c_str());
- rmdir(rollback_de_dir.c_str());
- };
- auto scope_guard = android::base::make_scope_guard(deleter);
+TEST_F(AppDataSnapshotTest, CreateSnapshotThenDestroyIt) {
+ auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0, 57);
+ auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0, 57);
// Prepare data for snapshot.
ASSERT_TRUE(android::base::WriteStringToFile(
@@ -588,7 +585,7 @@
int64_t ce_snapshot_inode;
// Request a snapshot of both the CE as well as the DE content.
ASSERT_TRUE(service->snapshotAppData(std::make_unique<std::string>("TEST"),
- "com.foo", 0, FLAG_STORAGE_DE | FLAG_STORAGE_CE, &ce_snapshot_inode).isOk());
+ "com.foo", 0, 57, FLAG_STORAGE_DE | FLAG_STORAGE_CE, &ce_snapshot_inode).isOk());
// Because CE data snapshot was requested, ce_snapshot_inode can't be null.
ASSERT_NE(0, ce_snapshot_inode);
// Check snapshot is there.
@@ -598,39 +595,19 @@
ASSERT_TRUE(service->destroyAppDataSnapshot(std::make_unique<std::string>("TEST"),
- "com.foo", 0, ce_snapshot_inode, FLAG_STORAGE_DE | FLAG_STORAGE_CE).isOk());
+ "com.foo", 0, ce_snapshot_inode, 57, FLAG_STORAGE_DE | FLAG_STORAGE_CE).isOk());
// Check snapshot is deleted.
ASSERT_EQ(-1, stat((rollback_ce_dir + "/com.foo").c_str(), &sb));
ASSERT_EQ(-1, stat((rollback_de_dir + "/com.foo").c_str(), &sb));
}
-TEST_F(ServiceTest, DestroyAppDataSnapshot_CeSnapshotInodeIsZero) {
- auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0);
- auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0);
-
- ASSERT_TRUE(mkdirs(rollback_ce_dir, 700));
- ASSERT_TRUE(mkdirs(rollback_de_dir, 700));
-
- auto fake_package_ce_path = create_data_user_ce_package_path("TEST", 0, "com.foo");
- auto fake_package_de_path = create_data_user_de_package_path("TEST", 0, "com.foo");
-
- ASSERT_TRUE(mkdirs(fake_package_ce_path, 700));
- ASSERT_TRUE(mkdirs(fake_package_de_path, 700));
-
- auto deleter = [&rollback_ce_dir, &rollback_de_dir,
- &fake_package_ce_path, &fake_package_de_path]() {
- delete_dir_contents(rollback_ce_dir, true);
- delete_dir_contents(rollback_de_dir, true);
- delete_dir_contents(fake_package_ce_path, true);
- delete_dir_contents(fake_package_de_path, true);
- rmdir(rollback_ce_dir.c_str());
- rmdir(rollback_de_dir.c_str());
- };
- auto scope_guard = android::base::make_scope_guard(deleter);
+TEST_F(AppDataSnapshotTest, DestroyAppDataSnapshot_CeSnapshotInodeIsZero) {
+ auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0, 1543);
+ auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0, 1543);
// Create a snapshot
- ASSERT_TRUE(mkdirs(rollback_ce_dir + "/com.foo/", 700));
- ASSERT_TRUE(mkdirs(rollback_de_dir + "/com.foo/", 700));
+ ASSERT_TRUE(mkdirs(rollback_ce_dir + "/com.foo/", 0700));
+ ASSERT_TRUE(mkdirs(rollback_de_dir + "/com.foo/", 0700));
ASSERT_TRUE(android::base::WriteStringToFile(
"CE_RESTORE_CONTENT", rollback_ce_dir + "/com.foo/file1",
0700, 10000, 20000, false /* follow_symlinks */));
@@ -639,7 +616,7 @@
0700, 10000, 20000, false /* follow_symlinks */));
ASSERT_TRUE(service->destroyAppDataSnapshot(std::make_unique<std::string>("TEST"),
- "com.foo", 0, 0, FLAG_STORAGE_DE | FLAG_STORAGE_CE).isOk());
+ "com.foo", 0, 0, 1543, FLAG_STORAGE_DE | FLAG_STORAGE_CE).isOk());
// Check snapshot is deleted.
struct stat sb;
@@ -648,67 +625,33 @@
// Check that deleting already deleted snapshot is no-op.
ASSERT_TRUE(service->destroyAppDataSnapshot(std::make_unique<std::string>("TEST"),
- "com.foo", 0, 0, FLAG_STORAGE_DE | FLAG_STORAGE_CE).isOk());
+ "com.foo", 0, 0, 1543, FLAG_STORAGE_DE | FLAG_STORAGE_CE).isOk());
}
-TEST_F(ServiceTest, DestroyAppDataSnapshot_WrongVolumeUuid) {
+TEST_F(AppDataSnapshotTest, DestroyAppDataSnapshot_WrongVolumeUuid) {
// Setup rollback data to make sure that test fails due to wrong volumeUuid
// being passed, not because of some other reason.
- auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0);
- auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0);
+ auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0, 43);
+ auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0, 43);
- ASSERT_TRUE(mkdirs(rollback_ce_dir, 700));
- ASSERT_TRUE(mkdirs(rollback_de_dir, 700));
-
- auto fake_package_ce_path = create_data_user_ce_package_path("TEST", 0, "com.foo");
- auto fake_package_de_path = create_data_user_de_package_path("TEST", 0, "com.foo");
-
- ASSERT_TRUE(mkdirs(fake_package_ce_path, 700));
- ASSERT_TRUE(mkdirs(fake_package_de_path, 700));
-
- auto deleter = [&rollback_ce_dir, &rollback_de_dir,
- &fake_package_ce_path, &fake_package_de_path]() {
- delete_dir_contents(rollback_ce_dir, true);
- delete_dir_contents(rollback_de_dir, true);
- delete_dir_contents(fake_package_ce_path, true);
- delete_dir_contents(fake_package_de_path, true);
- rmdir(rollback_ce_dir.c_str());
- rmdir(rollback_de_dir.c_str());
- };
- auto scope_guard = android::base::make_scope_guard(deleter);
+ ASSERT_TRUE(mkdirs(rollback_ce_dir, 0700));
+ ASSERT_TRUE(mkdirs(rollback_de_dir, 0700));
ASSERT_FALSE(service->destroyAppDataSnapshot(std::make_unique<std::string>("BAR"),
- "com.foo", 0, 0, FLAG_STORAGE_DE).isOk());
+ "com.foo", 0, 0, 43, FLAG_STORAGE_DE).isOk());
}
-TEST_F(ServiceTest, RestoreAppDataSnapshot_WrongVolumeUuid) {
+TEST_F(AppDataSnapshotTest, RestoreAppDataSnapshot_WrongVolumeUuid) {
// Setup rollback data to make sure that fails due to wrong volumeUuid being
// passed, not because of some other reason.
- auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0);
- auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0);
+ auto rollback_ce_dir = create_data_misc_ce_rollback_path("TEST", 0, 41);
+ auto rollback_de_dir = create_data_misc_de_rollback_path("TEST", 0, 41);
- ASSERT_TRUE(mkdirs(rollback_ce_dir, 700));
- ASSERT_TRUE(mkdirs(rollback_de_dir, 700));
-
- auto fake_package_ce_path = create_data_user_ce_package_path("TEST", 0, "com.foo");
- auto fake_package_de_path = create_data_user_de_package_path("TEST", 0, "com.foo");
-
- ASSERT_TRUE(mkdirs(fake_package_ce_path, 700));
- ASSERT_TRUE(mkdirs(fake_package_de_path, 700));
-
- auto deleter = [&rollback_ce_dir, &rollback_de_dir,
- &fake_package_ce_path, &fake_package_de_path]() {
- delete_dir_contents(rollback_ce_dir, true);
- delete_dir_contents(rollback_de_dir, true);
- delete_dir_contents(fake_package_ce_path, true);
- delete_dir_contents(fake_package_de_path, true);
- rmdir(rollback_ce_dir.c_str());
- rmdir(rollback_de_dir.c_str());
- };
- auto scope_guard = android::base::make_scope_guard(deleter);
+ ASSERT_TRUE(mkdirs(rollback_ce_dir, 0700));
+ ASSERT_TRUE(mkdirs(rollback_de_dir, 0700));
EXPECT_BINDER_FAIL(service->restoreAppDataSnapshot(std::make_unique<std::string>("BAR"),
- "com.foo", 10000, -1, "", 0, FLAG_STORAGE_DE));
+ "com.foo", 10000, "", 0, 41, FLAG_STORAGE_DE));
}
} // namespace installd
diff --git a/cmds/installd/tests/installd_utils_test.cpp b/cmds/installd/tests/installd_utils_test.cpp
index 1782aa2..e61eb6e 100644
--- a/cmds/installd/tests/installd_utils_test.cpp
+++ b/cmds/installd/tests/installd_utils_test.cpp
@@ -546,56 +546,86 @@
}
TEST_F(UtilsTest, TestRollbackPaths) {
- EXPECT_EQ("/data/misc_ce/0/rollback/com.foo",
- create_data_misc_ce_rollback_package_path(nullptr, 0, "com.foo"));
- EXPECT_EQ("/data/misc_ce/10/rollback/com.foo",
- create_data_misc_ce_rollback_package_path(nullptr, 10, "com.foo"));
+ EXPECT_EQ("/data/misc_ce/0/rollback/239/com.foo",
+ create_data_misc_ce_rollback_package_path(nullptr, 0, 239, "com.foo"));
+ EXPECT_EQ("/data/misc_ce/10/rollback/37/com.foo",
+ create_data_misc_ce_rollback_package_path(nullptr, 10, 37, "com.foo"));
- EXPECT_EQ("/data/misc_de/0/rollback/com.foo",
- create_data_misc_de_rollback_package_path(nullptr, 0, "com.foo"));
- EXPECT_EQ("/data/misc_de/10/rollback/com.foo",
- create_data_misc_de_rollback_package_path(nullptr, 10, "com.foo"));
+ EXPECT_EQ("/data/misc_de/0/rollback/73/com.foo",
+ create_data_misc_de_rollback_package_path(nullptr, 0, 73, "com.foo"));
+ EXPECT_EQ("/data/misc_de/10/rollback/13/com.foo",
+ create_data_misc_de_rollback_package_path(nullptr, 10, 13, "com.foo"));
- EXPECT_EQ("/data/misc_ce/0/rollback",
- create_data_misc_ce_rollback_path(nullptr, 0));
- EXPECT_EQ("/data/misc_ce/10/rollback",
- create_data_misc_ce_rollback_path(nullptr, 10));
+ EXPECT_EQ("/data/misc_ce/0/rollback/57",
+ create_data_misc_ce_rollback_path(nullptr, 0, 57));
+ EXPECT_EQ("/data/misc_ce/10/rollback/1543",
+ create_data_misc_ce_rollback_path(nullptr, 10, 1543));
- EXPECT_EQ("/data/misc_de/0/rollback",
- create_data_misc_de_rollback_path(nullptr, 0));
- EXPECT_EQ("/data/misc_de/10/rollback",
- create_data_misc_de_rollback_path(nullptr, 10));
+ EXPECT_EQ("/data/misc_de/0/rollback/43",
+ create_data_misc_de_rollback_path(nullptr, 0, 43));
+ EXPECT_EQ("/data/misc_de/10/rollback/41",
+ create_data_misc_de_rollback_path(nullptr, 10, 41));
- EXPECT_EQ("/data/misc_ce/0/rollback/com.foo",
- create_data_misc_ce_rollback_package_path(nullptr, 0, "com.foo", 0));
- EXPECT_EQ("/data/misc_ce/0/rollback/com.foo",
- create_data_misc_ce_rollback_package_path(nullptr, 0, "com.foo", 239));
+ EXPECT_EQ("/data/misc_ce/0/rollback/17/com.foo",
+ create_data_misc_ce_rollback_package_path(nullptr, 0, 17, "com.foo", 0));
+ EXPECT_EQ("/data/misc_ce/0/rollback/19/com.foo",
+ create_data_misc_ce_rollback_package_path(nullptr, 0, 19, "com.foo", 239));
- auto rollback_ce_package_path = create_data_misc_ce_rollback_package_path(nullptr, 0, "com.foo");
- auto deleter = [&rollback_ce_package_path]() {
- delete_dir_contents_and_dir(rollback_ce_package_path, true /* ignore_if_missing */);
+ auto rollback_ce_path = create_data_misc_ce_rollback_path(nullptr, 0, 53);
+ auto rollback_ce_package_path = create_data_misc_ce_rollback_package_path(nullptr, 0, 53,
+ "com.foo");
+ auto deleter = [&rollback_ce_path]() {
+ delete_dir_contents_and_dir(rollback_ce_path, true /* ignore_if_missing */);
};
auto scope_guard = android::base::make_scope_guard(deleter);
- ASSERT_NE(-1, mkdir(rollback_ce_package_path.c_str(), 700));
+ EXPECT_NE(-1, mkdir(rollback_ce_path.c_str(), 700));
+ EXPECT_NE(-1, mkdir(rollback_ce_package_path.c_str(), 700));
ino_t ce_data_inode;
- ASSERT_EQ(0, get_path_inode(rollback_ce_package_path, &ce_data_inode));
+ EXPECT_EQ(0, get_path_inode(rollback_ce_package_path, &ce_data_inode));
- EXPECT_EQ("/data/misc_ce/0/rollback/com.foo",
- create_data_misc_ce_rollback_package_path(nullptr, 0, "com.foo", ce_data_inode));
+ EXPECT_EQ("/data/misc_ce/0/rollback/53/com.foo",
+ create_data_misc_ce_rollback_package_path(nullptr, 0, 53, "com.foo", ce_data_inode));
// Check that path defined by inode is picked even if it's not the same as
// the fallback one.
- EXPECT_EQ("/data/misc_ce/0/rollback/com.foo",
- create_data_misc_ce_rollback_package_path(nullptr, 0, "com.bar", ce_data_inode));
+ EXPECT_EQ("/data/misc_ce/0/rollback/53/com.foo",
+ create_data_misc_ce_rollback_package_path(nullptr, 0, 53, "com.bar", ce_data_inode));
// These last couple of cases are never exercised in production because we
// only snapshot apps in the primary data partition. Exercise them here for
// the sake of completeness.
- EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/misc_ce/0/rollback/com.example",
- create_data_misc_ce_rollback_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 0, "com.example"));
- EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/misc_de/0/rollback/com.example",
- create_data_misc_de_rollback_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 0, "com.example"));
+ EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/misc_ce/0/rollback/7/com.example",
+ create_data_misc_ce_rollback_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 0, 7,
+ "com.example"));
+ EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/misc_de/0/rollback/11/com.example",
+ create_data_misc_de_rollback_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 0, 11,
+ "com.example"));
+}
+
+TEST_F(UtilsTest, TestCreateDirIfNeeded) {
+ system("mkdir -p /data/local/tmp/user/0");
+
+ auto deleter = [&]() {
+ delete_dir_contents_and_dir("/data/local/tmp/user/0", true /* ignore_if_missing */);
+ };
+ auto scope_guard = android::base::make_scope_guard(deleter);
+
+ // Create folder and check it's permissions.
+ ASSERT_EQ(0, create_dir_if_needed("/data/local/tmp/user/0/foo", 0700));
+ struct stat st;
+ ASSERT_EQ(0, stat("/data/local/tmp/user/0/foo", &st));
+ ASSERT_EQ(0700, st.st_mode & ALLPERMS);
+
+ // Check that create_dir_if_needed is no-op if folder already exists with
+ // correct permissions.
+ ASSERT_EQ(0, create_dir_if_needed("/data/local/tmp/user/0/foo", 0700));
+
+ // Check -1 is returned if folder exists but with different permissions.
+ ASSERT_EQ(-1, create_dir_if_needed("/data/local/tmp/user/0/foo", 0750));
+
+ // Check that call fails if parent doesn't exist.
+ ASSERT_NE(0, create_dir_if_needed("/data/local/tmp/user/0/bar/baz", 0700));
}
} // namespace installd
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index 5b487bb..52ca0df 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -197,32 +197,44 @@
return StringPrintf("%s/user_de/%u", data.c_str(), userid);
}
-
-std::string create_data_misc_ce_rollback_path(const char* volume_uuid, userid_t user) {
+std::string create_data_misc_ce_rollback_base_path(const char* volume_uuid, userid_t user) {
return StringPrintf("%s/misc_ce/%u/rollback", create_data_path(volume_uuid).c_str(), user);
}
-std::string create_data_misc_de_rollback_path(const char* volume_uuid, userid_t user) {
+std::string create_data_misc_de_rollback_base_path(const char* volume_uuid, userid_t user) {
return StringPrintf("%s/misc_de/%u/rollback", create_data_path(volume_uuid).c_str(), user);
}
-std::string create_data_misc_ce_rollback_package_path(const char* volume_uuid,
- userid_t user, const char* package_name) {
- return StringPrintf("%s/%s",
- create_data_misc_ce_rollback_path(volume_uuid, user).c_str(), package_name);
+std::string create_data_misc_ce_rollback_path(const char* volume_uuid, userid_t user,
+ int32_t snapshot_id) {
+ return StringPrintf("%s/%d", create_data_misc_ce_rollback_base_path(volume_uuid, user).c_str(),
+ snapshot_id);
+}
+
+std::string create_data_misc_de_rollback_path(const char* volume_uuid, userid_t user,
+ int32_t snapshot_id) {
+ return StringPrintf("%s/%d", create_data_misc_de_rollback_base_path(volume_uuid, user).c_str(),
+ snapshot_id);
}
std::string create_data_misc_ce_rollback_package_path(const char* volume_uuid,
- userid_t user, const char* package_name, ino_t ce_rollback_inode) {
- auto fallback = create_data_misc_ce_rollback_package_path(volume_uuid, user, package_name);
- auto user_path = create_data_misc_ce_rollback_path(volume_uuid, user);
+ userid_t user, int32_t snapshot_id, const char* package_name) {
+ return StringPrintf("%s/%s",
+ create_data_misc_ce_rollback_path(volume_uuid, user, snapshot_id).c_str(), package_name);
+}
+
+std::string create_data_misc_ce_rollback_package_path(const char* volume_uuid,
+ userid_t user, int32_t snapshot_id, const char* package_name, ino_t ce_rollback_inode) {
+ auto fallback = create_data_misc_ce_rollback_package_path(volume_uuid, user, snapshot_id,
+ package_name);
+ auto user_path = create_data_misc_ce_rollback_path(volume_uuid, user, snapshot_id);
return resolve_ce_path_by_inode_or_fallback(user_path, ce_rollback_inode, fallback);
}
std::string create_data_misc_de_rollback_package_path(const char* volume_uuid,
- userid_t user, const char* package_name) {
+ userid_t user, int32_t snapshot_id, const char* package_name) {
return StringPrintf("%s/%s",
- create_data_misc_de_rollback_path(volume_uuid, user).c_str(), package_name);
+ create_data_misc_de_rollback_path(volume_uuid, user, snapshot_id).c_str(), package_name);
}
/**
@@ -528,6 +540,30 @@
return result;
}
+int create_dir_if_needed(const std::string& pathname, mode_t perms) {
+ struct stat st;
+
+ int rc;
+ if ((rc = stat(pathname.c_str(), &st)) != 0) {
+ if (errno == ENOENT) {
+ return mkdir(pathname.c_str(), perms);
+ } else {
+ return rc;
+ }
+ } else if (!S_ISDIR(st.st_mode)) {
+ LOG(DEBUG) << pathname << " is not a folder";
+ return -1;
+ }
+
+ mode_t actual_perms = st.st_mode & ALLPERMS;
+ if (actual_perms != perms) {
+ LOG(WARNING) << pathname << " permissions " << actual_perms << " expected " << perms;
+ return -1;
+ }
+
+ return 0;
+}
+
int delete_dir_contents(const std::string& pathname, bool ignore_if_missing) {
return delete_dir_contents(pathname.c_str(), 0, nullptr, ignore_if_missing);
}
diff --git a/cmds/installd/utils.h b/cmds/installd/utils.h
index 5d3a97d..91d9e13 100644
--- a/cmds/installd/utils.h
+++ b/cmds/installd/utils.h
@@ -61,14 +61,18 @@
std::string create_data_user_ce_package_path_as_user_link(
const char* volume_uuid, userid_t userid, const char* package_name);
-std::string create_data_misc_ce_rollback_path(const char* volume_uuid, userid_t user);
-std::string create_data_misc_de_rollback_path(const char* volume_uuid, userid_t user);
+std::string create_data_misc_ce_rollback_base_path(const char* volume_uuid, userid_t user);
+std::string create_data_misc_de_rollback_base_path(const char* volume_uuid, userid_t user);
+std::string create_data_misc_ce_rollback_path(const char* volume_uuid, userid_t user,
+ int32_t snapshot_id);
+std::string create_data_misc_de_rollback_path(const char* volume_uuid, userid_t user,
+ int32_t snapshot_id);
std::string create_data_misc_ce_rollback_package_path(const char* volume_uuid,
- userid_t user, const char* package_name);
+ userid_t user, int32_t snapshot_id, const char* package_name);
std::string create_data_misc_ce_rollback_package_path(const char* volume_uuid,
- userid_t user, const char* package_name, ino_t ce_rollback_inode);
+ userid_t user, int32_t snapshot_id, const char* package_name, ino_t ce_rollback_inode);
std::string create_data_misc_de_rollback_package_path(const char* volume_uuid,
- userid_t user, const char* package_name);
+ userid_t user, int32_t snapshot_id, const char* package_name);
std::string create_data_media_path(const char* volume_uuid, userid_t userid);
std::string create_data_media_obb_path(const char* volume_uuid, const char* package_name);
@@ -109,6 +113,8 @@
bool is_valid_filename(const std::string& name);
bool is_valid_package_name(const std::string& packageName);
+int create_dir_if_needed(const std::string& pathname, mode_t mode);
+
int delete_dir_contents(const std::string& pathname, bool ignore_if_missing = false);
int delete_dir_contents_and_dir(const std::string& pathname, bool ignore_if_missing = false);