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

#ifndef ANDROID_APEXD_APEXD_UTILS_H_
#define ANDROID_APEXD_APEXD_UTILS_H_

#include <chrono>
#include <filesystem>
#include <string>
#include <thread>
#include <vector>

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

#include <android-base/chrono_utils.h>
#include <android-base/logging.h>
#include <android-base/result.h>
#include <android-base/scopeguard.h>
#include <android-base/strings.h>
#include <cutils/android_reboot.h>

#include "apex_constants.h"

using android::base::EndsWith;
using android::base::ErrnoError;
using android::base::Error;
using android::base::Result;

namespace android {
namespace apex {

inline int WaitChild(pid_t pid) {
  int status;
  pid_t got_pid = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0));

  if (got_pid != pid) {
    PLOG(WARNING) << "waitpid failed: wanted " << pid << ", got " << got_pid;
    return 1;
  }

  if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
    return 0;
  } else {
    return status;
  }
}

inline Result<void> ForkAndRun(const std::vector<std::string>& args) {
  LOG(DEBUG) << "Forking : " << android::base::Join(args, " ");
  std::vector<const char*> argv;
  argv.resize(args.size() + 1, nullptr);
  std::transform(args.begin(), args.end(), argv.begin(),
                 [](const std::string& in) { return in.c_str(); });

  pid_t pid = fork();
  if (pid == -1) {
    // Fork failed.
    return ErrnoError() << "Unable to fork";
  }

  if (pid == 0) {
    execv(argv[0], const_cast<char**>(argv.data()));
    PLOG(ERROR) << "execv failed";
    _exit(1);
  }

  int rc = WaitChild(pid);
  if (rc != 0) {
    return Error() << "Failed run: status=" << rc;
  }
  return {};
}

template <typename Fn>
Result<void> WalkDir(const std::string& path, Fn fn) {
  namespace fs = std::filesystem;
  std::error_code ec;
  auto it = fs::directory_iterator(path, ec);
  auto end = fs::directory_iterator();
  while (!ec && it != end) {
    fn(*it);
    it.increment(ec);
  }
  if (ec) {
    return Error() << "Can't open " << path
                   << " for reading : " << ec.message();
  }
  return {};
}

template <typename FilterFn>
Result<std::vector<std::string>> ReadDir(const std::string& path, FilterFn fn) {
  namespace fs = std::filesystem;

  std::vector<std::string> ret;
  auto status = WalkDir(path, [&](const fs::directory_entry& entry) {
    if (fn(entry)) {
      ret.push_back(entry.path());
    }
  });
  if (!status.ok()) {
    return status.error();
  }
  return ret;
}

inline bool IsEmptyDirectory(const std::string& path) {
  auto res = ReadDir(path, [](auto _) { return true; });
  return res.ok() && res->empty();
}

inline Result<void> createDirIfNeeded(const std::string& path, mode_t mode) {
  struct stat stat_data;

  if (stat(path.c_str(), &stat_data) != 0) {
    if (errno == ENOENT) {
      if (mkdir(path.c_str(), mode) != 0) {
        return ErrnoError() << "Could not mkdir " << path;
      }
    } else {
      return ErrnoError() << "Could not stat " << path;
    }
  } else {
    if (!S_ISDIR(stat_data.st_mode)) {
      return Error() << path << " exists and is not a directory.";
    }
  }

  // Need to manually call chmod because mkdir will create a folder with
  // permissions mode & ~umask.
  if (chmod(path.c_str(), mode) != 0) {
    return ErrnoError() << "Could not chmod " << path;
  }

  return {};
}

inline Result<void> DeleteDirContent(const std::string& path) {
  auto files = ReadDir(path, [](auto _) { return true; });
  if (!files.ok()) {
    return Error() << "Failed to delete " << path << " : " << files.error();
  }
  for (const std::string& file : *files) {
    if (unlink(file.c_str()) != 0) {
      return ErrnoError() << "Failed to delete " << file;
    }
  }
  return {};
}

inline Result<void> DeleteDir(const std::string& path) {
  namespace fs = std::filesystem;
  std::error_code ec;
  fs::remove_all(path, ec);
  if (ec) {
    return Error() << "Failed to delete path " << path << " : " << ec.message();
  }
  return {};
}

inline Result<ino_t> get_path_inode(const std::string& path) {
  struct stat buf;
  memset(&buf, 0, sizeof(buf));
  if (stat(path.c_str(), &buf) != 0) {
    return ErrnoError() << "Failed to stat " << path;
  } else {
    return buf.st_ino;
  }
}

inline Result<bool> PathExists(const std::string& path) {
  namespace fs = std::filesystem;

  std::error_code ec;
  if (!fs::exists(fs::path(path), ec)) {
    if (ec) {
      return Error() << "Failed to access " << path << " : " << ec.message();
    } else {
      return false;
    }
  }
  return true;
}

inline void Reboot() {
  LOG(INFO) << "Rebooting device";
  if (android_reboot(ANDROID_RB_RESTART2, 0, nullptr) != 0) {
    LOG(ERROR) << "Failed to reboot device";
  }
}

inline Result<void> WaitForFile(const std::string& path,
                                std::chrono::nanoseconds timeout) {
  android::base::Timer t;
  bool has_slept = false;
  while (t.duration() < timeout) {
    struct stat sb;
    if (stat(path.c_str(), &sb) != -1) {
      if (has_slept) {
        LOG(INFO) << "wait for '" << path << "' took " << t;
      }
      return {};
    }
    std::this_thread::sleep_for(5ms);
    has_slept = true;
  }
  return ErrnoError() << "wait for '" << path << "' timed out and took " << t;
}

inline Result<std::vector<std::string>> GetSubdirs(const std::string& path) {
  namespace fs = std::filesystem;
  auto filter_fn = [](const std::filesystem::directory_entry& entry) {
    std::error_code ec;
    bool result = entry.is_directory(ec);
    if (ec) {
      LOG(ERROR) << "Failed to check is_directory : " << ec.message();
      return false;
    }
    return result;
  };
  return ReadDir(path, filter_fn);
}

inline Result<std::vector<std::string>> GetDeUserDirs() {
  return GetSubdirs(kDeNDataDir);
}

inline Result<std::vector<std::string>> FindApexFilesByName(
    const std::string& path) {
  auto filter_fn = [](const std::filesystem::directory_entry& entry) {
    std::error_code ec;
    if (entry.is_regular_file(ec) &&
        EndsWith(entry.path().filename().string(), kApexPackageSuffix)) {
      return true;  // APEX file, take.
    }
    return false;
  };
  return ReadDir(path, filter_fn);
}

inline Result<std::vector<std::string>> FindApexes(
    const std::vector<std::string>& paths) {
  std::vector<std::string> result;
  for (const auto& path : paths) {
    auto exist = PathExists(path);
    if (!exist.ok()) {
      return exist.error();
    }
    if (!*exist) continue;

    const auto& apexes = FindApexFilesByName(path);
    if (!apexes.ok()) {
      return apexes;
    }

    result.insert(result.end(), apexes->begin(), apexes->end());
  }
  return result;
}

}  // namespace apex
}  // namespace android

#endif  // ANDROID_APEXD_APEXD_UTILS_H_
