Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4ce8b0dd authored by Oli Lan's avatar Oli Lan Committed by Gerrit Code Review
Browse files

Merge "Add installd method to delete CE snapshots."

parents 4a24272a 035abbb1
Loading
Loading
Loading
Loading
+39 −0
Original line number Diff line number Diff line
@@ -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>
@@ -74,6 +75,7 @@
#define LOG_TAG "installd"
#endif

using android::base::ParseUint;
using android::base::StringPrintf;
using std::endl;

@@ -1090,6 +1092,43 @@ binder::Status InstalldNativeService::destroyAppDataSnapshot(
    return ok();
}

binder::Status InstalldNativeService::destroyCeSnapshotsNotSpecified(
        const std::optional<std::string> &volumeUuid, const int32_t user,
        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, user);

    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, user, 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::optional<std::string>& fromUuid,
        const std::optional<std::string>& toUuid, const std::string& packageName,
+2 −0
Original line number Diff line number Diff line
@@ -69,6 +69,8 @@ public:
    binder::Status destroyAppDataSnapshot(const std::optional<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::optional<std::string> &volumeUuid,
            const int32_t user, const std::vector<int32_t>& retainSnapshotIds);

    binder::Status getAppSize(const std::optional<std::string>& uuid,
            const std::vector<std::string>& packageNames, int32_t userId, int32_t flags,
+2 −0
Original line number Diff line number Diff line
@@ -109,6 +109,8 @@ interface IInstalld {
            int userId, int snapshotId, int storageFlags);
    void restoreAppDataSnapshot(@nullable @utf8InCpp String uuid, in @utf8InCpp String packageName,
            int appId, @utf8InCpp String seInfo, int user, int snapshotId, int storageflags);
    void destroyCeSnapshotsNotSpecified(@nullable @utf8InCpp String uuid, int userId,
            in int[] retainSnapshotIds);
    void destroyAppDataSnapshot(@nullable @utf8InCpp String uuid, @utf8InCpp String packageName,
            int userId, long ceSnapshotInode, int snapshotId, int storageFlags);

+40 −0
Original line number Diff line number Diff line
@@ -640,6 +640,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_optional<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.