// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Contains the implementation of class Platform

#include "platform.h"

#include <errno.h>
#include <grp.h>
#include <limits.h>
#include <mntent.h>
#include <pwd.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
#include <sys/types.h>
#include <sys/wait.h>

#include <base/file_util.h>
#include <base/string_number_conversions.h>
#include <base/string_split.h>
#include <base/string_util.h>
#include <base/stringprintf.h>
#include <base/sys_info.h>
#include <base/time.h>
#include <chromeos/process.h>
#include <chromeos/secure_blob.h>
#include <chromeos/utility.h>

using base::SplitString;
using std::string;

namespace chromeos {

const int kDefaultMountOptions = MS_NOEXEC | MS_NOSUID | MS_NODEV;
const int kDefaultPwnameLength = 1024;
const int kDefaultUmask = S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH
                               | S_IXOTH;
const std::string kMtab = "/etc/mtab";
const std::string kProcDir = "/proc";
const std::string kPathDf = "/bin/df";
const std::string kPathTune2fs = "/sbin/tune2fs";

Platform::Platform()
  : mtab_path_(kMtab) {
}

Platform::~Platform() {
}

bool Platform::GetMountsBySourcePrefix(const std::string& from_prefix,
                 std::multimap<const std::string, const std::string>* mounts) {
  std::string contents;
  if (!file_util::ReadFileToString(FilePath(mtab_path_), &contents))
    return false;

  std::vector<std::string> lines;
  SplitString(contents, '\n', &lines);
  for (std::vector<std::string>::iterator it = lines.begin();
       it < lines.end();
       ++it) {
    if (it->substr(0, from_prefix.size()) != from_prefix)
      continue;
    // If there is no mounts pointer, we can return true right away.
    if (!mounts)
      return true;
    size_t src_end = it->find(' ');
    std::string source = it->substr(0, src_end);
    size_t dst_start = src_end + 1;
    size_t dst_end = it->find(' ', dst_start);
    std::string destination = it->substr(dst_start, dst_end - dst_start);
    mounts->insert(
      std::pair<const std::string, const std::string>(source, destination));
  }
  return mounts && mounts->size();
}

bool Platform::IsDirectoryMounted(const std::string& directory) {
  // Trivial string match from /etc/mtab to see if the cryptohome mount point is
  // listed.  This works because Chrome OS is a controlled environment and the
  // only way /home/chronos/user should be mounted is if cryptohome mounted it.
  string contents;
  if (file_util::ReadFileToString(FilePath(mtab_path_), &contents)) {
    if (contents.find(StringPrintf(" %s ", directory.c_str()))
        != string::npos) {
      return true;
    }
  }
  return false;
}

bool Platform::IsDirectoryMountedWith(const std::string& directory,
                                      const std::string& from) {
  // Trivial string match from /etc/mtab to see if the cryptohome mount point
  // and the user's vault path are present.  Assumes this user is mounted if it
  // finds both.  This will need to change if simultaneous login is implemented.
  string contents;
  if (file_util::ReadFileToString(FilePath(mtab_path_), &contents)) {
    if ((contents.find(StringPrintf(" %s ", directory.c_str()))
         != string::npos)
        && (contents.find(StringPrintf("%s ",
                                       from.c_str()).c_str())
            != string::npos)) {
      return true;
    }
  }
  return false;
}

bool Platform::Mount(const std::string& from, const std::string& to,
                     const std::string& type,
                     const std::string& mount_options) {
  if (mount(from.c_str(), to.c_str(), type.c_str(), kDefaultMountOptions,
            mount_options.c_str())) {
    return false;
  }
  return true;
}

bool Platform::Bind(const std::string& from, const std::string& to) {
  if (mount(from.c_str(), to.c_str(), NULL, kDefaultMountOptions | MS_BIND,
            NULL))
    return false;
  return true;
}

bool Platform::Unmount(const std::string& path, bool lazy, bool* was_busy) {
  if (lazy) {
    if (umount2(path.c_str(), MNT_DETACH)) {
      if (was_busy) {
        *was_busy = (errno == EBUSY);
      }
      return false;
    }
  } else {
    if (umount(path.c_str())) {
      if (was_busy) {
        *was_busy = (errno == EBUSY);
      }
      return false;
    }
  }
  if (was_busy) {
    *was_busy = false;
  }
  return true;
}

void Platform::GetProcessesWithOpenFiles(
    const std::string& path,
    std::vector<ProcessInformation>* processes) {
  std::vector<pid_t> pids;
  LookForOpenFiles(path, &pids);
  for (std::vector<pid_t>::iterator it = pids.begin(); it != pids.end(); ++it) {
    pid_t pid = static_cast<pid_t>(*it);
    processes->push_back(ProcessInformation());
    GetProcessOpenFileInformation(pid, path,
                                  &processes->at(processes->size() - 1));
  }
}

std::string Platform::ReadLink(const std::string& link_path) {
  char link_buf[PATH_MAX];
  ssize_t link_length = readlink(link_path.c_str(), link_buf, sizeof(link_buf));
  if (link_length > 0) {
    return std::string(link_buf, link_length);
  }
  return std::string();
}

void Platform::GetProcessOpenFileInformation(pid_t pid,
                                             const std::string& path_in,
                                             ProcessInformation* process_info) {
  process_info->set_process_id(pid);
  FilePath pid_path(StringPrintf("/proc/%d", pid));
  FilePath cmdline_file = pid_path.Append("cmdline");
  string contents;
  std::vector<std::string> cmd_line;
  if (file_util::ReadFileToString(cmdline_file, &contents)) {
    SplitString(contents, '\0', &cmd_line);
  }
  process_info->set_cmd_line(&cmd_line);

  // Make sure that if we get a directory, it has a trailing separator
  FilePath file_path(path_in);
  file_util::EnsureEndsWithSeparator(&file_path);
  std::string path = file_path.value();

  FilePath cwd_path = pid_path.Append("cwd");
  std::string link_val = ReadLink(cwd_path.value());
  if (IsPathChild(path, link_val)) {
    process_info->set_cwd(&link_val);
  } else {
    link_val.clear();
    process_info->set_cwd(&link_val);
  }

  // Open /proc/<pid>/fd
  FilePath fd_dirpath = pid_path.Append("fd");

  file_util::FileEnumerator fd_dir_enum(fd_dirpath, false,
                                        file_util::FileEnumerator::FILES);

  std::set<std::string> open_files;
  // List open file descriptors
  for (FilePath fd_path = fd_dir_enum.Next();
       !fd_path.empty();
       fd_path = fd_dir_enum.Next()) {
    link_val = ReadLink(fd_path.value());
    if (IsPathChild(path, link_val)) {
      open_files.insert(link_val);
    }
  }
  process_info->set_open_files(&open_files);
}

void Platform::LookForOpenFiles(const std::string& path_in,
                                std::vector<pid_t>* pids) {
  // Make sure that if we get a directory, it has a trailing separator
  FilePath file_path(path_in);
  file_util::EnsureEndsWithSeparator(&file_path);
  std::string path = file_path.value();

  // Open /proc
  file_util::FileEnumerator proc_dir_enum(FilePath(kProcDir), false,
      file_util::FileEnumerator::DIRECTORIES);

  int linkbuf_length = path.length();
  std::vector<char> linkbuf(linkbuf_length);

  // List PIDs in /proc
  for (FilePath pid_path = proc_dir_enum.Next();
       !pid_path.empty();
       pid_path = proc_dir_enum.Next()) {
    const char* pidstr = pid_path.BaseName().value().c_str();
    pid_t pid = 0;
    // Ignore PID 1 and errors
    if (!base::StringToInt(pidstr, &pid) || pid <= 1) {
      continue;
    }

    FilePath cwd_path = pid_path.Append("cwd");
    ssize_t link_length = readlink(cwd_path.value().c_str(),
                                   &linkbuf[0],
                                   linkbuf.size());
    if (link_length > 0) {
      std::string open_file(&linkbuf[0], link_length);
      if (IsPathChild(path, open_file)) {
        pids->push_back(pid);
        continue;
      }
    }

    // Open /proc/<pid>/fd
    FilePath fd_dirpath = pid_path.Append("fd");

    file_util::FileEnumerator fd_dir_enum(fd_dirpath, false,
                                          file_util::FileEnumerator::FILES);

    // List open file descriptors
    for (FilePath fd_path = fd_dir_enum.Next();
         !fd_path.empty();
         fd_path = fd_dir_enum.Next()) {
      link_length = readlink(fd_path.value().c_str(), &linkbuf[0],
                                     linkbuf.size());
      if (link_length > 0) {
        std::string open_file(&linkbuf[0], link_length);
        if (IsPathChild(path, open_file)) {
          pids->push_back(pid);
          break;
        }
      }
    }
  }
}

bool Platform::IsPathChild(const std::string& parent,
                           const std::string& child) {
  if (parent.length() == 0 || child.length() == 0) {
    return false;
  }
  if (child.length() >= parent.length()) {
    if (child.compare(0, parent.length(), parent, 0, parent.length()) == 0) {
      return true;
    }
  } else if ((parent[parent.length() - 1] == '/') &&
             (child.length() == (parent.length() - 1))) {
    if (child.compare(0, child.length(), parent, 0, parent.length() - 1) == 0) {
      return true;
    }
  }
  return false;
}

bool Platform::GetOwnership(const string& path,
                            uid_t* user_id, gid_t* group_id) const {
  struct stat path_status;
  if (stat(path.c_str(), &path_status) != 0) {
    PLOG(ERROR) << "stat() of " << path << " failed.";
    return false;
  }
  if (user_id)
    *user_id = path_status.st_uid;
  if (group_id)
    *group_id = path_status.st_gid;
  return true;
}

bool Platform::SetOwnership(const std::string& path, uid_t user_id,
                            gid_t group_id) const {
  if (chown(path.c_str(), user_id, group_id)) {
    PLOG(ERROR) << "chown() of " << path.c_str() << " to (" << user_id
                << "," << group_id << ") failed.";
    return false;
  }
  return true;
}

bool Platform::GetPermissions(const string& path, mode_t* mode) const {
  struct stat path_status;
  if (stat(path.c_str(), &path_status) != 0) {
    PLOG(ERROR) << "stat() of " << path << " failed.";
    return false;
  }
  *mode = path_status.st_mode;
  return true;
}

bool Platform::SetPermissions(const std::string& path, mode_t mode) const {
  if (chmod(path.c_str(), mode)) {
    PLOG(ERROR) << "chmod() of " << path.c_str() << " to (" << std::oct << mode
                << ") failed.";
    return false;
  }
  return true;
}

bool Platform::SetGroupAccessible(const string& path, gid_t group_id,
                                  mode_t group_mode) const {
  uid_t user_id;
  mode_t mode;
  if (!GetOwnership(path, &user_id, NULL) ||
      !GetPermissions(path, &mode) ||
      !SetOwnership(path, user_id, group_id) ||
      !SetPermissions(path, (mode & ~S_IRWXG) | (group_mode & S_IRWXG))) {
    LOG(ERROR) << "Couldn't set up group access on directory: " << path;
    return false;
  }
  return true;
}

int Platform::SetMask(int new_mask) const {
  return umask(new_mask);
}

bool Platform::GetUserId(const std::string& user, uid_t* user_id,
                         gid_t* group_id) const {
  // Load the passwd entry
  long user_name_length = sysconf(_SC_GETPW_R_SIZE_MAX);  // NOLINT long
  if (user_name_length == -1) {
    user_name_length = kDefaultPwnameLength;
  }
  struct passwd user_info, *user_infop;
  std::vector<char> user_name_buf(user_name_length);
  if (getpwnam_r(user.c_str(), &user_info, &user_name_buf[0],
                user_name_length, &user_infop)) {
    return false;
  }
  *user_id = user_info.pw_uid;
  *group_id = user_info.pw_gid;
  return true;
}

bool Platform::GetGroupId(const std::string& group, gid_t* group_id) const {
  // Load the group entry
  long group_name_length = sysconf(_SC_GETGR_R_SIZE_MAX);  // NOLINT long
  if (group_name_length == -1) {
    group_name_length = kDefaultPwnameLength;
  }
  struct group group_info, *group_infop;
  std::vector<char> group_name_buf(group_name_length);
  if (getgrnam_r(group.c_str(), &group_info, &group_name_buf[0],
                group_name_length, &group_infop)) {
    return false;
  }
  *group_id = group_info.gr_gid;
  return true;
}

int64 Platform::AmountOfFreeDiskSpace(const string& path) const {
  return base::SysInfo::AmountOfFreeDiskSpace(FilePath(path));
}

bool Platform::FileExists(const std::string& path) {
  return file_util::PathExists(FilePath(path));
}

bool Platform::DirectoryExists(const std::string& path) {
  return file_util::DirectoryExists(FilePath(path));
}

bool Platform::GetFileSize(const std::string& path, int64* size) {
  return file_util::GetFileSize(FilePath(path), size);
}

FILE* Platform::CreateAndOpenTemporaryFile(std::string* path) {
  FilePath created_path;
  FILE* f = file_util::CreateAndOpenTemporaryFile(&created_path);
  if (f)
    path->assign(created_path.value());

  return f;
}

FILE* Platform::OpenFile(const std::string& path, const char* mode) {
  return file_util::OpenFile(FilePath(path), mode);
}

bool Platform::CloseFile(FILE* fp) {
  return file_util::CloseFile(fp);
}

bool Platform::WriteOpenFile(FILE* fp, const chromeos::Blob& blob) {
  return (fwrite(static_cast<const void*>(&blob.at(0)), 1, blob.size(), fp)
            != blob.size());
}

bool Platform::WriteFile(const std::string& path,
                         const chromeos::Blob& blob) {
  return WriteArrayToFile(path,
                          reinterpret_cast<const char*>(&blob[0]),
                          blob.size());
}

bool Platform::WriteStringToFile(const std::string& path,
                                 const std::string& data) {
  return WriteArrayToFile(path, data.data(), data.size());
}

bool Platform::WriteArrayToFile(const std::string& path, const char* data,
                                size_t size) {
  FilePath file_path(path);
  if (!file_util::DirectoryExists(file_path.DirName())) {
    if (!file_util::CreateDirectory(file_path.DirName())) {
      LOG(ERROR) << "Cannot create directory: " << file_path.DirName().value();
      return false;
    }
  }
  // chromeos::Blob::size_type is std::vector::size_type and is unsigned.
  if (size > static_cast<std::string::size_type>(INT_MAX)) {
    LOG(ERROR) << "Cannot write to " << path
               << ". Data is too large: " << size << " bytes.";
    return false;
  }

  int data_written = file_util::WriteFile(file_path, data, size);
  return data_written == static_cast<int>(size);
}

bool Platform::ReadFile(const std::string& path, chromeos::Blob* blob) {
  int64 file_size;
  FilePath file_path(path);
  if (!file_util::PathExists(file_path)) {
    return false;
  }
  if (!file_util::GetFileSize(file_path, &file_size)) {
    LOG(ERROR) << "Could not get size of " << path;
    return false;
  }
  // Compare to the max of a signed integer.
  if (file_size > static_cast<int64>(INT_MAX)) {
    LOG(ERROR) << "File " << path << " is too large: "
               << file_size << " bytes.";
    return false;
  }
  chromeos::Blob buf(file_size);
  int data_read = file_util::ReadFile(file_path,
                                      reinterpret_cast<char*>(&buf[0]),
                                      file_size);
  // Cast is okay because of comparison to INT_MAX above.
  if (data_read != static_cast<int>(file_size)) {
    LOG(ERROR) << "Only read " << data_read << " of " << file_size << " bytes.";
    return false;
  }
  blob->swap(buf);
  return true;
}

bool Platform::ReadFileToString(const std::string& path, std::string* string) {
  return file_util::ReadFileToString(FilePath(path), string);
}

bool Platform::CreateDirectory(const std::string& path) {
  return file_util::CreateDirectory(FilePath(path));
}

bool Platform::DeleteFile(const std::string& path, bool is_recursive) {
  return file_util::Delete(FilePath(path), is_recursive);
}

bool Platform::Move(const std::string& from, const std::string& to) {
  return file_util::Move(FilePath(from), FilePath(to));
}

bool Platform::EnumerateDirectoryEntries(const std::string& path,
                                         bool recursive,
                                         std::vector<std::string>* ent_list) {
  file_util::FileEnumerator::FileType ft = static_cast<typeof(ft)>(
    file_util::FileEnumerator::FILES | file_util::FileEnumerator::DIRECTORIES |
    file_util::FileEnumerator::SHOW_SYM_LINKS);
  file_util::FileEnumerator ent_enum(FilePath(path), recursive, ft);
  for (FilePath path = ent_enum.Next(); !path.empty(); path = ent_enum.Next())
    ent_list->push_back(path.value());
  return true;
}

base::Time Platform::GetCurrentTime() const {
  return base::Time::Now();
}

bool Platform::Stat(const std::string& path, struct stat *buf) {
  return lstat(path.c_str(), buf) == 0;
}

bool Platform::Rename(const std::string& from, const std::string& to) {
  return rename(from.c_str(), to.c_str()) == 0;
}

bool Platform::Copy(const std::string& from, const std::string& to) {
  FilePath from_path(from);
  FilePath to_path(to);
  return file_util::CopyDirectory(from_path, to_path, true);
}

bool Platform::GetFilesystemStats(const std::string& fs, struct statvfs *st) {
  return statvfs(fs.c_str(), st) == 0;
}

bool Platform::FindFilesystemDevice(const std::string &filesystem_in,
                                    std::string *device)
{
  /* Clear device to indicate failure case. */
  device->clear();

  /* Removing trailing slashes. */
  std::string filesystem = filesystem_in;
  size_t offset = filesystem.find_last_not_of('/');
  if (offset != std::string::npos)
    filesystem.erase(offset+1);

  /* If we fail to open mtab, abort immediately. */
  FILE *mtab_file = setmntent(mtab_path_.c_str(), "r");
  if (!mtab_file)
    return false;

  /* Copy device of first matching filesystem location. */
  struct mntent *entry;
  while ((entry = getmntent(mtab_file)) != NULL) {
    if (filesystem.compare(entry->mnt_dir) == 0) {
      *device = entry->mnt_fsname;
      break;
    }
  }
  endmntent(mtab_file);

  return (device->length() > 0);
}

bool Platform::ReportFilesystemDetails(const std::string &filesystem,
                                       const std::string &logfile) {
  chromeos::ProcessImpl process;
  int rc;
  std::string device;
  if (!FindFilesystemDevice(filesystem, &device)) {
    LOG(ERROR) << "Failed to find device for " << filesystem;
    return false;
  }

  process.RedirectOutput(logfile);
  process.AddArg(kPathTune2fs);
  process.AddArg("-l");
  process.AddArg(device);

  rc = process.Run();
  if (rc == 0)
    return true;
  LOG(ERROR) << "Failed to run tune2fs on " << device
             << " (" << filesystem << ", exit " << rc << ")";
  return false;
}

long Platform::ClearUserKeyring() {
  CHECK(0 && "unimplemented stub called");
  return 1;
}

long Platform::AddEcryptfsAuthToken(const chromeos::SecureBlob& key,
                                    const std::string& key_sig,
                                    const chromeos::SecureBlob& salt) {
  CHECK(0 && "unimplemented stub called");
  return 1;
}

FileEnumerator* Platform::GetFileEnumerator(const std::string& root_path,
                                            bool recursive,
                                            int file_type) {
  return new FileEnumerator(root_path, recursive, file_type);
}



FileEnumerator::FileEnumerator(const std::string& root_path,
                               bool recursive,
                               int file_type) {
  enumerator_ = new file_util::FileEnumerator(
      FilePath(root_path),
      recursive,
      static_cast<file_util::FileEnumerator::FileType>(file_type));
}

FileEnumerator::FileEnumerator(const std::string& root_path,
                               bool recursive,
                               int file_type,
                               const std::string& pattern) {
  enumerator_ = new file_util::FileEnumerator(
      FilePath(root_path),
      recursive,
      static_cast<file_util::FileEnumerator::FileType>(file_type),
      pattern);
}

FileEnumerator::~FileEnumerator() {
  if (enumerator_)
    delete enumerator_;
}

std::string FileEnumerator::Next() {
  if (!enumerator_)
    return "";
  return enumerator_->Next().value();
}

void FileEnumerator::GetFindInfo(FindInfo* info) {
  DCHECK(info);
  enumerator_->GetFindInfo(
      reinterpret_cast<file_util::FileEnumerator::FindInfo*>(info));
}

// static
bool FileEnumerator::IsDirectory(const FindInfo& info) {
 return !!S_ISDIR(info.stat.st_mode);
}

//static
std::string FileEnumerator::GetFilename(const FindInfo& find_info) {
  return find_info.filename;
}

// static
int64 FileEnumerator::GetFilesize(const FindInfo& info) {
  return file_util::FileEnumerator::GetFilesize(
    *(reinterpret_cast<const file_util::FileEnumerator::FindInfo*>(&info)));
}

// static
base::Time FileEnumerator::GetLastModifiedTime(const FindInfo& info) {
  return file_util::FileEnumerator::GetLastModifiedTime(
    *(reinterpret_cast<const file_util::FileEnumerator::FindInfo*>(&info)));
}

}  // namespace chromeos
