/*
 * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Oracle nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <assert.h>
#include <string.h>
#include <stdlib.h>

#include "endian.hpp"
#include "imageDecompressor.hpp"
#include "imageFile.hpp"
#include "inttypes.hpp"
#include "jni.h"
#include "osSupport.hpp"

// Map the full jimage, only with 64 bit addressing.
bool ImageFileReader::memory_map_image = sizeof(void *) == 8;

#ifdef WIN32
const char FileSeparator = '\\';
#else
const char FileSeparator = '/';
#endif

// Image files are an alternate file format for storing classes and resources. The
// goal is to supply file access which is faster and smaller than the jar format.
//
// (More detailed nodes in the header.)
//

// Compute the Perfect Hashing hash code for the supplied UTF-8 string.
s4 ImageStrings::hash_code(const char* string, s4 seed) {
    assert(seed > 0 && "invariant");
    // Access bytes as unsigned.
    u1* bytes = (u1*)string;
    u4 useed = (u4)seed;
    // Compute hash code.
    for (u1 byte = *bytes++; byte; byte = *bytes++) {
        useed = (useed * HASH_MULTIPLIER) ^ byte;
    }
    // Ensure the result is not signed.
    return (s4)(useed & 0x7FFFFFFF);
}

// Match up a string in a perfect hash table.
// Returns the index where the name should be.
// Result still needs validation for precise match (false positive.)
s4 ImageStrings::find(Endian* endian, const char* name, s4* redirect, u4 length) {
    // If the table is empty, then short cut.
    if (!redirect || !length) {
        return NOT_FOUND;
    }
    // Compute the basic perfect hash for name.
    s4 hash_code = ImageStrings::hash_code(name);
    // Modulo table size.
    s4 index = hash_code % length;
    // Get redirect entry.
    //   value == 0 then not found
    //   value < 0 then -1 - value is true index
    //   value > 0 then value is seed for recomputing hash.
    s4 value = endian->get(redirect[index]);
    // if recompute is required.
    if (value > 0 ) {
        // Entry collision value, need to recompute hash.
        hash_code = ImageStrings::hash_code(name, value);
        // Modulo table size.
        return hash_code % length;
    } else if (value < 0) {
        // Compute direct index.
        return -1 - value;
    }
    // No entry found.
    return NOT_FOUND;
}

// Test to see if UTF-8 string begins with the start UTF-8 string.  If so,
// return non-NULL address of remaining portion of string.  Otherwise, return
// NULL.    Used to test sections of a path without copying from image string
// table.
const char* ImageStrings::starts_with(const char* string, const char* start) {
    char ch1, ch2;
    // Match up the strings the best we can.
    while ((ch1 = *string) && (ch2 = *start)) {
        if (ch1 != ch2) {
            // Mismatch, return NULL.
            return NULL;
        }
        // Next characters.
        string++, start++;
    }
    // Return remainder of string.
    return string;
}

// Inflates the attribute stream into individual values stored in the long
// array _attributes. This allows an attribute value to be quickly accessed by
// direct indexing.  Unspecified values default to zero (from constructor.)
void ImageLocation::set_data(u1* data) {
    // Deflate the attribute stream into an array of attributes.
    u1 byte;
    // Repeat until end header is found.
    while ((data != NULL) && (byte = *data)) {
        // Extract kind from header byte.
        u1 kind = attribute_kind(byte);
        assert(kind < ATTRIBUTE_COUNT && "invalid image location attribute");
        if (kind == ATTRIBUTE_END) {
            break;
        }
        // Extract length of data (in bytes).
        u1 n = attribute_length(byte);
        // Read value (most significant first.)
        _attributes[kind] = attribute_value(data + 1, n);
        // Position to next attribute by skipping attribute header and data bytes.
        data += n + 1;
    }
}

// Zero all attribute values.
void ImageLocation::clear_data() {
    // Set defaults to zero.
    memset(_attributes, 0, sizeof(_attributes));
}

// ImageModuleData constructor maps out sub-tables for faster access.
ImageModuleData::ImageModuleData(const ImageFileReader* image_file) :
        _image_file(image_file),
        _endian(image_file->endian()) {
}

// Release module data resource.
ImageModuleData::~ImageModuleData() {
}


// Return the module in which a package resides.    Returns NULL if not found.
const char* ImageModuleData::package_to_module(const char* package_name) {
    // replace all '/' by '.'
    char* replaced = new char[(int) strlen(package_name) + 1];
    assert(replaced != NULL && "allocation failed");
    int i;
    for (i = 0; package_name[i] != '\0'; i++) {
      replaced[i] = package_name[i] == '/' ? '.' : package_name[i];
    }
    replaced[i] = '\0';

    // build path /packages/<package_name>
    const char* radical = "/packages/";
    char* path = new char[(int) strlen(radical) + (int) strlen(package_name) + 1];
    assert(path != NULL && "allocation failed");
    strcpy(path, radical);
    strcat(path, replaced);
    delete[] replaced;

    // retrieve package location
    ImageLocation location;
    bool found = _image_file->find_location(path, location);
    delete[] path;
    if (!found) {
        return NULL;
    }

    // retrieve offsets to module name
    int size = (int)location.get_attribute(ImageLocation::ATTRIBUTE_UNCOMPRESSED);
    u1* content = new u1[size];
    assert(content != NULL && "allocation failed");
    _image_file->get_resource(location, content);
    u1* ptr = content;
    // sequence of sizeof(8) isEmpty|offset. Use the first module that is not empty.
    u4 offset = 0;
    for (i = 0; i < size; i+=8) {
        u4 isEmpty = _endian->get(*((u4*)ptr));
        ptr += 4;
        if (!isEmpty) {
            offset = _endian->get(*((u4*)ptr));
            break;
        }
        ptr += 4;
    }
    delete[] content;
    return _image_file->get_strings().get(offset);
}

// Manage a table of open image files.  This table allows multiple access points
// to share an open image.
ImageFileReaderTable::ImageFileReaderTable() : _count(0), _max(_growth) {
    _table = static_cast<ImageFileReader**>(calloc(_max, sizeof(ImageFileReader*)));
    assert(_table != NULL && "allocation failed");
}

// Add a new image entry to the table.
void ImageFileReaderTable::add(ImageFileReader* image) {
    if (_count == _max) {
        _max += _growth;
        _table = static_cast<ImageFileReader**>(realloc(_table, _max * sizeof(ImageFileReader*)));
    }
    _table[_count++] = image;
}

// Remove an image entry from the table.
void ImageFileReaderTable::remove(ImageFileReader* image) {
    for (u4 i = 0; i < _count; i++) {
        if (_table[i] == image) {
            // Swap the last element into the found slot
            _table[i] = _table[--_count];
            break;
        }
    }

    if (_count != 0 && _count == _max - _growth) {
        _max -= _growth;
        _table = static_cast<ImageFileReader**>(realloc(_table, _max * sizeof(ImageFileReader*)));
    }
}

// Determine if image entry is in table.
bool ImageFileReaderTable::contains(ImageFileReader* image) {
    for (u4 i = 0; i < _count; i++) {
        if (_table[i] == image) {
            return true;
        }
    }
    return false;
}

// Table to manage multiple opens of an image file.
ImageFileReaderTable ImageFileReader::_reader_table;

SimpleCriticalSection _reader_table_lock;

// Locate an image if file already open.
ImageFileReader* ImageFileReader::find_image(const char* name) {
    // Lock out _reader_table.
    SimpleCriticalSectionLock cs(&_reader_table_lock);
    // Search for an exist image file.
    for (u4 i = 0; i < _reader_table.count(); i++) {
        // Retrieve table entry.
        ImageFileReader* reader = _reader_table.get(i);
        // If name matches, then reuse (bump up use count.)
        assert(reader->name() != NULL && "reader->name must not be null");
        if (strcmp(reader->name(), name) == 0) {
            reader->inc_use();
            return reader;
        }
    }

    return NULL;
}

// Open an image file, reuse structure if file already open.
ImageFileReader* ImageFileReader::open(const char* name, bool big_endian) {
    ImageFileReader* reader = find_image(name);
    if (reader != NULL) {
        return reader;
    }

    // Need a new image reader.
    reader = new ImageFileReader(name, big_endian);
    if (reader == NULL || !reader->open()) {
        // Failed to open.
        delete reader;
        return NULL;
    }

    // Lock to update
    SimpleCriticalSectionLock cs(&_reader_table_lock);
    // Search for an existing image file.
    for (u4 i = 0; i < _reader_table.count(); i++) {
        // Retrieve table entry.
        ImageFileReader* existing_reader = _reader_table.get(i);
        // If name matches, then reuse (bump up use count.)
        assert(reader->name() != NULL && "reader->name still must not be null");
        if (strcmp(existing_reader->name(), name) == 0) {
            existing_reader->inc_use();
            reader->close();
            delete reader;
            return existing_reader;
        }
    }
    // Bump use count and add to table.
    reader->inc_use();
    _reader_table.add(reader);
    return reader;
}

// Close an image file if the file is not in use elsewhere.
void ImageFileReader::close(ImageFileReader *reader) {
    // Lock out _reader_table.
    SimpleCriticalSectionLock cs(&_reader_table_lock);
    // If last use then remove from table and then close.
    if (reader->dec_use()) {
        _reader_table.remove(reader);
        delete reader;
    }
}

// Return an id for the specified ImageFileReader.
u8 ImageFileReader::reader_to_ID(ImageFileReader *reader) {
    // ID is just the cloaked reader address.
    return (u8)reader;
}

// Validate the image id.
bool ImageFileReader::id_check(u8 id) {
    // Make sure the ID is a managed (_reader_table) reader.
    SimpleCriticalSectionLock cs(&_reader_table_lock);
    return _reader_table.contains((ImageFileReader*)id);
}

// Return an id for the specified ImageFileReader.
ImageFileReader* ImageFileReader::id_to_reader(u8 id) {
    assert(id_check(id) && "invalid image id");
    return (ImageFileReader*)id;
}

// Constructor initializes to a closed state.
ImageFileReader::ImageFileReader(const char* name, bool big_endian) :
    _module_data(NULL) {
    // Copy the image file name.
     int len = (int) strlen(name) + 1;
    _name = new char[len];
    assert(_name != NULL  && "allocation failed");
    strncpy(_name, name, len);
    // Initialize for a closed file.
    _fd = -1;
    _endian = Endian::get_handler(big_endian);
    _index_data = NULL;
}

// Close image and free up data structures.
ImageFileReader::~ImageFileReader() {
    // Ensure file is closed.
    close();
    // Free up name.
    if (_name) {
        delete[] _name;
        _name = NULL;
    }

    if (_module_data != NULL) {
        delete _module_data;
    }
}

// Open image file for read access.
bool ImageFileReader::open() {
    // If file exists open for reading.
    _fd = osSupport::openReadOnly(_name);
    if (_fd == -1) {
        return false;
    }
    // Retrieve the file size.
    _file_size = osSupport::size(_name);
    // Read image file header and verify it has a valid header.
    size_t header_size = sizeof(ImageHeader);
    if (_file_size < header_size ||
        !read_at((u1*)&_header, header_size, 0) ||
        _header.magic(_endian) != IMAGE_MAGIC ||
        _header.major_version(_endian) != MAJOR_VERSION ||
        _header.minor_version(_endian) != MINOR_VERSION) {
        close();
        return false;
    }
    // Size of image index.
    _index_size = index_size();
    // Make sure file is large enough to contain the index.
    if (_file_size < _index_size) {
        return false;
    }
    // Memory map image (minimally the index.)
    _index_data = (u1*)osSupport::map_memory(_fd, _name, 0, (size_t)map_size());
    assert(_index_data && "image file not memory mapped");
    // Retrieve length of index perfect hash table.
    u4 length = table_length();
    // Compute offset of the perfect hash table redirect table.
    u4 redirect_table_offset = (u4)header_size;
    // Compute offset of index attribute offsets.
    u4 offsets_table_offset = redirect_table_offset + length * (u4)sizeof(s4);
    // Compute offset of index location attribute data.
    u4 location_bytes_offset = offsets_table_offset + length * (u4)sizeof(u4);
    // Compute offset of index string table.
    u4 string_bytes_offset = location_bytes_offset + locations_size();
    // Compute address of the perfect hash table redirect table.
    _redirect_table = (s4*)(_index_data + redirect_table_offset);
    // Compute address of index attribute offsets.
    _offsets_table = (u4*)(_index_data + offsets_table_offset);
    // Compute address of index location attribute data.
    _location_bytes = _index_data + location_bytes_offset;
    // Compute address of index string table.
    _string_bytes = _index_data + string_bytes_offset;

    // Initialize the module data
    _module_data = new ImageModuleData(this);
    // Successful open (if memory allocation succeeded).
    return _module_data != NULL;
}

// Close image file.
void ImageFileReader::close() {
    // Deallocate the index.
    if (_index_data) {
        osSupport::unmap_memory((char*)_index_data, (size_t)map_size());
        _index_data = NULL;
    }
    // Close file.
    if (_fd != -1) {
        osSupport::close(_fd);
        _fd = -1;
    }

    if (_module_data != NULL) {
        delete _module_data;
        _module_data = NULL;
    }
}

// Read directly from the file.
bool ImageFileReader::read_at(u1* data, u8 size, u8 offset) const {
    return (u8)osSupport::read(_fd, (char*)data, size, offset) == size;
}

// Find the location attributes associated with the path.    Returns true if
// the location is found, false otherwise.
bool ImageFileReader::find_location(const char* path, ImageLocation& location) const {
    // Locate the entry in the index perfect hash table.
    s4 index = ImageStrings::find(_endian, path, _redirect_table, table_length());
    // If is found.
    if (index != ImageStrings::NOT_FOUND) {
        // Get address of first byte of location attribute stream.
        u1* data = get_location_data(index);
        // Expand location attributes.
        location.set_data(data);
        // Make sure result is not a false positive.
        return verify_location(location, path);
    }
    return false;
}

// Find the location index and size associated with the path.
// Returns the location index and size if the location is found, 0 otherwise.
u4 ImageFileReader::find_location_index(const char* path, u8 *size) const {
    // Locate the entry in the index perfect hash table.
    s4 index = ImageStrings::find(_endian, path, _redirect_table, table_length());
    // If found.
    if (index != ImageStrings::NOT_FOUND) {
        // Get address of first byte of location attribute stream.
        u4 offset = get_location_offset(index);
        u1* data = get_location_offset_data(offset);
        // Expand location attributes.
        ImageLocation location(data);
        // Make sure result is not a false positive.
        if (verify_location(location, path)) {
                *size = (jlong)location.get_attribute(ImageLocation::ATTRIBUTE_UNCOMPRESSED);
                return offset;
        }
    }
    return 0;            // not found
}

// Verify that a found location matches the supplied path (without copying.)
bool ImageFileReader::verify_location(ImageLocation& location, const char* path) const {
    // Manage the image string table.
    ImageStrings strings(_string_bytes, _header.strings_size(_endian));
    // Position to first character of the path string.
    const char* next = path;
    // Get module name string.
    const char* module = location.get_attribute(ImageLocation::ATTRIBUTE_MODULE, strings);
    // If module string is not empty.
    if (*module != '\0') {
        // Compare '/module/' .
        if (*next++ != '/') return false;
        if (!(next = ImageStrings::starts_with(next, module))) return false;
        if (*next++ != '/') return false;
    }
    // Get parent (package) string
    const char* parent = location.get_attribute(ImageLocation::ATTRIBUTE_PARENT, strings);
    // If parent string is not empty string.
    if (*parent != '\0') {
        // Compare 'parent/' .
        if (!(next = ImageStrings::starts_with(next, parent))) return false;
        if (*next++ != '/') return false;
    }
    // Get base name string.
    const char* base = location.get_attribute(ImageLocation::ATTRIBUTE_BASE, strings);
    // Compare with basne name.
    if (!(next = ImageStrings::starts_with(next, base))) return false;
    // Get extension string.
    const char* extension = location.get_attribute(ImageLocation::ATTRIBUTE_EXTENSION, strings);
    // If extension is not empty.
    if (*extension != '\0') {
        // Compare '.extension' .
        if (*next++ != '.') return false;
        if (!(next = ImageStrings::starts_with(next, extension))) return false;
    }
    // True only if complete match and no more characters.
    return *next == '\0';
}

// Return the resource for the supplied location offset.
void ImageFileReader::get_resource(u4 offset, u1* uncompressed_data) const {
        // Get address of first byte of location attribute stream.
        u1* data = get_location_offset_data(offset);
        // Expand location attributes.
        ImageLocation location(data);
        // Read the data
        get_resource(location, uncompressed_data);
}

// Return the resource for the supplied location.
void ImageFileReader::get_resource(ImageLocation& location, u1* uncompressed_data) const {
    // Retrieve the byte offset and size of the resource.
    u8 offset = location.get_attribute(ImageLocation::ATTRIBUTE_OFFSET);
    u8 uncompressed_size = location.get_attribute(ImageLocation::ATTRIBUTE_UNCOMPRESSED);
    u8 compressed_size = location.get_attribute(ImageLocation::ATTRIBUTE_COMPRESSED);
    // If the resource is compressed.
    if (compressed_size != 0) {
        u1* compressed_data;
        // If not memory mapped read in bytes.
        if (!memory_map_image) {
            // Allocate buffer for compression.
            compressed_data = new u1[(size_t)compressed_size];
            assert(compressed_data != NULL && "allocation failed");
            // Read bytes from offset beyond the image index.
            bool is_read = read_at(compressed_data, compressed_size, _index_size + offset);
            assert(is_read && "error reading from image or short read");
        } else {
            compressed_data = get_data_address() + offset;
        }
        // Get image string table.
        const ImageStrings strings = get_strings();
        // Decompress resource.
        ImageDecompressor::decompress_resource(compressed_data, uncompressed_data, uncompressed_size,
                        &strings, _endian);
        // If not memory mapped then release temporary buffer.
        if (!memory_map_image) {
                delete[] compressed_data;
        }
    } else {
        // Read bytes from offset beyond the image index.
        bool is_read = read_at(uncompressed_data, uncompressed_size, _index_size + offset);
        assert(is_read && "error reading from image or short read");
    }
}

// Return the ImageModuleData for this image
ImageModuleData * ImageFileReader::get_image_module_data() {
    return _module_data;
}
