//
// Copyright (C) 2014 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 "update_engine/mtd_file_descriptor.h"

#include <fcntl.h>
#include <mtd/ubi-user.h>
#include <string>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <vector>

#include <base/files/file_path.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
#include <update_engine/subprocess.h>

#include "update_engine/utils.h"

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

namespace {

static const char kSysfsClassUbi[] = "/sys/class/ubi/";
static const char kUsableEbSize[] = "/usable_eb_size";
static const char kReservedEbs[] = "/reserved_ebs";

using chromeos_update_engine::Subprocess;
using chromeos_update_engine::UbiVolumeInfo;
using chromeos_update_engine::utils::ReadFile;

// Return a UbiVolumeInfo pointer if |path| is a UBI volume. Otherwise, return
// a null unique pointer.
std::unique_ptr<UbiVolumeInfo> GetUbiVolumeInfo(const string& path) {
  base::FilePath device_node(path);
  base::FilePath ubi_name(device_node.BaseName());

  std::string sysfs_node(kSysfsClassUbi);
  sysfs_node.append(ubi_name.MaybeAsASCII());

  std::unique_ptr<UbiVolumeInfo> ret;

  // Obtain volume info from sysfs.
  std::string s_reserved_ebs;
  if (!ReadFile(sysfs_node + kReservedEbs, &s_reserved_ebs)) {
    LOG(ERROR) << "Cannot read " << sysfs_node + kReservedEbs;
    return ret;
  }
  std::string s_eb_size;
  if (!ReadFile(sysfs_node + kUsableEbSize, &s_eb_size)) {
    LOG(ERROR) << "Cannot read " << sysfs_node + kUsableEbSize;
    return ret;
  }

  base::TrimWhitespaceASCII(s_reserved_ebs,
                            base::TRIM_TRAILING,
                            &s_reserved_ebs);
  base::TrimWhitespaceASCII(s_eb_size, base::TRIM_TRAILING, &s_eb_size);

  uint64_t reserved_ebs, eb_size;
  if (!base::StringToUint64(s_reserved_ebs, &reserved_ebs)) {
    LOG(ERROR) << "Cannot parse reserved_ebs: " << s_reserved_ebs;
    return ret;
  }
  if (!base::StringToUint64(s_eb_size, &eb_size)) {
    LOG(ERROR) << "Cannot parse usable_eb_size: " << s_eb_size;
    return ret;
  }

  ret.reset(new UbiVolumeInfo);
  ret->reserved_ebs = reserved_ebs;
  ret->eraseblock_size = eb_size;
  return ret;
}

}  // namespace

