/*
 * Copyright (C) 2017 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.
 */

#ifndef ART_LIBDEXFILE_DEX_DEX_FILE_LOADER_H_
#define ART_LIBDEXFILE_DEX_DEX_FILE_LOADER_H_

#include <cstdint>
#include <functional>
#include <memory>
#include <optional>
#include <string>
#include <vector>

#include "base/os.h"
#include "base/unix_file/fd_file.h"
#include "dex_file.h"

namespace art {

class MemMap;
class OatDexFile;
class ScopedTrace;
class ZipArchive;

enum class DexFileLoaderErrorCode {
  kNoError,
  kEntryNotFound,
  kExtractToMemoryError,
  kDexFileError,
  kMakeReadOnlyError,
  kVerifyError
};

// Class that is used to open dex files and deal with corresponding multidex and location logic.
class DexFileLoader {
 public:
  // name of the DexFile entry within a zip archive
  static constexpr const char* kClassesDex = "classes.dex";

  // The separator character in MultiDex locations.
  static constexpr char kMultiDexSeparator = '!';

  // Return true if the magic is valid for dex or cdex.
  static bool IsMagicValid(uint32_t magic);
  static bool IsMagicValid(const uint8_t* magic);

  // Return true if the corresponding version and magic is valid.
  static bool IsVersionAndMagicValid(const uint8_t* magic);

  // Check whether a location denotes a multidex dex file. This is a very simple check: returns
  // whether the string contains the separator character.
  static bool IsMultiDexLocation(const char* location);

  // Return the name of the index-th classes.dex in a multidex zip file. This is classes.dex for
  // index == 0, and classes{index + 1}.dex else.
  static std::string GetMultiDexClassesDexName(size_t index);

  // Return the (possibly synthetic) dex location for a multidex entry. This is dex_location for
  // index == 0, and dex_location + multi-dex-separator + GetMultiDexClassesDexName(index) else.
  static std::string GetMultiDexLocation(size_t index, const char* dex_location);

  // Returns the canonical form of the given dex location.
  //
  // There are different flavors of "dex locations" as follows:
  // the file name of a dex file:
  //     The actual file path that the dex file has on disk.
  // dex_location:
  //     This acts as a key for the class linker to know which dex file to load.
  //     It may correspond to either an old odex file or a particular dex file
  //     inside an oat file. In the first case it will also match the file name
  //     of the dex file. In the second case (oat) it will include the file name
  //     and possibly some multidex annotation to uniquely identify it.
  // canonical_dex_location:
  //     the dex_location where its file name part has been made canonical.
  static std::string GetDexCanonicalLocation(const char* dex_location);

  // For normal dex files, location and base location coincide. If a dex file is part of a multidex
  // archive, the base location is the name of the originating jar/apk, stripped of any internal
  // classes*.dex path.
  static std::string GetBaseLocation(const char* location) {
    const char* pos = strrchr(location, kMultiDexSeparator);
    return (pos == nullptr) ? location : std::string(location, pos - location);
  }

  static std::string GetBaseLocation(const std::string& location) {
    return GetBaseLocation(location.c_str());
  }

  // Returns the '!classes*.dex' part of the dex location. Returns an empty
  // string if there is no multidex suffix for the given location.
  // The kMultiDexSeparator is included in the returned suffix.
  static std::string GetMultiDexSuffix(const std::string& location) {
    size_t pos = location.rfind(kMultiDexSeparator);
    return (pos == std::string::npos) ? std::string() : location.substr(pos);
  }

  DexFileLoader(const char* filename, int fd, const std::string& location)
      : filename_(filename),
        file_(fd == -1 ? std::optional<File>() : File(fd, /*check_usage=*/false)),
        location_(location) {}

  DexFileLoader(std::shared_ptr<DexFileContainer> container, const std::string& location)
      : root_container_(std::move(container)), location_(location) {
    DCHECK(root_container_ != nullptr);
  }

  DexFileLoader(const uint8_t* base, size_t size, const std::string& location);

  DexFileLoader(std::vector<uint8_t>&& memory, const std::string& location);

  DexFileLoader(MemMap&& mem_map, const std::string& location);

  DexFileLoader(int fd, const std::string& location)
      : DexFileLoader(/*filename=*/location.c_str(), fd, location) {}

  DexFileLoader(const char* filename, const std::string& location)
      : DexFileLoader(filename, /*fd=*/-1, location) {}

  explicit DexFileLoader(const std::string& location)
      : DexFileLoader(location.c_str(), /*fd=*/-1, location) {}

