/*
 * Copyright (C) 2021 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 "odr_fs_utils.h"

#include <dirent.h>
#include <ftw.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
#include <unistd.h>

#include <iosfwd>
#include <memory>
#include <ostream>
#include <queue>
#include <string>
#include <string_view>
#include <type_traits>
#include <vector>

#include <android-base/logging.h>
#include <android-base/macros.h>
#include <android-base/strings.h>
#include <base/os.h>

namespace art {
namespace odrefresh {

// Callback for use with nftw(3) to assist with clearing files and sub-directories.
// This method removes files and directories below the top-level directory passed to nftw().
static int NftwCleanUpCallback(const char* fpath,
                               [[maybe_unused]] const struct stat* sb,
                               int typeflag,
                               struct FTW* ftwbuf) {
  switch (typeflag) {
    case FTW_F:
      return unlink(fpath);
    case FTW_DP:
      return (ftwbuf->level == 0) ? 0 : rmdir(fpath);
    default:
      return -1;
  }
}

WARN_UNUSED bool RemoveDirectory(const std::string& dir_path) {
  if (!OS::DirectoryExists(dir_path.c_str())) {
    return true;
  }

  static constexpr int kMaxDescriptors = 4;  // Limit the need for nftw() to re-open descriptors.
  if (nftw(dir_path.c_str(), NftwCleanUpCallback, kMaxDescriptors, FTW_DEPTH | FTW_MOUNT) != 0) {
    LOG(ERROR) << "Failed to clean-up '" << dir_path << "'";
    return false;
  }

  if (rmdir(dir_path.c_str()) != 0) {
    // It's possible that we are not able to remove the directory itself. For example, when
    // odrefresh is running in CompOS, the staging dir is prepared beforehand passed to the VM as an
    // FD. In this case, just log and ignore the error. It's okay to keep the directory.
    LOG(WARNING) << "Failed to delete '" << dir_path << "'";
  }

  return true;
}

WARN_UNUSED bool EnsureDirectoryExists(const std::string& absolute_path) {
  if (absolute_path.empty() || absolute_path[0] != '/') {
    LOG(ERROR) << "Path not absolute '" << absolute_path << "'";
    return false;
  }
  std::string path;
  for (const std::string& directory : android::base::Split(absolute_path, "/")) {
    path.append("/").append(directory);
    if (!OS::DirectoryExists(path.c_str())) {
      static constexpr mode_t kDirectoryMode = S_IRWXU | S_IRGRP | S_IXGRP| S_IROTH | S_IXOTH;
      if (mkdir(path.c_str(), kDirectoryMode) != 0) {
        PLOG(ERROR) << "Could not create directory: " << path;
        return false;
      }
    }
  }
  return true;
}

bool GetFreeSpace(const std::string& path, uint64_t* bytes) {
  struct statvfs sv;
  if (statvfs(path.c_str(), &sv) != 0) {
    PLOG(ERROR) << "statvfs '" << path << "'";
    return false;
  }
  *bytes = sv.f_bfree * sv.f_bsize;
  return true;
}

bool GetUsedSpace(const std::string& path, uint64_t* bytes) {
  static constexpr std::string_view kCurrentDirectory{"."};
  static constexpr std::string_view kParentDirectory{".."};
  static constexpr size_t kBytesPerBlock = 512;  // see manual page for stat(2).

  uint64_t file_bytes = 0;
  std::queue<std::string> unvisited;
  unvisited.push(path);
  while (!unvisited.empty()) {
    std::string current = unvisited.front();
    unvisited.pop();
    std::unique_ptr<DIR, int (*)(DIR*)> dir(opendir(current.c_str()), closedir);
    if (!dir) {
      continue;
    }
    for (auto entity = readdir(dir.get()); entity != nullptr; entity = readdir(dir.get())) {
      std::string_view name{entity->d_name};
      if (name == kCurrentDirectory || name == kParentDirectory) {
        continue;
      }
      std::string entity_name = current + "/" + entity->d_name;
      if (entity->d_type == DT_DIR) {
        unvisited.push(entity_name.c_str());
      } else if (entity->d_type == DT_REG) {
        struct stat sb;
        if (stat(entity_name.c_str(), &sb) != 0) {
          PLOG(ERROR) << "Failed to stat() file " << entity_name;
          continue;
        }
        file_bytes += sb.st_blocks * kBytesPerBlock;
      }
    }
  }
  *bytes = file_bytes;
  return true;
}

}  // namespace odrefresh
}  // namespace art