namespace chromeos_update_engine {

MtdFileDescriptor::MtdFileDescriptor()
    : read_ctx_(nullptr, &mtd_read_close),
      write_ctx_(nullptr, &mtd_write_close) {}

bool MtdFileDescriptor::IsMtd(const char* path) {
  uint64_t size;
  return mtd_node_info(path, &size, nullptr, nullptr) == 0;
}

bool MtdFileDescriptor::Open(const char* path, int flags, mode_t mode) {
  // This File Descriptor does not support read and write.
  TEST_AND_RETURN_FALSE((flags & O_ACCMODE) != O_RDWR);
  // But we need to open the underlying file descriptor in O_RDWR mode because
  // during write, we need to read back to verify the write actually sticks or
  // we have to skip the block. That job is done by mtdutils library.
  if ((flags & O_ACCMODE) == O_WRONLY) {
    flags &= ~O_ACCMODE;
    flags |= O_RDWR;
  }
  TEST_AND_RETURN_FALSE(
      EintrSafeFileDescriptor::Open(path, flags | O_CLOEXEC, mode));

  if ((flags & O_ACCMODE) == O_RDWR) {
    write_ctx_.reset(mtd_write_descriptor(fd_, path));
    nr_written_ = 0;
  } else {
    read_ctx_.reset(mtd_read_descriptor(fd_, path));
  }

  if (!read_ctx_ && !write_ctx_) {
    Close();
    return false;
  }

  return true;
}

bool MtdFileDescriptor::Open(const char* path, int flags) {
  mode_t cur = umask(022);
  umask(cur);
  return Open(path, flags, 0777 & ~cur);
}

ssize_t MtdFileDescriptor::Read(void* buf, size_t count) {
  CHECK(read_ctx_);
  return mtd_read_data(read_ctx_.get(), static_cast<char*>(buf), count);
}

ssize_t MtdFileDescriptor::Write(const void* buf, size_t count) {
  CHECK(write_ctx_);
  ssize_t result = mtd_write_data(write_ctx_.get(),
                                  static_cast<const char*>(buf),
                                  count);
  if (result > 0) {
    nr_written_ += result;
  }
  return result;
}

off64_t MtdFileDescriptor::Seek(off64_t offset, int whence) {
  if (write_ctx_) {
    // Ignore seek in write mode.
    return nr_written_;
  }
  return EintrSafeFileDescriptor::Seek(offset, whence);
}

bool MtdFileDescriptor::Close() {
  read_ctx_.reset();
  write_ctx_.reset();
  return EintrSafeFileDescriptor::Close();
}

bool UbiFileDescriptor::IsUbi(const char* path) {
  base::FilePath device_node(path);
  base::FilePath ubi_name(device_node.BaseName());
  TEST_AND_RETURN_FALSE(
      base::StartsWithASCII(ubi_name.MaybeAsASCII(), "ubi", true));

  return static_cast<bool>(GetUbiVolumeInfo(path));
}

bool UbiFileDescriptor::Open(const char* path, int flags, mode_t mode) {
  std::unique_ptr<UbiVolumeInfo> info = GetUbiVolumeInfo(path);
  if (!info) {
    return false;
  }

  // This File Descriptor does not support read and write.
  TEST_AND_RETURN_FALSE((flags & O_ACCMODE) != O_RDWR);
  TEST_AND_RETURN_FALSE(
      EintrSafeFileDescriptor::Open(path, flags | O_CLOEXEC, mode));

  usable_eb_blocks_ = info->reserved_ebs;
  eraseblock_size_ = info->eraseblock_size;
  volume_size_ = usable_eb_blocks_ * eraseblock_size_;

  if ((flags & O_ACCMODE) == O_WRONLY) {
    // It's best to use volume update ioctl so that UBI layer will mark the
    // volume as being updated, and only clear that mark if the update is
    // successful. We will need to pad to the whole volume size at close.
    uint64_t vsize = volume_size_;
    if (ioctl(fd_, UBI_IOCVOLUP, &vsize) != 0) {
      PLOG(ERROR) << "Cannot issue volume update ioctl";
      EintrSafeFileDescriptor::Close();
      return false;
    }
    mode_ = kWriteOnly;
    nr_written_ = 0;
  } else {
    mode_ = kReadOnly;
  }

  return true;
}

bool UbiFileDescriptor::Open(const char* path, int flags) {
  mode_t cur = umask(022);
  umask(cur);
  return Open(path, flags, 0777 & ~cur);
}

ssize_t UbiFileDescriptor::Read(void* buf, size_t count) {
  CHECK(mode_ == kReadOnly);
  return EintrSafeFileDescriptor::Read(buf, count);
}

ssize_t UbiFileDescriptor::Write(const void* buf, size_t count) {
  CHECK(mode_ == kWriteOnly);
  ssize_t nr_chunk = EintrSafeFileDescriptor::Write(buf, count);
  if (nr_chunk >= 0) {
    nr_written_ += nr_chunk;
  }
  return nr_chunk;
}

off64_t UbiFileDescriptor::Seek(off64_t offset, int whence) {
  if (mode_ == kWriteOnly) {
    // Ignore seek in write mode.
    return nr_written_;
  }
  return EintrSafeFileDescriptor::Seek(offset, whence);
}

bool UbiFileDescriptor::Close() {
  bool pad_ok = true;
  if (IsOpen() && mode_ == kWriteOnly) {
    char buf[1024];
    memset(buf, 0xFF, sizeof(buf));
    while (nr_written_ < volume_size_) {
      // We have written less than the whole volume. In order for us to clear
      // the update marker, we need to fill the rest. It is recommended to fill
      // UBI writes with 0xFF.
      uint64_t to_write = volume_size_ - nr_written_;
      if (to_write > sizeof(buf)) {
        to_write = sizeof(buf);
      }
      ssize_t nr_chunk = EintrSafeFileDescriptor::Write(buf, to_write);
      if (nr_chunk < 0) {
        LOG(ERROR) << "Cannot 0xFF-pad before closing.";
        // There is an error, but we can't really do any meaningful thing here.
        pad_ok = false;
        break;
      }
      nr_written_ += nr_chunk;
    }
  }
  return EintrSafeFileDescriptor::Close() && pad_ok;
}

}  // namespace chromeos_update_engine
