/*
 * Copyright (C) 2019 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.
 */

#include "utility.h"

#include <stdint.h>
#include <sys/stat.h>
#include <sys/sysmacros.h>
#include <sys/types.h>
#include <sys/vfs.h>
#include <unistd.h>

#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <libfiemap/fiemap_writer.h>

namespace android {
namespace fiemap {

using namespace std::string_literals;
using android::base::unique_fd;

static constexpr char kUserdataDevice[] = "/dev/block/by-name/userdata";

FiemapStatus DetermineMaximumFileSize(const std::string& file_path, uint64_t* result) {
    // Create the smallest file possible (one block).
    FiemapUniquePtr writer;
    auto status = FiemapWriter::Open(file_path, 1, &writer);
    if (!status.is_ok()) {
        return status;
    }

    *result = 0;
    switch (writer->fs_type()) {
        case EXT4_SUPER_MAGIC:
            // The minimum is 16GiB, so just report that. If we wanted we could parse the
            // superblock and figure out if 64-bit support is enabled.
            *result = 17179869184ULL;
            break;
        case F2FS_SUPER_MAGIC:
            // Formula is from https://www.kernel.org/doc/Documentation/filesystems/f2fs.txt
            // 4KB * (923 + 2 * 1018 + 2 * 1018 * 1018 + 1018 * 1018 * 1018) := 3.94TB.
            *result = 4329690886144ULL;
            break;
        case MSDOS_SUPER_MAGIC:
            // 4GB-1, which we want aligned to the block size.
            *result = 4294967295;
            *result -= (*result % writer->block_size());
            break;
        default:
            LOG(ERROR) << "Unknown file system type: " << writer->fs_type();
            break;
    }

    // Close and delete the temporary file.
    writer = nullptr;
    unlink(file_path.c_str());

    return FiemapStatus::Ok();
}

// Given a SplitFiemap, this returns a device path that will work during first-
// stage init (i.e., its path can be found by InitRequiredDevices).
std::string GetDevicePathForFile(SplitFiemap* file) {
    auto bdev_path = file->bdev_path();

    struct stat userdata, given;
    if (!stat(bdev_path.c_str(), &given) && !stat(kUserdataDevice, &userdata)) {
        if (S_ISBLK(given.st_mode) && S_ISBLK(userdata.st_mode) &&
            given.st_rdev == userdata.st_rdev) {
            return kUserdataDevice;
        }
    }
    return bdev_path;
}

std::string JoinPaths(const std::string& dir, const std::string& file) {
    if (android::base::EndsWith(dir, "/")) {
        return dir + file;
    }
    return dir + "/" + file;
}

bool F2fsPinBeforeAllocate(int file_fd, bool* supported) {
    struct stat st;
    if (fstat(file_fd, &st) < 0) {
        PLOG(ERROR) << "stat failed";
        return false;
    }
    std::string bdev;
    if (!BlockDeviceToName(major(st.st_dev), minor(st.st_dev), &bdev)) {
        LOG(ERROR) << "Failed to get block device name for " << major(st.st_dev) << ":"
                   << minor(st.st_dev);
        return false;
    }

    std::string contents;
    std::string feature_file = "/sys/fs/f2fs/" + bdev + "/features";
    if (!android::base::ReadFileToString(feature_file, &contents)) {
        PLOG(ERROR) << "read failed: " << feature_file;
        return false;
    }
    contents = android::base::Trim(contents);

    auto features = android::base::Split(contents, ", ");
    auto iter = std::find(features.begin(), features.end(), "pin_file"s);
    *supported = (iter != features.end());
    return true;
}

bool BlockDeviceToName(uint32_t major, uint32_t minor, std::string* bdev_name) {
    // The symlinks in /sys/dev/block point to the block device node under /sys/device/..
    // The directory name in the target corresponds to the name of the block device. We use
    // that to extract the block device name.
    // e.g for block device name 'ram0', there exists a symlink named '1:0' in /sys/dev/block as
    // follows.
    //    1:0 -> ../../devices/virtual/block/ram0
    std::string sysfs_path = ::android::base::StringPrintf("/sys/dev/block/%u:%u", major, minor);
    std::string sysfs_bdev;

    if (!::android::base::Readlink(sysfs_path, &sysfs_bdev)) {
        PLOG(ERROR) << "Failed to read link at: " << sysfs_path;
        return false;
    }

    *bdev_name = ::android::base::Basename(sysfs_bdev);
    // Check that the symlink doesn't point to itself.
    if (sysfs_bdev == *bdev_name) {
        LOG(ERROR) << "Malformed symlink for block device: " << sysfs_bdev;
        return false;
    }

    return true;
}

bool FilesystemHasReliablePinning(const std::string& file, bool* supported) {
    struct statfs64 sfs;
    if (statfs64(file.c_str(), &sfs)) {
        PLOG(ERROR) << "statfs failed: " << file;
        return false;
    }
    if (sfs.f_type != F2FS_SUPER_MAGIC) {
        *supported = true;
        return true;
    }

    unique_fd fd(open(file.c_str(), O_RDONLY | O_CLOEXEC));
    if (fd < 0) {
        PLOG(ERROR) << "open failed: " << file;
        return false;
    }
    return F2fsPinBeforeAllocate(fd, supported);
}

bool IsSubdir(const std::string& child, const std::string& parent) {
    // Precondition: both are absolute paths.
    CHECK(android::base::StartsWith(child, "/")) << "Not an absolute path: " << child;
    CHECK(android::base::StartsWith(parent, "/")) << "Not an absolute path: " << parent;

    // Remove extraneous "/" at the end.
    std::string_view child_sv = child;
    while (child_sv != "/" && android::base::ConsumeSuffix(&child_sv, "/"))
        ;

    std::string_view parent_sv = parent;
    while (parent_sv != "/" && android::base::ConsumeSuffix(&parent_sv, "/"))
        ;

    // IsSubdir(anything, "/") => true
    if (parent_sv == "/") return true;

    // IsSubdir("/foo", "/foo") => true
    if (parent_sv == child_sv) return true;

    // IsSubdir("/foo/bar", "/foo") => true
    // IsSubdir("/foo-bar", "/foo") => false
    return android::base::StartsWith(child_sv, std::string(parent_sv) + "/");
}

}  // namespace fiemap
}  // namespace android
