diff options
| -rw-r--r-- | cmds/installd/InstalldNativeService.cpp | 39 | ||||
| -rw-r--r-- | cmds/installd/InstalldNativeService.h | 2 | ||||
| -rw-r--r-- | cmds/installd/binder/android/os/IInstalld.aidl | 3 | ||||
| -rw-r--r-- | cmds/installd/tests/installd_service_test.cpp | 40 |
4 files changed, 84 insertions, 0 deletions
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp index c9b51b597f..ae44d38ae1 100644 --- a/cmds/installd/InstalldNativeService.cpp +++ b/cmds/installd/InstalldNativeService.cpp @@ -42,6 +42,7 @@ #include <android-base/file.h> #include <android-base/logging.h> +#include <android-base/parseint.h> #include <android-base/properties.h> #include <android-base/scopeguard.h> #include <android-base/stringprintf.h> @@ -75,6 +76,7 @@ #define LOG_TAG "installd" #endif +using android::base::ParseUint; using android::base::StringPrintf; using std::endl; @@ -1101,6 +1103,43 @@ binder::Status InstalldNativeService::destroyAppDataSnapshot( return ok(); } +binder::Status InstalldNativeService::destroyCeSnapshotsNotSpecified( + const std::unique_ptr<std::string> &volumeUuid, const int32_t userId, + const std::vector<int32_t>& retainSnapshotIds) { + ENFORCE_UID(AID_SYSTEM); + CHECK_ARGUMENT_UUID_IS_TEST_OR_NULL(volumeUuid); + std::lock_guard<std::recursive_mutex> lock(mLock); + + const char* volume_uuid = volumeUuid ? volumeUuid->c_str() : nullptr; + + auto base_path = create_data_misc_ce_rollback_base_path(volume_uuid, userId); + + std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(base_path.c_str()), closedir); + if (!dir) { + return error(-1, "Failed to open rollback base dir " + base_path); + } + + struct dirent* ent; + while ((ent = readdir(dir.get()))) { + if (ent->d_type != DT_DIR) { + continue; + } + + uint snapshot_id; + bool parse_ok = ParseUint(ent->d_name, &snapshot_id); + if (parse_ok && + std::find(retainSnapshotIds.begin(), retainSnapshotIds.end(), + snapshot_id) == retainSnapshotIds.end()) { + auto rollback_path = create_data_misc_ce_rollback_path( + volume_uuid, userId, snapshot_id); + int res = delete_dir_contents_and_dir(rollback_path, true /* ignore_if_missing */); + if (res != 0) { + return error(res, "Failed clearing snapshot " + rollback_path); + } + } + } + return ok(); +} binder::Status InstalldNativeService::moveCompleteApp(const std::unique_ptr<std::string>& fromUuid, const std::unique_ptr<std::string>& toUuid, const std::string& packageName, diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h index df01c3ca85..eb151ca135 100644 --- a/cmds/installd/InstalldNativeService.h +++ b/cmds/installd/InstalldNativeService.h @@ -69,6 +69,8 @@ public: binder::Status destroyAppDataSnapshot(const std::unique_ptr<std::string> &volumeUuid, const std::string& packageName, const int32_t user, const int64_t ceSnapshotInode, const int32_t snapshotId, int32_t storageFlags); + binder::Status destroyCeSnapshotsNotSpecified(const std::unique_ptr<std::string> &volumeUuid, + const int32_t userId, const std::vector<int32_t>& retainSnapshotIds); 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 ca95cb3f9d..5e5af73624 100644 --- a/cmds/installd/binder/android/os/IInstalld.aidl +++ b/cmds/installd/binder/android/os/IInstalld.aidl @@ -116,6 +116,9 @@ interface IInstalld { 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 snapshotId, int storageFlags); + void destroyCeSnapshotsNotSpecified(@nullable @utf8InCpp String uuid, int userId, + in int[] retainSnapshotIds); + void tryMountDataMirror(@nullable @utf8InCpp String volumeUuid); void onPrivateVolumeRemoved(@nullable @utf8InCpp String volumeUuid); diff --git a/cmds/installd/tests/installd_service_test.cpp b/cmds/installd/tests/installd_service_test.cpp index a31d510565..0fb62ae9bf 100644 --- a/cmds/installd/tests/installd_service_test.cpp +++ b/cmds/installd/tests/installd_service_test.cpp @@ -641,6 +641,46 @@ TEST_F(AppDataSnapshotTest, DestroyAppDataSnapshot_WrongVolumeUuid) { "com.foo", 0, 0, 43, FLAG_STORAGE_DE).isOk()); } +TEST_F(AppDataSnapshotTest, DestroyCeSnapshotsNotSpecified) { + auto rollback_ce_dir_in_1 = create_data_misc_ce_rollback_path("TEST", 0, 1543); + auto rollback_ce_dir_in_2 = create_data_misc_ce_rollback_path("TEST", 0, 77); + auto rollback_ce_dir_out_1 = create_data_misc_ce_rollback_path("TEST", 0, 1500); + auto rollback_ce_dir_out_2 = create_data_misc_ce_rollback_path("TEST", 0, 2); + + // Create snapshots + ASSERT_TRUE(mkdirs(rollback_ce_dir_in_1 + "/com.foo/", 0700)); + ASSERT_TRUE(android::base::WriteStringToFile( + "CE_RESTORE_CONTENT", rollback_ce_dir_in_1 + "/com.foo/file1", + 0700, 10000, 20000, false /* follow_symlinks */)); + + ASSERT_TRUE(mkdirs(rollback_ce_dir_in_2 + "/com.foo/", 0700)); + ASSERT_TRUE(android::base::WriteStringToFile( + "CE_RESTORE_CONTENT", rollback_ce_dir_in_2 + "/com.foo/file1", + 0700, 10000, 20000, false /* follow_symlinks */)); + + ASSERT_TRUE(mkdirs(rollback_ce_dir_out_1 + "/com.foo/", 0700)); + ASSERT_TRUE(android::base::WriteStringToFile( + "CE_RESTORE_CONTENT", rollback_ce_dir_out_1 + "/com.foo/file1", + 0700, 10000, 20000, false /* follow_symlinks */)); + + ASSERT_TRUE(mkdirs(rollback_ce_dir_out_2 + "/com.foo/", 0700)); + ASSERT_TRUE(android::base::WriteStringToFile( + "CE_RESTORE_CONTENT", rollback_ce_dir_out_2 + "/com.foo/file1", + 0700, 10000, 20000, false /* follow_symlinks */)); + + ASSERT_TRUE(service->destroyCeSnapshotsNotSpecified( + std::make_unique<std::string>("TEST"), 0, { 1543, 77 }).isOk()); + + // Check only snapshots not specified are deleted. + struct stat sb; + ASSERT_EQ(0, stat((rollback_ce_dir_in_1 + "/com.foo").c_str(), &sb)); + ASSERT_EQ(0, stat((rollback_ce_dir_in_2 + "/com.foo").c_str(), &sb)); + ASSERT_EQ(-1, stat((rollback_ce_dir_out_1 + "/com.foo").c_str(), &sb)); + ASSERT_EQ(ENOENT, errno); + ASSERT_EQ(-1, stat((rollback_ce_dir_out_2 + "/com.foo").c_str(), &sb)); + ASSERT_EQ(ENOENT, errno); +} + 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. |