/*
 * Copyright (C) 2015 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 "MoveTask.h"
#include "Utils.h"
#include "VolumeManager.h"
#include "ResponseCode.h"

#include <base/stringprintf.h>
#include <base/logging.h>
#include <private/android_filesystem_config.h>

#include <dirent.h>
#include <sys/wait.h>

#define CONSTRAIN(amount, low, high) (amount < low ? low : (amount > high ? high : amount))

using android::base::StringPrintf;

namespace android {
namespace vold {

// TODO: keep in sync with PackageManager
static const int kMoveSucceeded = -100;
static const int kMoveFailedInternalError = -6;

static const char* kCpPath = "/system/bin/cp";
static const char* kRmPath = "/system/bin/rm";

MoveTask::MoveTask(const std::shared_ptr<VolumeBase>& from,
        const std::shared_ptr<VolumeBase>& to) :
        mFrom(from), mTo(to) {
}

MoveTask::~MoveTask() {
}

void MoveTask::start() {
    mThread = std::thread(&MoveTask::run, this);
}

static void notifyProgress(int progress) {
    VolumeManager::Instance()->getBroadcaster()->sendBroadcast(ResponseCode::MoveStatus,
            StringPrintf("%d", progress).c_str(), false);
}

static status_t pushBackContents(const std::string& path, std::vector<std::string>& cmd) {
    DIR* dir = opendir(path.c_str());
    if (dir == NULL) {
        return -1;
    }
    bool found = false;
    struct dirent* ent;
    while ((ent = readdir(dir)) != NULL) {
        if ((!strcmp(ent->d_name, ".")) || (!strcmp(ent->d_name, ".."))) {
            continue;
        }
        cmd.push_back(StringPrintf("%s/%s", path.c_str(), ent->d_name));
        found = true;
    }
    closedir(dir);
    return found ? OK : -1;
}

static status_t execRm(const std::string& path, int startProgress, int stepProgress) {
    notifyProgress(startProgress);

    uint64_t expectedBytes = GetTreeBytes(path);
    uint64_t startFreeBytes = GetFreeBytes(path);

    std::vector<std::string> cmd;
    cmd.push_back(kRmPath);
    cmd.push_back("-f"); /* force: remove without confirmation, no error if it doesn't exist */
    cmd.push_back("-R"); /* recursive: remove directory contents */
    if (pushBackContents(path, cmd) != OK) {
        LOG(WARNING) << "No contents in " << path;
        return OK;
    }

    pid_t pid = ForkExecvpAsync(cmd);
    if (pid == -1) return -1;

    int status;
    while (true) {
        if (waitpid(pid, &status, WNOHANG) == pid) {
            if (WIFEXITED(status)) {
                LOG(DEBUG) << "Finished rm with status " << WEXITSTATUS(status);
                return (WEXITSTATUS(status) == 0) ? OK : -1;
            } else {
                break;
            }
        }

        sleep(1);
        uint64_t deltaFreeBytes = GetFreeBytes(path) - startFreeBytes;
        notifyProgress(startProgress + CONSTRAIN((int)
                ((deltaFreeBytes * stepProgress) / expectedBytes), 0, stepProgress));
    }
    return -1;
}

static status_t execCp(const std::string& fromPath, const std::string& toPath,
        int startProgress, int stepProgress) {
    notifyProgress(startProgress);

    uint64_t expectedBytes = GetTreeBytes(fromPath);
    uint64_t startFreeBytes = GetFreeBytes(toPath);

    std::vector<std::string> cmd;
    cmd.push_back(kCpPath);
    cmd.push_back("-p"); /* preserve timestamps, ownership, and permissions */
    cmd.push_back("-R"); /* recurse into subdirectories (DEST must be a directory) */
    cmd.push_back("-P"); /* Do not follow symlinks [default] */
    cmd.push_back("-d"); /* don't dereference symlinks */
    if (pushBackContents(fromPath, cmd) != OK) {
        LOG(WARNING) << "No contents in " << fromPath;
        return OK;
    }
    cmd.push_back(toPath.c_str());

    pid_t pid = ForkExecvpAsync(cmd);
    if (pid == -1) return -1;

    int status;
    while (true) {
        if (waitpid(pid, &status, WNOHANG) == pid) {
            if (WIFEXITED(status)) {
                LOG(DEBUG) << "Finished cp with status " << WEXITSTATUS(status);
                return (WEXITSTATUS(status) == 0) ? OK : -1;
            } else {
                break;
            }
        }

        sleep(1);
        uint64_t deltaFreeBytes = startFreeBytes - GetFreeBytes(toPath);
        notifyProgress(startProgress + CONSTRAIN((int)
                ((deltaFreeBytes * stepProgress) / expectedBytes), 0, stepProgress));
    }
    return -1;
}

static void bringOffline(const std::shared_ptr<VolumeBase>& vol) {
    vol->destroy();
    vol->setSilent(true);
    vol->create();
    vol->setMountFlags(0);
    vol->mount();
}

static void bringOnline(const std::shared_ptr<VolumeBase>& vol) {
    vol->destroy();
    vol->setSilent(false);
    vol->create();
}

void MoveTask::run() {
    std::string fromPath;
    std::string toPath;

    // TODO: add support for public volumes
    if (mFrom->getType() != VolumeBase::Type::kEmulated) goto fail;
    if (mTo->getType() != VolumeBase::Type::kEmulated) goto fail;

    // Step 1: tear down volumes and mount silently without making
    // visible to userspace apps
    bringOffline(mFrom);
    bringOffline(mTo);

    fromPath = mFrom->getInternalPath();
    toPath = mTo->getInternalPath();

    // Step 2: clean up any stale data
    if (execRm(toPath, 10, 10) != OK) {
        goto fail;
    }

    // Step 3: perform actual copy
    if (execCp(fromPath, toPath, 20, 60) != OK) {
        goto fail;
    }

    // NOTE: MountService watches for this magic value to know
    // that move was successful
    notifyProgress(82);
    bringOnline(mFrom);
    bringOnline(mTo);

    // Step 4: clean up old data
    if (execRm(fromPath, 85, 15) != OK) {
        goto fail;
    }

    notifyProgress(kMoveSucceeded);
    return;
fail:
    bringOnline(mFrom);
    bringOnline(mTo);
    notifyProgress(kMoveFailedInternalError);
    return;
}

}  // namespace vold
}  // namespace android
