/*
 * Copyright (C) 2008 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 <ctype.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <fts.h>
#include <poll.h>
#include <pwd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>

#include <fstream>
#include <mntent.h>
#include <unordered_set>

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

#include "Process.h"

using android::base::StringPrintf;

namespace android {
namespace vold {

static bool checkMaps(const std::string& path, const std::string& prefix) {
    bool found = false;
    auto file = std::unique_ptr<FILE, decltype(&fclose)>{fopen(path.c_str(), "re"), fclose};
    if (!file) {
        return false;
    }

    char* buf = nullptr;
    size_t len = 0;
    while (getline(&buf, &len, file.get()) != -1) {
        std::string line(buf);
        std::string::size_type pos = line.find('/');
        if (pos != std::string::npos) {
            line = line.substr(pos);
            if (android::base::StartsWith(line, prefix)) {
                LOG(WARNING) << "Found map " << path << " referencing " << line;
                found = true;
                break;
            }
        }
    }
    free(buf);

    return found;
}

static bool checkSymlink(const std::string& path, const std::string& prefix) {
    std::string res;
    if (android::base::Readlink(path, &res)) {
        if (android::base::StartsWith(res, prefix)) {
            LOG(WARNING) << "Found symlink " << path << " referencing " << res;
            return true;
        }
    }
    return false;
}

// TODO: Refactor the code with KillProcessesWithOpenFiles().
int KillProcessesWithMounts(const std::string& prefix, int signal) {
    std::unordered_set<pid_t> pids;

    auto proc_d = std::unique_ptr<DIR, int (*)(DIR*)>(opendir("/proc"), closedir);
    if (!proc_d) {
        PLOG(ERROR) << "Failed to open proc";
        return -1;
    }

    struct dirent* proc_de;
    while ((proc_de = readdir(proc_d.get())) != nullptr) {
        // We only care about valid PIDs
        pid_t pid;
        if (proc_de->d_type != DT_DIR) continue;
        if (!android::base::ParseInt(proc_de->d_name, &pid)) continue;

        // Look for references to prefix
        std::string mounts_file(StringPrintf("/proc/%d/mounts", pid));
        auto fp = std::unique_ptr<FILE, int (*)(FILE*)>(
                setmntent(mounts_file.c_str(), "r"), endmntent);
        if (!fp) {
            PLOG(WARNING) << "Failed to open " << mounts_file;
            continue;
        }

        // Check if obb directory is mounted, and get all packages of mounted app data directory.
        mntent* mentry;
        while ((mentry = getmntent(fp.get())) != nullptr) {
            if (android::base::StartsWith(mentry->mnt_dir, prefix)) {
                pids.insert(pid);
                break;
            }
        }
    }
    if (signal != 0) {
        for (const auto& pid : pids) {
            LOG(WARNING) << "Killing pid "<< pid << " with signal " << strsignal(signal) <<
                    " because it has a mount with prefix " << prefix;
            kill(pid, signal);
        }
    }
    return pids.size();
}

int KillProcessesWithOpenFiles(const std::string& prefix, int signal) {
    std::unordered_set<pid_t> pids;

    auto proc_d = std::unique_ptr<DIR, int (*)(DIR*)>(opendir("/proc"), closedir);
    if (!proc_d) {
        PLOG(ERROR) << "Failed to open proc";
        return -1;
    }

    struct dirent* proc_de;
    while ((proc_de = readdir(proc_d.get())) != nullptr) {
        // We only care about valid PIDs
        pid_t pid;
        if (proc_de->d_type != DT_DIR) continue;
        if (!android::base::ParseInt(proc_de->d_name, &pid)) continue;

        // Look for references to prefix
        bool found = false;
        auto path = StringPrintf("/proc/%d", pid);
        found |= checkMaps(path + "/maps", prefix);
        found |= checkSymlink(path + "/cwd", prefix);
        found |= checkSymlink(path + "/root", prefix);
        found |= checkSymlink(path + "/exe", prefix);

        auto fd_path = path + "/fd";
        auto fd_d = std::unique_ptr<DIR, int (*)(DIR*)>(opendir(fd_path.c_str()), closedir);
        if (!fd_d) {
            PLOG(WARNING) << "Failed to open " << fd_path;
        } else {
            struct dirent* fd_de;
            while ((fd_de = readdir(fd_d.get())) != nullptr) {
                if (fd_de->d_type != DT_LNK) continue;
                found |= checkSymlink(fd_path + "/" + fd_de->d_name, prefix);
            }
        }

        if (found) {
            pids.insert(pid);
        }
    }
    if (signal != 0) {
        for (const auto& pid : pids) {
            LOG(WARNING) << "Sending " << strsignal(signal) << " to " << pid;
            kill(pid, signal);
        }
    }
    return pids.size();
}

}  // namespace vold
}  // namespace android
