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

Commit a2cc739a authored by Daeho Jeong's avatar Daeho Jeong
Browse files

Truncate the given userdata_exp alias partition



Given userdata.alias.remove prop by vendors, userdata_alias_remove service
will truncate the below file for giving back the space to userdata. The
target file names should exactly match with one of alias file names in
userdata.alias.devices created by fs_mgr.

/data/${userdata.alias.remove}

Bug: 383008495
Bug: 378120929
Test: trigger file truncation by vendors
Change-Id: Ie0b3c0476893bf5593f01588707568b7c8a102f2
Signed-off-by: default avatarDaeho Jeong <daehojeong@google.com>
parent e0e8d553
Loading
Loading
Loading
Loading
+22 −0
Original line number Diff line number Diff line
@@ -238,3 +238,25 @@ cc_binary {
        "set-verity-state",
    ],
}

cc_binary {
    name: "userdata_alias_remove",
    srcs: [
        "userdata_alias_remove.cpp",
    ],
    header_libs: [
        "libbase_headers",
    ],
    static_libs: [
        "libfstab",
    ],
    shared_libs: [
        "libbase",
    ],
    init_rc: ["userdata.alias.remove.rc"],
    cflags: [
        "-Werror",
        "-Wall",
        "-Wextra",
    ],
}
+15 −1
Original line number Diff line number Diff line
@@ -170,7 +170,21 @@ void ParseUserDevices(const std::string& arg, FstabEntry* entry) {
        entry->fs_mgr_flags.is_zoned = true;
    }
    entry->user_devices.push_back(param[1]);
    entry->device_aliased.push_back(param[0] == "exp_alias" ? 1 : 0);

    if (param[0] == "exp_alias") {
        std::string_view exp_alias_prefix = "userdata_exp.";
        std::string deviceName = android::base::Basename(param[1]);
        if (!android::base::StartsWith(deviceName, exp_alias_prefix)) {
            LERROR << "Device aliasing file " << deviceName << " doesn't start with "
                   << exp_alias_prefix;
            entry->user_devices.pop_back();
            return;
        }

        entry->device_aliased.push_back(1);
    } else {
        entry->device_aliased.push_back(0);
    }
}

bool ParseFsMgrFlags(const std::string& flags, FstabEntry* entry) {
+7 −0
Original line number Diff line number Diff line
# Userdata device aliasing file control service

service userdata_alias_remove /system/bin/userdata_alias_remove
    user root
    group system
    disabled
    oneshot
+66 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * This removes a userdata aliasing file, which maps storage space for
 * a specific purpose to a special-purpose partition, allowing for its
 * later release.
 */

#include <errno.h>
#include <error.h>
#include <stdio.h>

#include <android-base/file.h>
#include <android-base/properties.h>

#include <fstab/fstab.h>

static constexpr const char* ALIAS_REMOVE_PROP_NAME = "userdata.alias.remove";

int main(void) {
    android::fs_mgr::Fstab fstab;
    if (!android::fs_mgr::ReadDefaultFstab(&fstab)) {
        error(1, 0, "no valid fstab");
    }

    android::fs_mgr::FstabEntry* dataEntry =
            android::fs_mgr::GetEntryForMountPoint(&fstab, "/data");
    if (!dataEntry) {
        error(1, 0, "/data is not mounted yet");
    }

    /* Only F2FS supports device aliasing file */
    if (dataEntry->fs_type != "f2fs") {
        return 0;
    }

    std::string target = android::base::GetProperty(ALIAS_REMOVE_PROP_NAME, "");
    for (size_t i = 0; i < dataEntry->user_devices.size(); ++i) {
        if (dataEntry->device_aliased[i]) {
            std::string deviceName = android::base::Basename(dataEntry->user_devices[i]);
            if (target == deviceName) {
                std::string filename = "/data/" + target;
                if (unlink(filename.c_str())) {
                    error(1, errno, "Failed to remove file: %s", filename.c_str());
                }
                return 0;
            }
        }
    }

    error(1, 0, "%s is not a device aliasing file", target.c_str());
}