  virtual ~DexFileLoader() {}

  std::unique_ptr<const DexFile> Open(uint32_t location_checksum,
                                      const OatDexFile* oat_dex_file,
                                      bool verify,
                                      bool verify_checksum,
                                      std::string* error_msg);

  std::unique_ptr<const DexFile> Open(uint32_t location_checksum,
                                      bool verify,
                                      bool verify_checksum,
                                      std::string* error_msg) {
    return Open(location_checksum,
                /*oat_dex_file=*/nullptr,
                verify,
                verify_checksum,
                error_msg);
  }

  // Opens all dex files, guessing the container format based on file magic.
  bool Open(bool verify,
            bool verify_checksum,
            bool allow_no_dex_files,
            DexFileLoaderErrorCode* error_code,
            std::string* error_msg,
            std::vector<std::unique_ptr<const DexFile>>* dex_files);

  bool Open(bool verify,
            bool verify_checksum,
            DexFileLoaderErrorCode* error_code,
            std::string* error_msg,
            std::vector<std::unique_ptr<const DexFile>>* dex_files) {
    return Open(verify,
                verify_checksum,
                /*allow_no_dex_files=*/false,
                error_code,
                error_msg,
                dex_files);
  }

  bool Open(bool verify,
            bool verify_checksum,
            bool allow_no_dex_files,
            std::string* error_msg,
            std::vector<std::unique_ptr<const DexFile>>* dex_files) {
    DexFileLoaderErrorCode error_code;
    return Open(verify, verify_checksum, allow_no_dex_files, &error_code, error_msg, dex_files);
  }

  bool Open(bool verify,
            bool verify_checksum,
            std::string* error_msg,
            std::vector<std::unique_ptr<const DexFile>>* dex_files) {
    DexFileLoaderErrorCode error_code;
    return Open(verify,
                verify_checksum,
                /*allow_no_dex_files=*/false,
                &error_code,
                error_msg,
                dex_files);
  }

 protected:
  bool InitAndReadMagic(uint32_t* magic, std::string* error_msg);

  // Ensure we have root container.  If we are backed by a file, memory-map it.
  // We can only do this for dex files since zip files might be too big to map.
  bool MapRootContainer(std::string* error_msg);

  static std::unique_ptr<DexFile> OpenCommon(std::shared_ptr<DexFileContainer> container,
                                             const uint8_t* base,
                                             size_t size,
                                             const std::string& location,
                                             std::optional<uint32_t> location_checksum,
                                             const OatDexFile* oat_dex_file,
                                             bool verify,
                                             bool verify_checksum,
                                             std::string* error_msg,
                                             DexFileLoaderErrorCode* error_code);

  // Old signature preserved for app-compat.
  std::unique_ptr<const DexFile> Open(const uint8_t* base,
                                      size_t size,
                                      const std::string& location,
                                      uint32_t location_checksum,
                                      const OatDexFile* oat_dex_file,
                                      bool verify,
                                      bool verify_checksum,
                                      std::string* error_msg,
                                      std::unique_ptr<DexFileContainer> container) const;

  // Old signature preserved for app-compat.
  enum VerifyResult {};
  static std::unique_ptr<DexFile> OpenCommon(const uint8_t* base,
                                             size_t size,
                                             const uint8_t* data_base,
                                             size_t data_size,
                                             const std::string& location,
                                             uint32_t location_checksum,
                                             const OatDexFile* oat_dex_file,
                                             bool verify,
                                             bool verify_checksum,
                                             std::string* error_msg,
                                             std::unique_ptr<DexFileContainer> container,
                                             VerifyResult* verify_result);

  // Open .dex files from the entry_name in a zip archive.
  bool OpenFromZipEntry(const ZipArchive& zip_archive,
                        const char* entry_name,
                        const std::string& location,
                        bool verify,
                        bool verify_checksum,
                        DexFileLoaderErrorCode* error_code,
                        std::string* error_msg,
                        std::vector<std::unique_ptr<const DexFile>>* dex_files) const;

  // The DexFileLoader can be backed either by file or by memory (i.e. DexFileContainer).
  // We can not just mmap the file since APKs might be unreasonably large for 32-bit system.
  std::string filename_;
  std::optional<File> file_;
  std::shared_ptr<DexFileContainer> root_container_;
  const std::string location_;
};

}  // namespace art

#endif  // ART_LIBDEXFILE_DEX_DEX_FILE_LOADER_H_
