//
// Copyright (C) 2016 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/payload_generator/mapfile_filesystem.h"

#include <algorithm>
#include <map>

#include <base/files/file_util.h>
#include <base/logging.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_split.h>
#include <brillo/make_unique_ptr.h>

#include "update_engine/common/utils.h"
#include "update_engine/payload_generator/extent_ranges.h"
#include "update_engine/payload_generator/extent_utils.h"
#include "update_engine/update_metadata.pb.h"

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

namespace {
// The .map file is defined in terms of 4K blocks.
size_t kMapfileBlockSize = 4096;
}  // namespace

namespace chromeos_update_engine {

std::unique_ptr<MapfileFilesystem> MapfileFilesystem::CreateFromFile(
    const string& filename, const string& mapfile_filename) {
  if (filename.empty() || mapfile_filename.empty())
    return nullptr;

  off_t file_size = utils::FileSize(filename);
  if (file_size < 0)
    return nullptr;

  if (file_size % kMapfileBlockSize) {
    LOG(ERROR) << "Image file " << filename << " has a size of " << file_size
               << " which is not multiple of " << kMapfileBlockSize;
    return nullptr;
  }
  off_t num_blocks = file_size / kMapfileBlockSize;

  if (!utils::FileExists(mapfile_filename.c_str())) {
    LOG(ERROR) << "File " << mapfile_filename << " doesn't exist";
    return nullptr;
  }

  return brillo::make_unique_ptr(
      new MapfileFilesystem(mapfile_filename, num_blocks));
}

MapfileFilesystem::MapfileFilesystem(const string& mapfile_filename,
                                     off_t num_blocks)
    : mapfile_filename_(mapfile_filename), num_blocks_(num_blocks) {}

size_t MapfileFilesystem::GetBlockSize() const {
  return kMapfileBlockSize;
}

size_t MapfileFilesystem::GetBlockCount() const {
  return num_blocks_;
}

bool MapfileFilesystem::GetFiles(vector<File>* files) const {
  files->clear();

  string file_data;
  if (!base::ReadFileToString(base::FilePath(mapfile_filename_), &file_data)) {
    LOG(ERROR) << "Unable to read .map file: " << mapfile_filename_;
    return false;
  }

  // Iterate over all the lines in the file and generate one File entry per
  // line.
  vector<base::StringPiece> lines = base::SplitStringPiece(
      file_data, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
  for (const base::StringPiece& line : lines) {
    File mapped_file;

    mapped_file.extents = {};
    size_t delim, last_delim = line.size();
    while ((delim = line.rfind(' ', last_delim - 1)) != string::npos) {
      string blocks =
          line.substr(delim + 1, last_delim - (delim + 1)).as_string();
      size_t dash = blocks.find('-', 0);
      uint64_t block_start, block_end;
      if (dash == string::npos && base::StringToUint64(blocks, &block_start)) {
        mapped_file.extents.push_back(ExtentForRange(block_start, 1));
      } else if (dash != string::npos &&
                 base::StringToUint64(blocks.substr(0, dash), &block_start) &&
                 base::StringToUint64(blocks.substr(dash + 1), &block_end)) {
        if (block_end < block_start) {
          LOG(ERROR) << "End block " << block_end
                     << " is smaller than start block " << block_start
                     << std::endl
                     << line;
          return false;
        }
        if (block_end > static_cast<uint64_t>(num_blocks_)) {
          LOG(ERROR) << "The end block " << block_end
                     << " is past the end of the file of " << num_blocks_
                     << " blocks" << std::endl
                     << line;
          return false;
        }
        mapped_file.extents.push_back(
            ExtentForRange(block_start, block_end - block_start + 1));
      } else {
        // If we can't parse N or N-M, we assume the block is actually part of
        // the name of the file.
        break;
      }
      last_delim = delim;
    }
    // We parsed the blocks from the end of the line, so we need to reverse
    // the Extents in the file.
    std::reverse(mapped_file.extents.begin(), mapped_file.extents.end());

    if (last_delim == string::npos)
      continue;
    mapped_file.name = line.substr(0, last_delim).as_string();

    files->push_back(mapped_file);
  }

  return true;
}

bool MapfileFilesystem::LoadSettings(brillo::KeyValueStore* store) const {
  // Settings not supported in mapfile since the storage format is unknown.
  LOG(ERROR) << "mapfile doesn't support LoadSettings().";
  return false;
}

}  // namespace chromeos_update_engine
