// Copyright (c) 2011 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.

#include "cros-disks/mount_options.h"

#include <sys/mount.h>

#include <algorithm>

#include <base/strings/string_util.h>

using std::pair;
using std::string;
using std::vector;

namespace cros_disks {

const char MountOptions::kOptionBind[] = "bind";
const char MountOptions::kOptionDirSync[] = "dirsync";
const char MountOptions::kOptionFlush[] = "flush";
const char MountOptions::kOptionNoDev[] = "nodev";
const char MountOptions::kOptionNoExec[] = "noexec";
const char MountOptions::kOptionNoSuid[] = "nosuid";
const char MountOptions::kOptionReadOnly[] = "ro";
const char MountOptions::kOptionReadWrite[] = "rw";
const char MountOptions::kOptionSynchronous[] = "sync";
const char MountOptions::kOptionUtf8[] = "utf8";

void MountOptions::Initialize(const vector<string>& options,
                              bool set_user_and_group_id,
                              const string& default_user_id,
                              const string& default_group_id) {
  options_.clear();
  options_.reserve(options.size());

  bool option_read_only = false, option_read_write = false;
  string option_user_id, option_group_id;

  for (const auto& option : options) {
    // Skip early if |option| contains a comma.
    if (option.find(",") != string::npos) {
      LOG(WARNING) << "Ignoring invalid mount option '" << option << "'.";
      continue;
    }

    if (option == kOptionReadOnly) {
      option_read_only = true;
    } else if (option == kOptionReadWrite) {
      option_read_write = true;
    } else if (StartsWithASCII(option, "uid=", false)) {
      option_user_id = option;
    } else if (StartsWithASCII(option, "gid=", false)) {
      option_group_id = option;
    } else if (option == kOptionNoDev ||
               option == kOptionNoExec ||
               option == kOptionNoSuid) {
      // We'll add these options unconditionally below.
      continue;
    } else if (option == kOptionBind ||
               option == kOptionDirSync ||
               option == kOptionFlush ||
               option == kOptionSynchronous ||
               option == kOptionUtf8 ||
               StartsWithASCII(option, "shortname=", false)) {
      // Only add options in the whitelist.
      options_.push_back(option);
    } else {
      // Never add unknown/non-whitelisted options.
      LOG(WARNING) << "Ignoring unsupported mount option '" << option << "'.";
    }
  }

  if (option_read_only || !option_read_write) {
    options_.push_back(kOptionReadOnly);
  } else {
    options_.push_back(kOptionReadWrite);
  }

  if (set_user_and_group_id) {
    if (!option_user_id.empty()) {
      options_.push_back(option_user_id);
    } else if (!default_user_id.empty()) {
      options_.push_back("uid=" + default_user_id);
    }

    if (!option_group_id.empty()) {
      options_.push_back(option_group_id);
    } else if (!default_group_id.empty()) {
      options_.push_back("gid=" + default_group_id);
    }
  }

  // Always set 'nodev', 'noexec', and 'nosuid'.
  options_.push_back(kOptionNoDev);
  options_.push_back(kOptionNoExec);
  options_.push_back(kOptionNoSuid);
}

bool MountOptions::IsReadOnlyOptionSet() const {
  for (vector<string>::const_reverse_iterator
       option_iterator = options_.rbegin(); option_iterator != options_.rend();
       ++option_iterator) {
    const string& option = *option_iterator;
    if (option == kOptionReadOnly)
      return true;

    if (option == kOptionReadWrite)
      return false;
  }
  return true;
}

void MountOptions::SetReadOnlyOption() {
  std::replace(options_.begin(), options_.end(),
               kOptionReadWrite, kOptionReadOnly);
}

pair<MountOptions::Flags, string> MountOptions::ToMountFlagsAndData() const {
  Flags flags = MS_RDONLY;
  vector<string> data;
  data.reserve(options_.size());

  for (const auto& option : options_) {
    if (option == kOptionReadOnly) {
      flags |= MS_RDONLY;
    } else if (option == kOptionReadWrite) {
      flags &= ~static_cast<Flags>(MS_RDONLY);
    } else if (option == kOptionBind) {
      flags |= MS_BIND;
    } else if (option == kOptionDirSync) {
      flags |= MS_DIRSYNC;
    } else if (option == kOptionNoDev) {
      flags |= MS_NODEV;
    } else if (option == kOptionNoExec) {
      flags |= MS_NOEXEC;
    } else if (option == kOptionNoSuid) {
      flags |= MS_NOSUID;
    } else if (option == kOptionSynchronous) {
      flags |= MS_SYNCHRONOUS;
    } else {
      data.push_back(option);
    }
  }
  return std::make_pair(flags, JoinString(data, ','));
}

string MountOptions::ToString() const {
  return options_.empty() ? kOptionReadOnly : JoinString(options_, ',');
}

}  // namespace cros_disks
