Remove some old forge hacks
Forge apparently removed all `.pack.xz` files without warning. It broke a bunch of stuff, as always. But it also means we don't need some ugly code anymore. This is removed: - Support for 'forge-pack-xz' and the forge-specific file download compression. - The pack200 library we no longer need. This stays: - The LZMA decompression library - we may still want to use it.
This commit is contained in:
parent
9eaa636908
commit
e7f79c9076
@ -248,7 +248,6 @@ add_subdirectory(libraries/launcher) # java based launcher part for Minecraft
|
||||
add_subdirectory(libraries/javacheck) # java compatibility checker
|
||||
add_subdirectory(libraries/xz-embedded) # xz compression
|
||||
add_subdirectory(libraries/quazip) # zip manipulation library
|
||||
add_subdirectory(libraries/pack200) # java pack200 compression
|
||||
add_subdirectory(libraries/rainbow) # Qt extension for colors
|
||||
add_subdirectory(libraries/iconfix) # fork of Qt's QIcon loader
|
||||
add_subdirectory(libraries/LocalPeer) # fork of a library from Qt solutions
|
||||
|
29
COPYING.md
29
COPYING.md
@ -128,35 +128,6 @@
|
||||
This license is copied below, and is also available with a FAQ at:
|
||||
http://scripts.sil.org/OFL
|
||||
|
||||
# Pack200
|
||||
|
||||
The GNU General Public License (GPL)
|
||||
|
||||
Version 2, June 1991
|
||||
|
||||
+ "CLASSPATH" EXCEPTION TO THE GPL
|
||||
|
||||
Certain source files distributed by Oracle America and/or its affiliates are
|
||||
subject to the following clarification and special exception to the GPL, but
|
||||
only where Oracle has expressly included in the particular source file's header
|
||||
the words "Oracle designates this particular file as subject to the "Classpath"
|
||||
exception as provided by Oracle in the LICENSE file that accompanied this code."
|
||||
|
||||
Linking this library statically or dynamically with other modules is making
|
||||
a combined work based on this library. Thus, the terms and conditions of
|
||||
the GNU General Public License cover the whole combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent modules,
|
||||
and to copy and distribute the resulting executable under terms of your
|
||||
choice, provided that you also meet, for each linked independent module,
|
||||
the terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library. If
|
||||
you modify this library, you may extend this exception to your version of
|
||||
the library, but you are not obligated to do so. If you do not wish to do
|
||||
so, delete this exception statement from your version.
|
||||
|
||||
# Quazip
|
||||
|
||||
Copyright (C) 2005-2011 Sergey A. Tachenov
|
||||
|
@ -305,10 +305,6 @@ set(MINECRAFT_SOURCES
|
||||
minecraft/AssetsUtils.h
|
||||
minecraft/AssetsUtils.cpp
|
||||
|
||||
# Forge and all things forge related
|
||||
minecraft/forge/ForgeXzDownload.h
|
||||
minecraft/forge/ForgeXzDownload.cpp
|
||||
|
||||
# Skin upload utilities
|
||||
minecraft/SkinUpload.cpp
|
||||
minecraft/SkinUpload.h
|
||||
@ -495,7 +491,7 @@ set_target_properties(MultiMC_logic PROPERTIES CXX_VISIBILITY_PRESET hidden VISI
|
||||
generate_export_header(MultiMC_logic)
|
||||
|
||||
# Link
|
||||
target_link_libraries(MultiMC_logic xz-embedded MultiMC_unpack200 systeminfo MultiMC_quazip MultiMC_classparser ${NBT_NAME} ${ZLIB_LIBRARIES})
|
||||
target_link_libraries(MultiMC_logic systeminfo MultiMC_quazip MultiMC_classparser ${NBT_NAME} ${ZLIB_LIBRARIES})
|
||||
target_link_libraries(MultiMC_logic Qt5::Core Qt5::Xml Qt5::Network Qt5::Concurrent)
|
||||
|
||||
# Mark and export headers
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
#include <net/Download.h>
|
||||
#include <net/ChecksumValidator.h>
|
||||
#include <minecraft/forge/ForgeXzDownload.h>
|
||||
#include <Env.h>
|
||||
#include <FileSystem.h>
|
||||
|
||||
@ -88,26 +87,19 @@ QList< std::shared_ptr< NetAction > > Library::getDownloads(
|
||||
{
|
||||
options |= Net::Download::Option::AcceptLocalFiles;
|
||||
}
|
||||
if (isForge())
|
||||
|
||||
if(sha1.size())
|
||||
{
|
||||
qDebug() << "XzDownload for:" << rawName() << "storage:" << storage << "url:" << url;
|
||||
out.append(ForgeXzDownload::make(url, storage, entry));
|
||||
auto rawSha1 = QByteArray::fromHex(sha1.toLatin1());
|
||||
auto dl = Net::Download::makeCached(url, entry, options);
|
||||
dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, rawSha1));
|
||||
qDebug() << "Checksummed Download for:" << rawName() << "storage:" << storage << "url:" << url;
|
||||
out.append(dl);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(sha1.size())
|
||||
{
|
||||
auto rawSha1 = QByteArray::fromHex(sha1.toLatin1());
|
||||
auto dl = Net::Download::makeCached(url, entry, options);
|
||||
dl->addValidator(new Net::ChecksumValidator(QCryptographicHash::Sha1, rawSha1));
|
||||
qDebug() << "Checksummed Download for:" << rawName() << "storage:" << storage << "url:" << url;
|
||||
out.append(dl);
|
||||
}
|
||||
else
|
||||
{
|
||||
out.append(Net::Download::makeCached(url, entry, options));
|
||||
qDebug() << "Download for:" << rawName() << "storage:" << storage << "url:" << url;
|
||||
}
|
||||
out.append(Net::Download::makeCached(url, entry, options));
|
||||
qDebug() << "Download for:" << rawName() << "storage:" << storage << "url:" << url;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
@ -243,11 +235,6 @@ bool Library::isAlwaysStale() const
|
||||
return m_hint == "always-stale";
|
||||
}
|
||||
|
||||
bool Library::isForge() const
|
||||
{
|
||||
return m_hint == "forge-pack-xz";
|
||||
}
|
||||
|
||||
void Library::setStoragePrefix(QString prefix)
|
||||
{
|
||||
m_storagePrefix = prefix;
|
||||
|
@ -14,7 +14,6 @@
|
||||
*/
|
||||
|
||||
#include "Env.h"
|
||||
#include <minecraft/forge/ForgeXzDownload.h>
|
||||
#include "MinecraftUpdate.h"
|
||||
#include "MinecraftInstance.h"
|
||||
|
||||
|
@ -1,393 +0,0 @@
|
||||
/* Copyright 2013-2019 MultiMC Contributors
|
||||
*
|
||||
* 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 "Env.h"
|
||||
#include "ForgeXzDownload.h"
|
||||
#include <FileSystem.h>
|
||||
|
||||
#include <QCryptographicHash>
|
||||
#include <QFileInfo>
|
||||
#include <QDateTime>
|
||||
#include <QDir>
|
||||
#include <QDebug>
|
||||
|
||||
ForgeXzDownload::ForgeXzDownload(QString url, QString relative_path, MetaEntryPtr entry) : NetAction()
|
||||
{
|
||||
m_entry = entry;
|
||||
m_target_path = entry->getFullPath();
|
||||
m_pack200_xz_file.setFileTemplate("./dl_temp.XXXXXX");
|
||||
m_status = Job_NotStarted;
|
||||
m_url_path = relative_path;
|
||||
m_url = url + ".pack.xz";
|
||||
}
|
||||
|
||||
void ForgeXzDownload::start()
|
||||
{
|
||||
if(m_status == Job_Aborted)
|
||||
{
|
||||
qWarning() << "Attempt to start an aborted Download:" << m_url.toString();
|
||||
emit aborted(m_index_within_job);
|
||||
return;
|
||||
}
|
||||
m_status = Job_InProgress;
|
||||
if (!m_entry->isStale())
|
||||
{
|
||||
m_status = Job_Finished;
|
||||
emit succeeded(m_index_within_job);
|
||||
return;
|
||||
}
|
||||
// can we actually create the real, final file?
|
||||
if (!FS::ensureFilePathExists(m_target_path))
|
||||
{
|
||||
m_status = Job_Failed;
|
||||
emit failed(m_index_within_job);
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << "Downloading " << m_url.toString();
|
||||
QNetworkRequest request(m_url);
|
||||
request.setRawHeader(QString("If-None-Match").toLatin1(), m_entry->getETag().toLatin1());
|
||||
request.setHeader(QNetworkRequest::UserAgentHeader, "MultiMC/5.0 (Cached)");
|
||||
|
||||
QNetworkReply *rep = ENV.qnam().get(request);
|
||||
|
||||
m_reply.reset(rep);
|
||||
connect(rep, SIGNAL(downloadProgress(qint64, qint64)), SLOT(downloadProgress(qint64, qint64)));
|
||||
connect(rep, SIGNAL(finished()), SLOT(downloadFinished()));
|
||||
connect(rep, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(downloadError(QNetworkReply::NetworkError)));
|
||||
connect(rep, SIGNAL(readyRead()), SLOT(downloadReadyRead()));
|
||||
}
|
||||
|
||||
void ForgeXzDownload::downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
|
||||
{
|
||||
m_total_progress = bytesTotal;
|
||||
m_progress = bytesReceived;
|
||||
emit netActionProgress(m_index_within_job, bytesReceived, bytesTotal);
|
||||
}
|
||||
|
||||
void ForgeXzDownload::downloadError(QNetworkReply::NetworkError error)
|
||||
{
|
||||
if(error == QNetworkReply::OperationCanceledError)
|
||||
{
|
||||
qCritical() << "Aborted " << m_url.toString();
|
||||
m_status = Job_Aborted;
|
||||
}
|
||||
else
|
||||
{
|
||||
// error happened during download.
|
||||
qCritical() << "Failed " << m_url.toString() << " with reason " << error;
|
||||
m_status = Job_Failed;
|
||||
}
|
||||
}
|
||||
|
||||
void ForgeXzDownload::failAndTryNextMirror()
|
||||
{
|
||||
m_status = Job_Failed;
|
||||
emit failed(m_index_within_job);
|
||||
}
|
||||
|
||||
void ForgeXzDownload::downloadFinished()
|
||||
{
|
||||
// if the download succeeded
|
||||
if (m_status != Job_Failed && m_status != Job_Aborted)
|
||||
{
|
||||
// nothing went wrong...
|
||||
m_status = Job_Finished;
|
||||
if (m_pack200_xz_file.isOpen())
|
||||
{
|
||||
// we actually downloaded something! process and isntall it
|
||||
decompressAndInstall();
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// something bad happened -- on the local machine!
|
||||
m_status = Job_Failed;
|
||||
m_pack200_xz_file.remove();
|
||||
m_reply.reset();
|
||||
emit failed(m_index_within_job);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if(m_status == Job_Aborted)
|
||||
{
|
||||
m_pack200_xz_file.remove();
|
||||
m_reply.reset();
|
||||
emit failed(m_index_within_job);
|
||||
emit aborted(m_index_within_job);
|
||||
return;
|
||||
}
|
||||
// else the download failed
|
||||
else
|
||||
{
|
||||
m_status = Job_Failed;
|
||||
m_pack200_xz_file.close();
|
||||
m_pack200_xz_file.remove();
|
||||
m_reply.reset();
|
||||
failAndTryNextMirror();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void ForgeXzDownload::downloadReadyRead()
|
||||
{
|
||||
|
||||
if (!m_pack200_xz_file.isOpen())
|
||||
{
|
||||
if (!m_pack200_xz_file.open())
|
||||
{
|
||||
/*
|
||||
* Can't open the file... the job failed
|
||||
*/
|
||||
m_reply->abort();
|
||||
emit failed(m_index_within_job);
|
||||
return;
|
||||
}
|
||||
}
|
||||
m_pack200_xz_file.write(m_reply->readAll());
|
||||
}
|
||||
|
||||
#include "xz.h"
|
||||
#include "unpack200.h"
|
||||
#include <stdexcept>
|
||||
#include <unistd.h>
|
||||
|
||||
const size_t buffer_size = 8196;
|
||||
|
||||
// NOTE: once this gets here, it can't be aborted anymore. we don't care.
|
||||
void ForgeXzDownload::decompressAndInstall()
|
||||
{
|
||||
// rewind the downloaded temp file
|
||||
m_pack200_xz_file.seek(0);
|
||||
// de-xz'd file
|
||||
QTemporaryFile pack200_file("./dl_temp.XXXXXX");
|
||||
pack200_file.open();
|
||||
|
||||
bool xz_success = false;
|
||||
// first, de-xz
|
||||
{
|
||||
uint8_t in[buffer_size];
|
||||
uint8_t out[buffer_size];
|
||||
struct xz_buf b;
|
||||
struct xz_dec *s;
|
||||
enum xz_ret ret;
|
||||
xz_crc32_init();
|
||||
xz_crc64_init();
|
||||
s = xz_dec_init(XZ_DYNALLOC, 1 << 26);
|
||||
if (s == nullptr)
|
||||
{
|
||||
xz_dec_end(s);
|
||||
failAndTryNextMirror();
|
||||
return;
|
||||
}
|
||||
b.in = in;
|
||||
b.in_pos = 0;
|
||||
b.in_size = 0;
|
||||
b.out = out;
|
||||
b.out_pos = 0;
|
||||
b.out_size = buffer_size;
|
||||
while (!xz_success)
|
||||
{
|
||||
if (b.in_pos == b.in_size)
|
||||
{
|
||||
b.in_size = m_pack200_xz_file.read((char *)in, sizeof(in));
|
||||
b.in_pos = 0;
|
||||
}
|
||||
|
||||
ret = xz_dec_run(s, &b);
|
||||
|
||||
if (b.out_pos == sizeof(out))
|
||||
{
|
||||
auto wresult = pack200_file.write((char *)out, b.out_pos);
|
||||
if (wresult < 0 || size_t(wresult) != b.out_pos)
|
||||
{
|
||||
// msg = "Write error\n";
|
||||
xz_dec_end(s);
|
||||
failAndTryNextMirror();
|
||||
return;
|
||||
}
|
||||
|
||||
b.out_pos = 0;
|
||||
}
|
||||
|
||||
if (ret == XZ_OK)
|
||||
continue;
|
||||
|
||||
if (ret == XZ_UNSUPPORTED_CHECK)
|
||||
{
|
||||
// unsupported check. this is OK, but we should log this
|
||||
continue;
|
||||
}
|
||||
|
||||
auto wresult = pack200_file.write((char *)out, b.out_pos);
|
||||
if (wresult < 0 || size_t(wresult) != b.out_pos)
|
||||
{
|
||||
// write error
|
||||
pack200_file.close();
|
||||
xz_dec_end(s);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (ret)
|
||||
{
|
||||
case XZ_STREAM_END:
|
||||
xz_dec_end(s);
|
||||
xz_success = true;
|
||||
break;
|
||||
|
||||
case XZ_MEM_ERROR:
|
||||
qCritical() << "Memory allocation failed\n";
|
||||
xz_dec_end(s);
|
||||
failAndTryNextMirror();
|
||||
return;
|
||||
|
||||
case XZ_MEMLIMIT_ERROR:
|
||||
qCritical() << "Memory usage limit reached\n";
|
||||
xz_dec_end(s);
|
||||
failAndTryNextMirror();
|
||||
return;
|
||||
|
||||
case XZ_FORMAT_ERROR:
|
||||
qCritical() << "Not a .xz file\n";
|
||||
xz_dec_end(s);
|
||||
failAndTryNextMirror();
|
||||
return;
|
||||
|
||||
case XZ_OPTIONS_ERROR:
|
||||
qCritical() << "Unsupported options in the .xz headers\n";
|
||||
xz_dec_end(s);
|
||||
failAndTryNextMirror();
|
||||
return;
|
||||
|
||||
case XZ_DATA_ERROR:
|
||||
case XZ_BUF_ERROR:
|
||||
qCritical() << "File is corrupt\n";
|
||||
xz_dec_end(s);
|
||||
failAndTryNextMirror();
|
||||
return;
|
||||
|
||||
default:
|
||||
qCritical() << "Bug!\n";
|
||||
xz_dec_end(s);
|
||||
failAndTryNextMirror();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
m_pack200_xz_file.remove();
|
||||
|
||||
// revert pack200
|
||||
pack200_file.seek(0);
|
||||
int handle_in = pack200_file.handle();
|
||||
// FIXME: dispose of file handles, pointers and the like. Ideally wrap in objects.
|
||||
if(handle_in == -1)
|
||||
{
|
||||
qCritical() << "Error reopening " << pack200_file.fileName();
|
||||
failAndTryNextMirror();
|
||||
return;
|
||||
}
|
||||
int handle_in_dup = dup (handle_in);
|
||||
if(handle_in_dup == -1)
|
||||
{
|
||||
qCritical() << "Error reopening " << pack200_file.fileName();
|
||||
failAndTryNextMirror();
|
||||
return;
|
||||
}
|
||||
FILE *file_in = fdopen (handle_in_dup, "rb");
|
||||
if(!file_in)
|
||||
{
|
||||
qCritical() << "Error reopening " << pack200_file.fileName();
|
||||
failAndTryNextMirror();
|
||||
return;
|
||||
}
|
||||
QFile qfile_out(m_target_path);
|
||||
if(!qfile_out.open(QIODevice::WriteOnly))
|
||||
{
|
||||
qCritical() << "Error opening " << qfile_out.fileName();
|
||||
failAndTryNextMirror();
|
||||
return;
|
||||
}
|
||||
int handle_out = qfile_out.handle();
|
||||
if(handle_out == -1)
|
||||
{
|
||||
qCritical() << "Error opening " << qfile_out.fileName();
|
||||
failAndTryNextMirror();
|
||||
return;
|
||||
}
|
||||
int handle_out_dup = dup (handle_out);
|
||||
if(handle_out_dup == -1)
|
||||
{
|
||||
qCritical() << "Error reopening " << qfile_out.fileName();
|
||||
failAndTryNextMirror();
|
||||
return;
|
||||
}
|
||||
FILE *file_out = fdopen (handle_out_dup, "wb");
|
||||
if(!file_out)
|
||||
{
|
||||
qCritical() << "Error opening " << qfile_out.fileName();
|
||||
failAndTryNextMirror();
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
// NOTE: this takes ownership of both FILE pointers. That's why we duplicate them above.
|
||||
unpack_200(file_in, file_out);
|
||||
}
|
||||
catch (const std::runtime_error &err)
|
||||
{
|
||||
m_status = Job_Failed;
|
||||
qCritical() << "Error unpacking " << pack200_file.fileName() << " : " << err.what();
|
||||
QFile f(m_target_path);
|
||||
if (f.exists())
|
||||
f.remove();
|
||||
failAndTryNextMirror();
|
||||
return;
|
||||
}
|
||||
pack200_file.remove();
|
||||
|
||||
QFile jar_file(m_target_path);
|
||||
|
||||
if (!jar_file.open(QIODevice::ReadOnly))
|
||||
{
|
||||
jar_file.remove();
|
||||
failAndTryNextMirror();
|
||||
return;
|
||||
}
|
||||
auto hash = QCryptographicHash::hash(jar_file.readAll(), QCryptographicHash::Md5);
|
||||
m_entry->setMD5Sum(hash.toHex().constData());
|
||||
jar_file.close();
|
||||
|
||||
QFileInfo output_file_info(m_target_path);
|
||||
m_entry->setETag(m_reply->rawHeader("ETag").constData());
|
||||
m_entry->setLocalChangedTimestamp(output_file_info.lastModified().toUTC().toMSecsSinceEpoch());
|
||||
m_entry->setStale(false);
|
||||
ENV.metacache()->updateEntry(m_entry);
|
||||
|
||||
m_reply.reset();
|
||||
emit succeeded(m_index_within_job);
|
||||
}
|
||||
|
||||
bool ForgeXzDownload::abort()
|
||||
{
|
||||
if(m_reply)
|
||||
m_reply->abort();
|
||||
m_status = Job_Aborted;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ForgeXzDownload::canAbort()
|
||||
{
|
||||
return true;
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
/* Copyright 2013-2019 MultiMC Contributors
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "net/NetAction.h"
|
||||
#include "net/HttpMetaCache.h"
|
||||
#include <QFile>
|
||||
#include <QTemporaryFile>
|
||||
|
||||
typedef std::shared_ptr<class ForgeXzDownload> ForgeXzDownloadPtr;
|
||||
|
||||
class ForgeXzDownload : public NetAction
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
MetaEntryPtr m_entry;
|
||||
/// if saving to file, use the one specified in this string
|
||||
QString m_target_path;
|
||||
/// this is the output file, if any
|
||||
QTemporaryFile m_pack200_xz_file;
|
||||
/// path relative to the mirror base
|
||||
QString m_url_path;
|
||||
|
||||
public:
|
||||
explicit ForgeXzDownload(QString url, QString relative_path, MetaEntryPtr entry);
|
||||
static ForgeXzDownloadPtr make(QString url, QString relative_path, MetaEntryPtr entry)
|
||||
{
|
||||
return ForgeXzDownloadPtr(new ForgeXzDownload(url, relative_path, entry));
|
||||
}
|
||||
virtual ~ForgeXzDownload(){};
|
||||
bool canAbort() override;
|
||||
|
||||
protected
|
||||
slots:
|
||||
void downloadProgress(qint64 bytesReceived, qint64 bytesTotal) override;
|
||||
void downloadError(QNetworkReply::NetworkError error) override;
|
||||
void downloadFinished() override;
|
||||
void downloadReadyRead() override;
|
||||
|
||||
public
|
||||
slots:
|
||||
void start() override;
|
||||
bool abort() override;
|
||||
|
||||
private:
|
||||
void decompressAndInstall();
|
||||
void failAndTryNextMirror();
|
||||
};
|
@ -1,50 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
|
||||
project(MultiMC_unpack200)
|
||||
|
||||
option(PACK200_BUILD_BINARY "Build a tiny utility that decompresses pack200 streams" OFF)
|
||||
|
||||
# Find ZLIB for quazip
|
||||
find_package(ZLIB REQUIRED)
|
||||
|
||||
set(PACK200_SRC
|
||||
include/unpack200.h
|
||||
src/bands.cpp
|
||||
src/bands.h
|
||||
src/bytes.cpp
|
||||
src/bytes.h
|
||||
src/coding.cpp
|
||||
src/coding.h
|
||||
src/constants.h
|
||||
src/defines.h
|
||||
src/unpack200.cpp
|
||||
src/unpack.cpp
|
||||
src/unpack.h
|
||||
src/utils.cpp
|
||||
src/utils.h
|
||||
src/zip.cpp
|
||||
src/zip.h
|
||||
)
|
||||
|
||||
if (Qt5_POSITION_INDEPENDENT_CODE)
|
||||
SET(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
endif()
|
||||
|
||||
add_library(MultiMC_unpack200 SHARED ${PACK200_SRC})
|
||||
target_include_directories(MultiMC_unpack200 PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" "${CMAKE_CURRENT_BINARY_DIR}" PRIVATE ${ZLIB_INCLUDE_DIRS} "${CMAKE_CURRENT_SOURCE_DIR}/src")
|
||||
target_link_libraries(MultiMC_unpack200 ${ZLIB_LIBRARIES})
|
||||
|
||||
set_target_properties(MultiMC_unpack200 PROPERTIES CXX_VISIBILITY_PRESET hidden VISIBILITY_INLINES_HIDDEN 1)
|
||||
generate_export_header(MultiMC_unpack200)
|
||||
|
||||
# Install it
|
||||
install(
|
||||
TARGETS MultiMC_unpack200
|
||||
RUNTIME DESTINATION ${LIBRARY_DEST_DIR}
|
||||
LIBRARY DESTINATION ${LIBRARY_DEST_DIR}
|
||||
)
|
||||
|
||||
if(PACK200_BUILD_BINARY)
|
||||
add_executable(anti200 anti200.cpp)
|
||||
target_link_libraries(anti200 MultiMC_unpack200)
|
||||
endif()
|
@ -1,347 +0,0 @@
|
||||
The GNU General Public License (GPL)
|
||||
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies of this license
|
||||
document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your freedom to share
|
||||
and change it. By contrast, the GNU General Public License is intended to
|
||||
guarantee your freedom to share and change free software--to make sure the
|
||||
software is free for all its users. This General Public License applies to
|
||||
most of the Free Software Foundation's software and to any other program whose
|
||||
authors commit to using it. (Some other Free Software Foundation software is
|
||||
covered by the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not price. Our
|
||||
General Public Licenses are designed to make sure that you have the freedom to
|
||||
distribute copies of free software (and charge for this service if you wish),
|
||||
that you receive source code or can get it if you want it, that you can change
|
||||
the software or use pieces of it in new free programs; and that you know you
|
||||
can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid anyone to deny
|
||||
you these rights or to ask you to surrender the rights. These restrictions
|
||||
translate to certain responsibilities for you if you distribute copies of the
|
||||
software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether gratis or for
|
||||
a fee, you must give the recipients all the rights that you have. You must
|
||||
make sure that they, too, receive or can get the source code. And you must
|
||||
show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and (2)
|
||||
offer you this license which gives you legal permission to copy, distribute
|
||||
and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain that
|
||||
everyone understands that there is no warranty for this free software. If the
|
||||
software is modified by someone else and passed on, we want its recipients to
|
||||
know that what they have is not the original, so that any problems introduced
|
||||
by others will not reflect on the original authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software patents. We
|
||||
wish to avoid the danger that redistributors of a free program will
|
||||
individually obtain patent licenses, in effect making the program proprietary.
|
||||
To prevent this, we have made it clear that any patent must be licensed for
|
||||
everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and modification
|
||||
follow.
|
||||
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains a notice
|
||||
placed by the copyright holder saying it may be distributed under the terms of
|
||||
this General Public License. The "Program", below, refers to any such program
|
||||
or work, and a "work based on the Program" means either the Program or any
|
||||
derivative work under copyright law: that is to say, a work containing the
|
||||
Program or a portion of it, either verbatim or with modifications and/or
|
||||
translated into another language. (Hereinafter, translation is included
|
||||
without limitation in the term "modification".) Each licensee is addressed as
|
||||
"you".
|
||||
|
||||
Activities other than copying, distribution and modification are not covered by
|
||||
this License; they are outside its scope. The act of running the Program is
|
||||
not restricted, and the output from the Program is covered only if its contents
|
||||
constitute a work based on the Program (independent of having been made by
|
||||
running the Program). Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's source code as
|
||||
you receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice and
|
||||
disclaimer of warranty; keep intact all the notices that refer to this License
|
||||
and to the absence of any warranty; and give any other recipients of the
|
||||
Program a copy of this License along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and you may
|
||||
at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion of it, thus
|
||||
forming a work based on the Program, and copy and distribute such modifications
|
||||
or work under the terms of Section 1 above, provided that you also meet all of
|
||||
these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices stating
|
||||
that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in whole or
|
||||
in part contains or is derived from the Program or any part thereof, to be
|
||||
licensed as a whole at no charge to all third parties under the terms of
|
||||
this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively when run,
|
||||
you must cause it, when started running for such interactive use in the
|
||||
most ordinary way, to print or display an announcement including an
|
||||
appropriate copyright notice and a notice that there is no warranty (or
|
||||
else, saying that you provide a warranty) and that users may redistribute
|
||||
the program under these conditions, and telling the user how to view a copy
|
||||
of this License. (Exception: if the Program itself is interactive but does
|
||||
not normally print such an announcement, your work based on the Program is
|
||||
not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If identifiable
|
||||
sections of that work are not derived from the Program, and can be reasonably
|
||||
considered independent and separate works in themselves, then this License, and
|
||||
its terms, do not apply to those sections when you distribute them as separate
|
||||
works. But when you distribute the same sections as part of a whole which is a
|
||||
work based on the Program, the distribution of the whole must be on the terms
|
||||
of this License, whose permissions for other licensees extend to the entire
|
||||
whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest your
|
||||
rights to work written entirely by you; rather, the intent is to exercise the
|
||||
right to control the distribution of derivative or collective works based on
|
||||
the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program with the
|
||||
Program (or with a work based on the Program) on a volume of a storage or
|
||||
distribution medium does not bring the other work under the scope of this
|
||||
License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it, under
|
||||
Section 2) in object code or executable form under the terms of Sections 1 and
|
||||
2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable source
|
||||
code, which must be distributed under the terms of Sections 1 and 2 above
|
||||
on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three years, to
|
||||
give any third party, for a charge no more than your cost of physically
|
||||
performing source distribution, a complete machine-readable copy of the
|
||||
corresponding source code, to be distributed under the terms of Sections 1
|
||||
and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer to
|
||||
distribute corresponding source code. (This alternative is allowed only
|
||||
for noncommercial distribution and only if you received the program in
|
||||
object code or executable form with such an offer, in accord with
|
||||
Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for making
|
||||
modifications to it. For an executable work, complete source code means all
|
||||
the source code for all modules it contains, plus any associated interface
|
||||
definition files, plus the scripts used to control compilation and installation
|
||||
of the executable. However, as a special exception, the source code
|
||||
distributed need not include anything that is normally distributed (in either
|
||||
source or binary form) with the major components (compiler, kernel, and so on)
|
||||
of the operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the source
|
||||
code from the same place counts as distribution of the source code, even though
|
||||
third parties are not compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program except as
|
||||
expressly provided under this License. Any attempt otherwise to copy, modify,
|
||||
sublicense or distribute the Program is void, and will automatically terminate
|
||||
your rights under this License. However, parties who have received copies, or
|
||||
rights, from you under this License will not have their licenses terminated so
|
||||
long as such parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not signed it.
|
||||
However, nothing else grants you permission to modify or distribute the Program
|
||||
or its derivative works. These actions are prohibited by law if you do not
|
||||
accept this License. Therefore, by modifying or distributing the Program (or
|
||||
any work based on the Program), you indicate your acceptance of this License to
|
||||
do so, and all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the Program),
|
||||
the recipient automatically receives a license from the original licensor to
|
||||
copy, distribute or modify the Program subject to these terms and conditions.
|
||||
You may not impose any further restrictions on the recipients' exercise of the
|
||||
rights granted herein. You are not responsible for enforcing compliance by
|
||||
third parties to this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues), conditions
|
||||
are imposed on you (whether by court order, agreement or otherwise) that
|
||||
contradict the conditions of this License, they do not excuse you from the
|
||||
conditions of this License. If you cannot distribute so as to satisfy
|
||||
simultaneously your obligations under this License and any other pertinent
|
||||
obligations, then as a consequence you may not distribute the Program at all.
|
||||
For example, if a patent license would not permit royalty-free redistribution
|
||||
of the Program by all those who receive copies directly or indirectly through
|
||||
you, then the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply and
|
||||
the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any patents or
|
||||
other property right claims or to contest validity of any such claims; this
|
||||
section has the sole purpose of protecting the integrity of the free software
|
||||
distribution system, which is implemented by public license practices. Many
|
||||
people have made generous contributions to the wide range of software
|
||||
distributed through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing to
|
||||
distribute software through any other system and a licensee cannot impose that
|
||||
choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to be a
|
||||
consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in certain
|
||||
countries either by patents or by copyrighted interfaces, the original
|
||||
copyright holder who places the Program under this License may add an explicit
|
||||
geographical distribution limitation excluding those countries, so that
|
||||
distribution is permitted only in or among countries not thus excluded. In
|
||||
such case, this License incorporates the limitation as if written in the body
|
||||
of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions of the
|
||||
General Public License from time to time. Such new versions will be similar in
|
||||
spirit to the present version, but may differ in detail to address new problems
|
||||
or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any later
|
||||
version", you have the option of following the terms and conditions either of
|
||||
that version or of any later version published by the Free Software Foundation.
|
||||
If the Program does not specify a version number of this License, you may
|
||||
choose any version ever published by the Free Software Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free programs
|
||||
whose distribution conditions are different, write to the author to ask for
|
||||
permission. For software which is copyrighted by the Free Software Foundation,
|
||||
write to the Free Software Foundation; we sometimes make exceptions for this.
|
||||
Our decision will be guided by the two goals of preserving the free status of
|
||||
all derivatives of our free software and of promoting the sharing and reuse of
|
||||
software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR
|
||||
THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE
|
||||
STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE
|
||||
PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND
|
||||
PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE,
|
||||
YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL
|
||||
ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE
|
||||
PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
|
||||
INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA
|
||||
BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER
|
||||
OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest possible
|
||||
use to the public, the best way to achieve this is to make it free software
|
||||
which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest to attach
|
||||
them to the start of each source file to most effectively convey the exclusion
|
||||
of warranty; and each file should have at least the "copyright" line and a
|
||||
pointer to where the full notice is found.
|
||||
|
||||
One line to give the program's name and a brief idea of what it does.
|
||||
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation; either version 2 of the License, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc., 59
|
||||
Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this when it
|
||||
starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author Gnomovision comes
|
||||
with ABSOLUTELY NO WARRANTY; for details type 'show w'. This is free
|
||||
software, and you are welcome to redistribute it under certain conditions;
|
||||
type 'show c' for details.
|
||||
|
||||
The hypothetical commands 'show w' and 'show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may be
|
||||
called something other than 'show w' and 'show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary. Here
|
||||
is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
'Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
signature of Ty Coon, 1 April 1989
|
||||
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General Public
|
||||
License instead of this License.
|
||||
|
||||
|
||||
"CLASSPATH" EXCEPTION TO THE GPL
|
||||
|
||||
Certain source files distributed by Oracle America and/or its affiliates are
|
||||
subject to the following clarification and special exception to the GPL, but
|
||||
only where Oracle has expressly included in the particular source file's header
|
||||
the words "Oracle designates this particular file as subject to the "Classpath"
|
||||
exception as provided by Oracle in the LICENSE file that accompanied this code."
|
||||
|
||||
Linking this library statically or dynamically with other modules is making
|
||||
a combined work based on this library. Thus, the terms and conditions of
|
||||
the GNU General Public License cover the whole combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent modules,
|
||||
and to copy and distribute the resulting executable under terms of your
|
||||
choice, provided that you also meet, for each linked independent module,
|
||||
the terms and conditions of the license of that module. An independent
|
||||
module is a module which is not derived from or based on this library. If
|
||||
you modify this library, you may extend this exception to your version of
|
||||
the library, but you are not obligated to do so. If you do not wish to do
|
||||
so, delete this exception statement from your version.
|
@ -1,43 +0,0 @@
|
||||
/*
|
||||
* This is trivial. Do what thou wilt with it. Public domain.
|
||||
*/
|
||||
|
||||
#include <stdexcept>
|
||||
#include <iostream>
|
||||
#include "unpack200.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc != 3)
|
||||
{
|
||||
std::cerr << "Simple pack200 unpacker!" << std::endl << "Run like this:" << std::endl
|
||||
<< " " << argv[0] << " input.jar.lzma output.jar" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
FILE *input = fopen(argv[1], "rb");
|
||||
if (!input)
|
||||
{
|
||||
std::cerr << "Can't open input file";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
FILE *output = fopen(argv[2], "wb");
|
||||
if (!output)
|
||||
{
|
||||
fclose(input);
|
||||
std::cerr << "Can't open output file";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
try
|
||||
{
|
||||
unpack_200(input, output);
|
||||
}
|
||||
catch (const std::runtime_error &e)
|
||||
{
|
||||
std::cerr << "Bad things happened: " << e.what() << std::endl;
|
||||
fclose(input);
|
||||
fclose(output);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "multimc_unpack200_export.h"
|
||||
|
||||
/**
|
||||
* @brief Unpack a PACK200 file
|
||||
*
|
||||
* @param input_path Path to the input file in PACK200 format. System native string encoding.
|
||||
* @param output_path Path to the output file in PACK200 format. System native string encoding.
|
||||
* @throw std::runtime_error for any error encountered
|
||||
*/
|
||||
MULTIMC_UNPACK200_EXPORT void unpack_200(FILE * input_path, FILE * output_path);
|
@ -1,423 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2009, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
// -*- C++ -*-
|
||||
// Small program for unpacking specially compressed Java packages.
|
||||
// John R. Rose
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "defines.h"
|
||||
#include "bytes.h"
|
||||
#include "utils.h"
|
||||
#include "coding.h"
|
||||
#include "bands.h"
|
||||
|
||||
#include "constants.h"
|
||||
#include "unpack.h"
|
||||
|
||||
void band::readData(int expectedLength)
|
||||
{
|
||||
assert(expectedLength >= 0);
|
||||
assert(vs[0].cmk == cmk_ERROR);
|
||||
if (expectedLength != 0)
|
||||
{
|
||||
assert(length == 0);
|
||||
length = expectedLength;
|
||||
}
|
||||
if (length == 0)
|
||||
{
|
||||
assert((rplimit = cm.vs0.rp = u->rp) != nullptr);
|
||||
return;
|
||||
}
|
||||
assert(length > 0);
|
||||
|
||||
bool is_BYTE1 = (defc->spec == BYTE1_spec);
|
||||
|
||||
if (is_BYTE1)
|
||||
{
|
||||
// No possibility of coding change. Sizing is exact.
|
||||
u->ensure_input(length);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Make a conservatively generous estimate of band size in bytes.
|
||||
// Assume B == 5 everywhere.
|
||||
// Assume awkward pop with all {U} values (2*5 per value)
|
||||
int64_t generous = (int64_t)length * (B_MAX * 3 + 1) + C_SLOP;
|
||||
u->ensure_input(generous);
|
||||
}
|
||||
|
||||
// Read one value to see what it might be.
|
||||
int XB = _meta_default;
|
||||
if (!is_BYTE1)
|
||||
{
|
||||
// must be a variable-length coding
|
||||
assert(defc->B() > 1 && defc->L() > 0);
|
||||
|
||||
value_stream xvs;
|
||||
coding *valc = defc;
|
||||
if (valc->D() != 0)
|
||||
{
|
||||
valc = coding::findBySpec(defc->B(), defc->H(), defc->S());
|
||||
assert(!valc->isMalloc);
|
||||
}
|
||||
xvs.init(u->rp, u->rplimit, valc);
|
||||
int X = xvs.getInt();
|
||||
if (valc->S() != 0)
|
||||
{
|
||||
assert(valc->min <= -256);
|
||||
XB = -1 - X;
|
||||
}
|
||||
else
|
||||
{
|
||||
int L = valc->L();
|
||||
assert(valc->max >= L + 255);
|
||||
XB = X - L;
|
||||
}
|
||||
if (0 <= XB && XB < 256)
|
||||
{
|
||||
// Skip over the escape value.
|
||||
u->rp = xvs.rp;
|
||||
}
|
||||
else
|
||||
{
|
||||
// No, it's still default.
|
||||
XB = _meta_default;
|
||||
}
|
||||
}
|
||||
|
||||
if (XB <= _meta_canon_max)
|
||||
{
|
||||
byte XB_byte = (byte)XB;
|
||||
byte *XB_ptr = &XB_byte;
|
||||
cm.init(u->rp, u->rplimit, XB_ptr, 0, defc, length, nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(u->meta_rp != nullptr);
|
||||
// Scribble the initial byte onto the band.
|
||||
byte *save_meta_rp = --u->meta_rp;
|
||||
byte save_meta_xb = (*save_meta_rp);
|
||||
(*save_meta_rp) = (byte)XB;
|
||||
cm.init(u->rp, u->rplimit, u->meta_rp, 0, defc, length, nullptr);
|
||||
(*save_meta_rp) = save_meta_xb; // put it back, just to be tidy
|
||||
}
|
||||
rplimit = u->rp;
|
||||
|
||||
rewind();
|
||||
}
|
||||
|
||||
void band::setIndex(cpindex *ix_)
|
||||
{
|
||||
assert(ix_ == nullptr || ixTag == ix_->ixTag);
|
||||
ix = ix_;
|
||||
}
|
||||
void band::setIndexByTag(byte tag)
|
||||
{
|
||||
setIndex(u->cp.getIndex(tag));
|
||||
}
|
||||
|
||||
entry *band::getRefCommon(cpindex *ix_, bool nullOKwithCaller)
|
||||
{
|
||||
assert(ix_->ixTag == ixTag ||
|
||||
(ixTag == CONSTANT_Literal && ix_->ixTag >= CONSTANT_Integer &&
|
||||
ix_->ixTag <= CONSTANT_String));
|
||||
int n = vs[0].getInt() - nullOK;
|
||||
// Note: band-local nullOK means nullptr encodes as 0.
|
||||
// But nullOKwithCaller means caller is willing to tolerate a nullptr.
|
||||
entry *ref = ix_->get(n);
|
||||
if (ref == nullptr && !(nullOKwithCaller && n == -1))
|
||||
unpack_abort(n == -1 ? "nullptr ref" : "bad ref");
|
||||
return ref;
|
||||
}
|
||||
|
||||
int64_t band::getLong(band &lo_band, bool have_hi)
|
||||
{
|
||||
band &hi_band = (*this);
|
||||
assert(lo_band.bn == hi_band.bn + 1);
|
||||
uint32_t lo = lo_band.getInt();
|
||||
if (!have_hi)
|
||||
{
|
||||
assert(hi_band.length == 0);
|
||||
return makeLong(0, lo);
|
||||
}
|
||||
uint32_t hi = hi_band.getInt();
|
||||
return makeLong(hi, lo);
|
||||
}
|
||||
|
||||
int band::getIntTotal()
|
||||
{
|
||||
if (length == 0)
|
||||
return 0;
|
||||
if (total_memo > 0)
|
||||
return total_memo - 1;
|
||||
int total = getInt();
|
||||
// overflow checks require that none of the addends are <0,
|
||||
// and that the partial sums never overflow (wrap negative)
|
||||
if (total < 0)
|
||||
{
|
||||
unpack_abort("overflow detected");
|
||||
}
|
||||
for (int k = length - 1; k > 0; k--)
|
||||
{
|
||||
int prev_total = total;
|
||||
total += vs[0].getInt();
|
||||
if (total < prev_total)
|
||||
{
|
||||
unpack_abort("overflow detected");
|
||||
}
|
||||
}
|
||||
rewind();
|
||||
total_memo = total + 1;
|
||||
return total;
|
||||
}
|
||||
|
||||
int band::getIntCount(int tag)
|
||||
{
|
||||
if (length == 0)
|
||||
return 0;
|
||||
if (tag >= HIST0_MIN && tag <= HIST0_MAX)
|
||||
{
|
||||
if (hist0 == nullptr)
|
||||
{
|
||||
// Lazily calculate an approximate histogram.
|
||||
hist0 = U_NEW(int, (HIST0_MAX - HIST0_MIN) + 1);
|
||||
for (int k = length; k > 0; k--)
|
||||
{
|
||||
int x = vs[0].getInt();
|
||||
if (x >= HIST0_MIN && x <= HIST0_MAX)
|
||||
hist0[x - HIST0_MIN] += 1;
|
||||
}
|
||||
rewind();
|
||||
}
|
||||
return hist0[tag - HIST0_MIN];
|
||||
}
|
||||
int total = 0;
|
||||
for (int k = length; k > 0; k--)
|
||||
{
|
||||
total += (vs[0].getInt() == tag) ? 1 : 0;
|
||||
}
|
||||
rewind();
|
||||
return total;
|
||||
}
|
||||
|
||||
#define INDEX_INIT(tag, nullOK, subindex) ((tag) + (subindex) * SUBINDEX_BIT + (nullOK) * 256)
|
||||
|
||||
#define INDEX(tag) INDEX_INIT(tag, 0, 0)
|
||||
#define NULL_OR_INDEX(tag) INDEX_INIT(tag, 1, 0)
|
||||
#define SUB_INDEX(tag) INDEX_INIT(tag, 0, 1)
|
||||
#define NO_INDEX 0
|
||||
|
||||
struct band_init
|
||||
{
|
||||
int defc;
|
||||
int index;
|
||||
};
|
||||
|
||||
#define BAND_INIT(name, cspec, ix) \
|
||||
{ \
|
||||
cspec, ix \
|
||||
}
|
||||
|
||||
const band_init all_band_inits[] =
|
||||
{
|
||||
// BAND_INIT(archive_magic, BYTE1_spec, 0),
|
||||
// BAND_INIT(archive_header, UNSIGNED5_spec, 0),
|
||||
// BAND_INIT(band_headers, BYTE1_spec, 0),
|
||||
BAND_INIT(cp_Utf8_prefix, DELTA5_spec, 0), BAND_INIT(cp_Utf8_suffix, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(cp_Utf8_chars, CHAR3_spec, 0), BAND_INIT(cp_Utf8_big_suffix, DELTA5_spec, 0),
|
||||
BAND_INIT(cp_Utf8_big_chars, DELTA5_spec, 0), BAND_INIT(cp_Int, UDELTA5_spec, 0),
|
||||
BAND_INIT(cp_Float, UDELTA5_spec, 0), BAND_INIT(cp_Long_hi, UDELTA5_spec, 0),
|
||||
BAND_INIT(cp_Long_lo, DELTA5_spec, 0), BAND_INIT(cp_Double_hi, UDELTA5_spec, 0),
|
||||
BAND_INIT(cp_Double_lo, DELTA5_spec, 0),
|
||||
BAND_INIT(cp_String, UDELTA5_spec, INDEX(CONSTANT_Utf8)),
|
||||
BAND_INIT(cp_Class, UDELTA5_spec, INDEX(CONSTANT_Utf8)),
|
||||
BAND_INIT(cp_Signature_form, DELTA5_spec, INDEX(CONSTANT_Utf8)),
|
||||
BAND_INIT(cp_Signature_classes, UDELTA5_spec, INDEX(CONSTANT_Class)),
|
||||
BAND_INIT(cp_Descr_name, DELTA5_spec, INDEX(CONSTANT_Utf8)),
|
||||
BAND_INIT(cp_Descr_type, UDELTA5_spec, INDEX(CONSTANT_Signature)),
|
||||
BAND_INIT(cp_Field_class, DELTA5_spec, INDEX(CONSTANT_Class)),
|
||||
BAND_INIT(cp_Field_desc, UDELTA5_spec, INDEX(CONSTANT_NameandType)),
|
||||
BAND_INIT(cp_Method_class, DELTA5_spec, INDEX(CONSTANT_Class)),
|
||||
BAND_INIT(cp_Method_desc, UDELTA5_spec, INDEX(CONSTANT_NameandType)),
|
||||
BAND_INIT(cp_Imethod_class, DELTA5_spec, INDEX(CONSTANT_Class)),
|
||||
BAND_INIT(cp_Imethod_desc, UDELTA5_spec, INDEX(CONSTANT_NameandType)),
|
||||
BAND_INIT(attr_definition_headers, BYTE1_spec, 0),
|
||||
BAND_INIT(attr_definition_name, UNSIGNED5_spec, INDEX(CONSTANT_Utf8)),
|
||||
BAND_INIT(attr_definition_layout, UNSIGNED5_spec, INDEX(CONSTANT_Utf8)),
|
||||
BAND_INIT(ic_this_class, UDELTA5_spec, INDEX(CONSTANT_Class)),
|
||||
BAND_INIT(ic_flags, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(ic_outer_class, DELTA5_spec, NULL_OR_INDEX(CONSTANT_Class)),
|
||||
BAND_INIT(ic_name, DELTA5_spec, NULL_OR_INDEX(CONSTANT_Utf8)),
|
||||
BAND_INIT(class_this, DELTA5_spec, INDEX(CONSTANT_Class)),
|
||||
BAND_INIT(class_super, DELTA5_spec, INDEX(CONSTANT_Class)),
|
||||
BAND_INIT(class_interface_count, DELTA5_spec, 0),
|
||||
BAND_INIT(class_interface, DELTA5_spec, INDEX(CONSTANT_Class)),
|
||||
BAND_INIT(class_field_count, DELTA5_spec, 0),
|
||||
BAND_INIT(class_method_count, DELTA5_spec, 0),
|
||||
BAND_INIT(field_descr, DELTA5_spec, INDEX(CONSTANT_NameandType)),
|
||||
BAND_INIT(field_flags_hi, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(field_flags_lo, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(field_attr_count, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(field_attr_indexes, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(field_attr_calls, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(field_ConstantValue_KQ, UNSIGNED5_spec, INDEX(CONSTANT_Literal)),
|
||||
BAND_INIT(field_Signature_RS, UNSIGNED5_spec, INDEX(CONSTANT_Signature)),
|
||||
BAND_INIT(field_metadata_bands, -1, -1), BAND_INIT(field_attr_bands, -1, -1),
|
||||
BAND_INIT(method_descr, MDELTA5_spec, INDEX(CONSTANT_NameandType)),
|
||||
BAND_INIT(method_flags_hi, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(method_flags_lo, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(method_attr_count, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(method_attr_indexes, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(method_attr_calls, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(method_Exceptions_N, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(method_Exceptions_RC, UNSIGNED5_spec, INDEX(CONSTANT_Class)),
|
||||
BAND_INIT(method_Signature_RS, UNSIGNED5_spec, INDEX(CONSTANT_Signature)),
|
||||
BAND_INIT(method_metadata_bands, -1, -1), BAND_INIT(method_attr_bands, -1, -1),
|
||||
BAND_INIT(class_flags_hi, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(class_flags_lo, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(class_attr_count, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(class_attr_indexes, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(class_attr_calls, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(class_SourceFile_RUN, UNSIGNED5_spec, NULL_OR_INDEX(CONSTANT_Utf8)),
|
||||
BAND_INIT(class_EnclosingMethod_RC, UNSIGNED5_spec, INDEX(CONSTANT_Class)),
|
||||
BAND_INIT(class_EnclosingMethod_RDN, UNSIGNED5_spec,
|
||||
NULL_OR_INDEX(CONSTANT_NameandType)),
|
||||
BAND_INIT(class_Signature_RS, UNSIGNED5_spec, INDEX(CONSTANT_Signature)),
|
||||
BAND_INIT(class_metadata_bands, -1, -1),
|
||||
BAND_INIT(class_InnerClasses_N, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(class_InnerClasses_RC, UNSIGNED5_spec, INDEX(CONSTANT_Class)),
|
||||
BAND_INIT(class_InnerClasses_F, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(class_InnerClasses_outer_RCN, UNSIGNED5_spec, NULL_OR_INDEX(CONSTANT_Class)),
|
||||
BAND_INIT(class_InnerClasses_name_RUN, UNSIGNED5_spec, NULL_OR_INDEX(CONSTANT_Utf8)),
|
||||
BAND_INIT(class_ClassFile_version_minor_H, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(class_ClassFile_version_major_H, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(class_attr_bands, -1, -1), BAND_INIT(code_headers, BYTE1_spec, 0),
|
||||
BAND_INIT(code_max_stack, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(code_max_na_locals, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(code_handler_count, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(code_handler_start_P, BCI5_spec, 0),
|
||||
BAND_INIT(code_handler_end_PO, BRANCH5_spec, 0),
|
||||
BAND_INIT(code_handler_catch_PO, BRANCH5_spec, 0),
|
||||
BAND_INIT(code_handler_class_RCN, UNSIGNED5_spec, NULL_OR_INDEX(CONSTANT_Class)),
|
||||
BAND_INIT(code_flags_hi, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(code_flags_lo, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(code_attr_count, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(code_attr_indexes, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(code_attr_calls, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(code_StackMapTable_N, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(code_StackMapTable_frame_T, BYTE1_spec, 0),
|
||||
BAND_INIT(code_StackMapTable_local_N, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(code_StackMapTable_stack_N, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(code_StackMapTable_offset, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(code_StackMapTable_T, BYTE1_spec, 0),
|
||||
BAND_INIT(code_StackMapTable_RC, UNSIGNED5_spec, INDEX(CONSTANT_Class)),
|
||||
BAND_INIT(code_StackMapTable_P, BCI5_spec, 0),
|
||||
BAND_INIT(code_LineNumberTable_N, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(code_LineNumberTable_bci_P, BCI5_spec, 0),
|
||||
BAND_INIT(code_LineNumberTable_line, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(code_LocalVariableTable_N, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(code_LocalVariableTable_bci_P, BCI5_spec, 0),
|
||||
BAND_INIT(code_LocalVariableTable_span_O, BRANCH5_spec, 0),
|
||||
BAND_INIT(code_LocalVariableTable_name_RU, UNSIGNED5_spec, INDEX(CONSTANT_Utf8)),
|
||||
BAND_INIT(code_LocalVariableTable_type_RS, UNSIGNED5_spec, INDEX(CONSTANT_Signature)),
|
||||
BAND_INIT(code_LocalVariableTable_slot, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(code_LocalVariableTypeTable_N, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(code_LocalVariableTypeTable_bci_P, BCI5_spec, 0),
|
||||
BAND_INIT(code_LocalVariableTypeTable_span_O, BRANCH5_spec, 0),
|
||||
BAND_INIT(code_LocalVariableTypeTable_name_RU, UNSIGNED5_spec, INDEX(CONSTANT_Utf8)),
|
||||
BAND_INIT(code_LocalVariableTypeTable_type_RS, UNSIGNED5_spec,
|
||||
INDEX(CONSTANT_Signature)),
|
||||
BAND_INIT(code_LocalVariableTypeTable_slot, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(code_attr_bands, -1, -1), BAND_INIT(bc_codes, BYTE1_spec, 0),
|
||||
BAND_INIT(bc_case_count, UNSIGNED5_spec, 0), BAND_INIT(bc_case_value, DELTA5_spec, 0),
|
||||
BAND_INIT(bc_byte, BYTE1_spec, 0), BAND_INIT(bc_short, DELTA5_spec, 0),
|
||||
BAND_INIT(bc_local, UNSIGNED5_spec, 0), BAND_INIT(bc_label, BRANCH5_spec, 0),
|
||||
BAND_INIT(bc_intref, DELTA5_spec, INDEX(CONSTANT_Integer)),
|
||||
BAND_INIT(bc_floatref, DELTA5_spec, INDEX(CONSTANT_Float)),
|
||||
BAND_INIT(bc_longref, DELTA5_spec, INDEX(CONSTANT_Long)),
|
||||
BAND_INIT(bc_doubleref, DELTA5_spec, INDEX(CONSTANT_Double)),
|
||||
BAND_INIT(bc_stringref, DELTA5_spec, INDEX(CONSTANT_String)),
|
||||
BAND_INIT(bc_classref, UNSIGNED5_spec, NULL_OR_INDEX(CONSTANT_Class)),
|
||||
BAND_INIT(bc_fieldref, DELTA5_spec, INDEX(CONSTANT_Fieldref)),
|
||||
BAND_INIT(bc_methodref, UNSIGNED5_spec, INDEX(CONSTANT_Methodref)),
|
||||
BAND_INIT(bc_imethodref, DELTA5_spec, INDEX(CONSTANT_InterfaceMethodref)),
|
||||
BAND_INIT(bc_thisfield, UNSIGNED5_spec, SUB_INDEX(CONSTANT_Fieldref)),
|
||||
BAND_INIT(bc_superfield, UNSIGNED5_spec, SUB_INDEX(CONSTANT_Fieldref)),
|
||||
BAND_INIT(bc_thismethod, UNSIGNED5_spec, SUB_INDEX(CONSTANT_Methodref)),
|
||||
BAND_INIT(bc_supermethod, UNSIGNED5_spec, SUB_INDEX(CONSTANT_Methodref)),
|
||||
BAND_INIT(bc_initref, UNSIGNED5_spec, SUB_INDEX(CONSTANT_Methodref)),
|
||||
BAND_INIT(bc_escref, UNSIGNED5_spec, INDEX(CONSTANT_All)),
|
||||
BAND_INIT(bc_escrefsize, UNSIGNED5_spec, 0), BAND_INIT(bc_escsize, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(bc_escbyte, BYTE1_spec, 0),
|
||||
BAND_INIT(file_name, UNSIGNED5_spec, INDEX(CONSTANT_Utf8)),
|
||||
BAND_INIT(file_size_hi, UNSIGNED5_spec, 0), BAND_INIT(file_size_lo, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(file_modtime, DELTA5_spec, 0), BAND_INIT(file_options, UNSIGNED5_spec, 0),
|
||||
// BAND_INIT(file_bits, BYTE1_spec, 0),
|
||||
{0, 0}};
|
||||
|
||||
band *band::makeBands(unpacker *u)
|
||||
{
|
||||
band *tmp_all_bands = U_NEW(band, BAND_LIMIT);
|
||||
for (int i = 0; i < BAND_LIMIT; i++)
|
||||
{
|
||||
assert((byte *)&all_band_inits[i + 1] <
|
||||
(byte *)all_band_inits + sizeof(all_band_inits));
|
||||
const band_init &bi = all_band_inits[i];
|
||||
band &b = tmp_all_bands[i];
|
||||
coding *defc = coding::findBySpec(bi.defc);
|
||||
assert((defc == nullptr) == (bi.defc == -1)); // no garbage, please
|
||||
assert(defc == nullptr || !defc->isMalloc);
|
||||
b.init(u, i, defc);
|
||||
if (bi.index > 0)
|
||||
{
|
||||
b.nullOK = ((bi.index >> 8) & 1);
|
||||
b.ixTag = (bi.index & 0xFF);
|
||||
}
|
||||
}
|
||||
return tmp_all_bands;
|
||||
}
|
||||
|
||||
void band::initIndexes(unpacker *u)
|
||||
{
|
||||
band *tmp_all_bands = u->all_bands;
|
||||
for (int i = 0; i < BAND_LIMIT; i++)
|
||||
{
|
||||
band *scan = &tmp_all_bands[i];
|
||||
uint32_t tag = scan->ixTag; // Cf. #define INDEX(tag) above
|
||||
if (tag != 0 && tag != CONSTANT_Literal && (tag & SUBINDEX_BIT) == 0)
|
||||
{
|
||||
scan->setIndex(u->cp.getIndex(tag));
|
||||
}
|
||||
}
|
||||
}
|
@ -1,489 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2005, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
// -*- C++ -*-
|
||||
struct entry;
|
||||
struct cpindex;
|
||||
struct unpacker;
|
||||
|
||||
struct band
|
||||
{
|
||||
int bn; // band_number of this band
|
||||
coding *defc; // default coding method
|
||||
cpindex *ix; // CP entry mapping, if CPRefBand
|
||||
byte ixTag; // 0 or 1; nullptr is coded as (nullOK?0:-1)
|
||||
byte nullOK; // 0 or 1; nullptr is coded as (nullOK?0:-1)
|
||||
int length; // expected # values
|
||||
unpacker *u; // back pointer
|
||||
|
||||
value_stream vs[2]; // source of values
|
||||
coding_method cm; // method used for initial state of vs[0]
|
||||
byte *rplimit; // end of band (encoded, transmitted)
|
||||
|
||||
int total_memo; // cached value of getIntTotal, or -1
|
||||
int *hist0; // approximate. histogram
|
||||
enum
|
||||
{
|
||||
HIST0_MIN = 0,
|
||||
HIST0_MAX = 255
|
||||
}; // catches the usual cases
|
||||
|
||||
// properties for attribute layout elements:
|
||||
byte le_kind; // EK_XXX
|
||||
byte le_bci; // 0,EK_BCI,EK_BCD,EK_BCO
|
||||
byte le_back; // ==EF_BACK
|
||||
byte le_len; // 0,1,2,4 (size in classfile), or call addr
|
||||
band **le_body; // body of repl, union, call (nullptr-terminated)
|
||||
// Note: EK_CASE elements use hist0 to record union tags.
|
||||
#define le_casetags hist0
|
||||
|
||||
band &nextBand()
|
||||
{
|
||||
return this[1];
|
||||
}
|
||||
band &prevBand()
|
||||
{
|
||||
return this[-1];
|
||||
}
|
||||
|
||||
void init(unpacker *u_, int bn_, coding *defc_)
|
||||
{
|
||||
u = u_;
|
||||
cm.u = u_;
|
||||
bn = bn_;
|
||||
defc = defc_;
|
||||
}
|
||||
void init(unpacker *u_, int bn_, int defcSpec)
|
||||
{
|
||||
init(u_, bn_, coding::findBySpec(defcSpec));
|
||||
}
|
||||
void initRef(int ixTag_ = 0, bool nullOK_ = false)
|
||||
{
|
||||
ixTag = ixTag_;
|
||||
nullOK = nullOK_;
|
||||
setIndexByTag(ixTag);
|
||||
}
|
||||
|
||||
void expectMoreLength(int l)
|
||||
{
|
||||
assert(length >= 0); // able to accept a length
|
||||
assert((int)l >= 0); // no overflow
|
||||
assert(rplimit == nullptr); // readData not yet called
|
||||
length += l;
|
||||
assert(length >= l); // no overflow
|
||||
}
|
||||
|
||||
void setIndex(cpindex *ix_);
|
||||
void setIndexByTag(byte tag);
|
||||
|
||||
// Parse the band and its meta-coding header.
|
||||
void readData(int expectedLength = 0);
|
||||
|
||||
// Reset the band for another pass (Cf. Java Band.resetForSecondPass.)
|
||||
void rewind()
|
||||
{
|
||||
cm.reset(&vs[0]);
|
||||
}
|
||||
|
||||
byte *&curRP()
|
||||
{
|
||||
return vs[0].rp;
|
||||
}
|
||||
byte *minRP()
|
||||
{
|
||||
return cm.vs0.rp;
|
||||
}
|
||||
byte *maxRP()
|
||||
{
|
||||
return rplimit;
|
||||
}
|
||||
size_t size()
|
||||
{
|
||||
return maxRP() - minRP();
|
||||
}
|
||||
|
||||
int getByte()
|
||||
{
|
||||
assert(ix == nullptr);
|
||||
return vs[0].getByte();
|
||||
}
|
||||
int getInt()
|
||||
{
|
||||
assert(ix == nullptr);
|
||||
return vs[0].getInt();
|
||||
}
|
||||
entry *getRefN()
|
||||
{
|
||||
assert(ix != nullptr);
|
||||
return getRefCommon(ix, true);
|
||||
}
|
||||
entry *getRef()
|
||||
{
|
||||
assert(ix != nullptr);
|
||||
return getRefCommon(ix, false);
|
||||
}
|
||||
entry *getRefUsing(cpindex *ix2)
|
||||
{
|
||||
assert(ix == nullptr);
|
||||
return getRefCommon(ix2, true);
|
||||
}
|
||||
entry *getRefCommon(cpindex *ix, bool nullOK);
|
||||
int64_t getLong(band &lo_band, bool have_hi);
|
||||
|
||||
static int64_t makeLong(uint32_t hi, uint32_t lo)
|
||||
{
|
||||
return ((uint64_t)hi << 32) + (((uint64_t)lo << 32) >> 32);
|
||||
}
|
||||
|
||||
int getIntTotal();
|
||||
int getIntCount(int tag);
|
||||
|
||||
static band *makeBands(unpacker *u);
|
||||
static void initIndexes(unpacker *u);
|
||||
};
|
||||
|
||||
extern band all_bands[];
|
||||
|
||||
#define BAND_LOCAL /* \
|
||||
band* band_temp = all_bands; \
|
||||
band* all_bands = band_temp */
|
||||
|
||||
// Band schema:
|
||||
enum band_number
|
||||
{
|
||||
// e_archive_magic,
|
||||
// e_archive_header,
|
||||
// e_band_headers,
|
||||
|
||||
// constant pool contents
|
||||
e_cp_Utf8_prefix,
|
||||
e_cp_Utf8_suffix,
|
||||
e_cp_Utf8_chars,
|
||||
e_cp_Utf8_big_suffix,
|
||||
e_cp_Utf8_big_chars,
|
||||
e_cp_Int,
|
||||
e_cp_Float,
|
||||
e_cp_Long_hi,
|
||||
e_cp_Long_lo,
|
||||
e_cp_Double_hi,
|
||||
e_cp_Double_lo,
|
||||
e_cp_String,
|
||||
e_cp_Class,
|
||||
e_cp_Signature_form,
|
||||
e_cp_Signature_classes,
|
||||
e_cp_Descr_name,
|
||||
e_cp_Descr_type,
|
||||
e_cp_Field_class,
|
||||
e_cp_Field_desc,
|
||||
e_cp_Method_class,
|
||||
e_cp_Method_desc,
|
||||
e_cp_Imethod_class,
|
||||
e_cp_Imethod_desc,
|
||||
|
||||
// bands which define transmission of attributes
|
||||
e_attr_definition_headers,
|
||||
e_attr_definition_name,
|
||||
e_attr_definition_layout,
|
||||
|
||||
// band for hardwired InnerClasses attribute (shared across the package)
|
||||
e_ic_this_class,
|
||||
e_ic_flags,
|
||||
// These bands contain data only where flags sets ACC_IC_LONG_FORM:
|
||||
e_ic_outer_class,
|
||||
e_ic_name,
|
||||
|
||||
// bands for carrying class schema information:
|
||||
e_class_this,
|
||||
e_class_super,
|
||||
e_class_interface_count,
|
||||
e_class_interface,
|
||||
|
||||
// bands for class members
|
||||
e_class_field_count,
|
||||
e_class_method_count,
|
||||
e_field_descr,
|
||||
e_field_flags_hi,
|
||||
e_field_flags_lo,
|
||||
e_field_attr_count,
|
||||
e_field_attr_indexes,
|
||||
e_field_attr_calls,
|
||||
e_field_ConstantValue_KQ,
|
||||
e_field_Signature_RS,
|
||||
e_field_metadata_bands,
|
||||
e_field_attr_bands,
|
||||
e_method_descr,
|
||||
e_method_flags_hi,
|
||||
e_method_flags_lo,
|
||||
e_method_attr_count,
|
||||
e_method_attr_indexes,
|
||||
e_method_attr_calls,
|
||||
e_method_Exceptions_N,
|
||||
e_method_Exceptions_RC,
|
||||
e_method_Signature_RS,
|
||||
e_method_metadata_bands,
|
||||
e_method_attr_bands,
|
||||
e_class_flags_hi,
|
||||
e_class_flags_lo,
|
||||
e_class_attr_count,
|
||||
e_class_attr_indexes,
|
||||
e_class_attr_calls,
|
||||
e_class_SourceFile_RUN,
|
||||
e_class_EnclosingMethod_RC,
|
||||
e_class_EnclosingMethod_RDN,
|
||||
e_class_Signature_RS,
|
||||
e_class_metadata_bands,
|
||||
e_class_InnerClasses_N,
|
||||
e_class_InnerClasses_RC,
|
||||
e_class_InnerClasses_F,
|
||||
e_class_InnerClasses_outer_RCN,
|
||||
e_class_InnerClasses_name_RUN,
|
||||
e_class_ClassFile_version_minor_H,
|
||||
e_class_ClassFile_version_major_H,
|
||||
e_class_attr_bands,
|
||||
e_code_headers,
|
||||
e_code_max_stack,
|
||||
e_code_max_na_locals,
|
||||
e_code_handler_count,
|
||||
e_code_handler_start_P,
|
||||
e_code_handler_end_PO,
|
||||
e_code_handler_catch_PO,
|
||||
e_code_handler_class_RCN,
|
||||
|
||||
// code attributes
|
||||
e_code_flags_hi,
|
||||
e_code_flags_lo,
|
||||
e_code_attr_count,
|
||||
e_code_attr_indexes,
|
||||
e_code_attr_calls,
|
||||
e_code_StackMapTable_N,
|
||||
e_code_StackMapTable_frame_T,
|
||||
e_code_StackMapTable_local_N,
|
||||
e_code_StackMapTable_stack_N,
|
||||
e_code_StackMapTable_offset,
|
||||
e_code_StackMapTable_T,
|
||||
e_code_StackMapTable_RC,
|
||||
e_code_StackMapTable_P,
|
||||
e_code_LineNumberTable_N,
|
||||
e_code_LineNumberTable_bci_P,
|
||||
e_code_LineNumberTable_line,
|
||||
e_code_LocalVariableTable_N,
|
||||
e_code_LocalVariableTable_bci_P,
|
||||
e_code_LocalVariableTable_span_O,
|
||||
e_code_LocalVariableTable_name_RU,
|
||||
e_code_LocalVariableTable_type_RS,
|
||||
e_code_LocalVariableTable_slot,
|
||||
e_code_LocalVariableTypeTable_N,
|
||||
e_code_LocalVariableTypeTable_bci_P,
|
||||
e_code_LocalVariableTypeTable_span_O,
|
||||
e_code_LocalVariableTypeTable_name_RU,
|
||||
e_code_LocalVariableTypeTable_type_RS,
|
||||
e_code_LocalVariableTypeTable_slot,
|
||||
e_code_attr_bands,
|
||||
|
||||
// bands for bytecodes
|
||||
e_bc_codes,
|
||||
// remaining bands provide typed opcode fields required by the bc_codes
|
||||
e_bc_case_count,
|
||||
e_bc_case_value,
|
||||
e_bc_byte,
|
||||
e_bc_short,
|
||||
e_bc_local,
|
||||
e_bc_label,
|
||||
|
||||
// ldc* operands:
|
||||
e_bc_intref,
|
||||
e_bc_floatref,
|
||||
e_bc_longref,
|
||||
e_bc_doubleref,
|
||||
e_bc_stringref,
|
||||
e_bc_classref,
|
||||
e_bc_fieldref,
|
||||
e_bc_methodref,
|
||||
e_bc_imethodref,
|
||||
|
||||
// _self_linker_op family
|
||||
e_bc_thisfield,
|
||||
e_bc_superfield,
|
||||
e_bc_thismethod,
|
||||
e_bc_supermethod,
|
||||
|
||||
// bc_invokeinit family:
|
||||
e_bc_initref,
|
||||
|
||||
// bytecode escape sequences
|
||||
e_bc_escref,
|
||||
e_bc_escrefsize,
|
||||
e_bc_escsize,
|
||||
e_bc_escbyte,
|
||||
|
||||
// file attributes and contents
|
||||
e_file_name,
|
||||
e_file_size_hi,
|
||||
e_file_size_lo,
|
||||
e_file_modtime,
|
||||
e_file_options,
|
||||
// e_file_bits, // handled specially as an appendix
|
||||
BAND_LIMIT
|
||||
};
|
||||
|
||||
// Symbolic names for bands, as if in a giant global struct:
|
||||
//#define archive_magic all_bands[e_archive_magic]
|
||||
//#define archive_header all_bands[e_archive_header]
|
||||
//#define band_headers all_bands[e_band_headers]
|
||||
#define cp_Utf8_prefix all_bands[e_cp_Utf8_prefix]
|
||||
#define cp_Utf8_suffix all_bands[e_cp_Utf8_suffix]
|
||||
#define cp_Utf8_chars all_bands[e_cp_Utf8_chars]
|
||||
#define cp_Utf8_big_suffix all_bands[e_cp_Utf8_big_suffix]
|
||||
#define cp_Utf8_big_chars all_bands[e_cp_Utf8_big_chars]
|
||||
#define cp_Int all_bands[e_cp_Int]
|
||||
#define cp_Float all_bands[e_cp_Float]
|
||||
#define cp_Long_hi all_bands[e_cp_Long_hi]
|
||||
#define cp_Long_lo all_bands[e_cp_Long_lo]
|
||||
#define cp_Double_hi all_bands[e_cp_Double_hi]
|
||||
#define cp_Double_lo all_bands[e_cp_Double_lo]
|
||||
#define cp_String all_bands[e_cp_String]
|
||||
#define cp_Class all_bands[e_cp_Class]
|
||||
#define cp_Signature_form all_bands[e_cp_Signature_form]
|
||||
#define cp_Signature_classes all_bands[e_cp_Signature_classes]
|
||||
#define cp_Descr_name all_bands[e_cp_Descr_name]
|
||||
#define cp_Descr_type all_bands[e_cp_Descr_type]
|
||||
#define cp_Field_class all_bands[e_cp_Field_class]
|
||||
#define cp_Field_desc all_bands[e_cp_Field_desc]
|
||||
#define cp_Method_class all_bands[e_cp_Method_class]
|
||||
#define cp_Method_desc all_bands[e_cp_Method_desc]
|
||||
#define cp_Imethod_class all_bands[e_cp_Imethod_class]
|
||||
#define cp_Imethod_desc all_bands[e_cp_Imethod_desc]
|
||||
#define attr_definition_headers all_bands[e_attr_definition_headers]
|
||||
#define attr_definition_name all_bands[e_attr_definition_name]
|
||||
#define attr_definition_layout all_bands[e_attr_definition_layout]
|
||||
#define ic_this_class all_bands[e_ic_this_class]
|
||||
#define ic_flags all_bands[e_ic_flags]
|
||||
#define ic_outer_class all_bands[e_ic_outer_class]
|
||||
#define ic_name all_bands[e_ic_name]
|
||||
#define class_this all_bands[e_class_this]
|
||||
#define class_super all_bands[e_class_super]
|
||||
#define class_interface_count all_bands[e_class_interface_count]
|
||||
#define class_interface all_bands[e_class_interface]
|
||||
#define class_field_count all_bands[e_class_field_count]
|
||||
#define class_method_count all_bands[e_class_method_count]
|
||||
#define field_descr all_bands[e_field_descr]
|
||||
#define field_flags_hi all_bands[e_field_flags_hi]
|
||||
#define field_flags_lo all_bands[e_field_flags_lo]
|
||||
#define field_attr_count all_bands[e_field_attr_count]
|
||||
#define field_attr_indexes all_bands[e_field_attr_indexes]
|
||||
#define field_ConstantValue_KQ all_bands[e_field_ConstantValue_KQ]
|
||||
#define field_Signature_RS all_bands[e_field_Signature_RS]
|
||||
#define field_attr_bands all_bands[e_field_attr_bands]
|
||||
#define method_descr all_bands[e_method_descr]
|
||||
#define method_flags_hi all_bands[e_method_flags_hi]
|
||||
#define method_flags_lo all_bands[e_method_flags_lo]
|
||||
#define method_attr_count all_bands[e_method_attr_count]
|
||||
#define method_attr_indexes all_bands[e_method_attr_indexes]
|
||||
#define method_Exceptions_N all_bands[e_method_Exceptions_N]
|
||||
#define method_Exceptions_RC all_bands[e_method_Exceptions_RC]
|
||||
#define method_Signature_RS all_bands[e_method_Signature_RS]
|
||||
#define method_attr_bands all_bands[e_method_attr_bands]
|
||||
#define class_flags_hi all_bands[e_class_flags_hi]
|
||||
#define class_flags_lo all_bands[e_class_flags_lo]
|
||||
#define class_attr_count all_bands[e_class_attr_count]
|
||||
#define class_attr_indexes all_bands[e_class_attr_indexes]
|
||||
#define class_SourceFile_RUN all_bands[e_class_SourceFile_RUN]
|
||||
#define class_EnclosingMethod_RC all_bands[e_class_EnclosingMethod_RC]
|
||||
#define class_EnclosingMethod_RDN all_bands[e_class_EnclosingMethod_RDN]
|
||||
#define class_Signature_RS all_bands[e_class_Signature_RS]
|
||||
#define class_InnerClasses_N all_bands[e_class_InnerClasses_N]
|
||||
#define class_InnerClasses_RC all_bands[e_class_InnerClasses_RC]
|
||||
#define class_InnerClasses_F all_bands[e_class_InnerClasses_F]
|
||||
#define class_InnerClasses_outer_RCN all_bands[e_class_InnerClasses_outer_RCN]
|
||||
#define class_InnerClasses_name_RUN all_bands[e_class_InnerClasses_name_RUN]
|
||||
#define class_ClassFile_version_minor_H all_bands[e_class_ClassFile_version_minor_H]
|
||||
#define class_ClassFile_version_major_H all_bands[e_class_ClassFile_version_major_H]
|
||||
#define class_attr_bands all_bands[e_class_attr_bands]
|
||||
#define code_headers all_bands[e_code_headers]
|
||||
#define code_max_stack all_bands[e_code_max_stack]
|
||||
#define code_max_na_locals all_bands[e_code_max_na_locals]
|
||||
#define code_handler_count all_bands[e_code_handler_count]
|
||||
#define code_handler_start_P all_bands[e_code_handler_start_P]
|
||||
#define code_handler_end_PO all_bands[e_code_handler_end_PO]
|
||||
#define code_handler_catch_PO all_bands[e_code_handler_catch_PO]
|
||||
#define code_handler_class_RCN all_bands[e_code_handler_class_RCN]
|
||||
#define code_flags_hi all_bands[e_code_flags_hi]
|
||||
#define code_flags_lo all_bands[e_code_flags_lo]
|
||||
#define code_attr_count all_bands[e_code_attr_count]
|
||||
#define code_attr_indexes all_bands[e_code_attr_indexes]
|
||||
#define code_StackMapTable_N all_bands[e_code_StackMapTable_N]
|
||||
#define code_StackMapTable_frame_T all_bands[e_code_StackMapTable_frame_T]
|
||||
#define code_StackMapTable_local_N all_bands[e_code_StackMapTable_local_N]
|
||||
#define code_StackMapTable_stack_N all_bands[e_code_StackMapTable_stack_N]
|
||||
#define code_StackMapTable_offset all_bands[e_code_StackMapTable_offset]
|
||||
#define code_StackMapTable_T all_bands[e_code_StackMapTable_T]
|
||||
#define code_StackMapTable_RC all_bands[e_code_StackMapTable_RC]
|
||||
#define code_StackMapTable_P all_bands[e_code_StackMapTable_P]
|
||||
#define code_LineNumberTable_N all_bands[e_code_LineNumberTable_N]
|
||||
#define code_LineNumberTable_bci_P all_bands[e_code_LineNumberTable_bci_P]
|
||||
#define code_LineNumberTable_line all_bands[e_code_LineNumberTable_line]
|
||||
#define code_LocalVariableTable_N all_bands[e_code_LocalVariableTable_N]
|
||||
#define code_LocalVariableTable_bci_P all_bands[e_code_LocalVariableTable_bci_P]
|
||||
#define code_LocalVariableTable_span_O all_bands[e_code_LocalVariableTable_span_O]
|
||||
#define code_LocalVariableTable_name_RU all_bands[e_code_LocalVariableTable_name_RU]
|
||||
#define code_LocalVariableTable_type_RS all_bands[e_code_LocalVariableTable_type_RS]
|
||||
#define code_LocalVariableTable_slot all_bands[e_code_LocalVariableTable_slot]
|
||||
#define code_LocalVariableTypeTable_N all_bands[e_code_LocalVariableTypeTable_N]
|
||||
#define code_LocalVariableTypeTable_bci_P all_bands[e_code_LocalVariableTypeTable_bci_P]
|
||||
#define code_LocalVariableTypeTable_span_O all_bands[e_code_LocalVariableTypeTable_span_O]
|
||||
#define code_LocalVariableTypeTable_name_RU all_bands[e_code_LocalVariableTypeTable_name_RU]
|
||||
#define code_LocalVariableTypeTable_type_RS all_bands[e_code_LocalVariableTypeTable_type_RS]
|
||||
#define code_LocalVariableTypeTable_slot all_bands[e_code_LocalVariableTypeTable_slot]
|
||||
#define code_attr_bands all_bands[e_code_attr_bands]
|
||||
#define bc_codes all_bands[e_bc_codes]
|
||||
#define bc_case_count all_bands[e_bc_case_count]
|
||||
#define bc_case_value all_bands[e_bc_case_value]
|
||||
#define bc_byte all_bands[e_bc_byte]
|
||||
#define bc_short all_bands[e_bc_short]
|
||||
#define bc_local all_bands[e_bc_local]
|
||||
#define bc_label all_bands[e_bc_label]
|
||||
#define bc_intref all_bands[e_bc_intref]
|
||||
#define bc_floatref all_bands[e_bc_floatref]
|
||||
#define bc_longref all_bands[e_bc_longref]
|
||||
#define bc_doubleref all_bands[e_bc_doubleref]
|
||||
#define bc_stringref all_bands[e_bc_stringref]
|
||||
#define bc_classref all_bands[e_bc_classref]
|
||||
#define bc_fieldref all_bands[e_bc_fieldref]
|
||||
#define bc_methodref all_bands[e_bc_methodref]
|
||||
#define bc_imethodref all_bands[e_bc_imethodref]
|
||||
#define bc_thisfield all_bands[e_bc_thisfield]
|
||||
#define bc_superfield all_bands[e_bc_superfield]
|
||||
#define bc_thismethod all_bands[e_bc_thismethod]
|
||||
#define bc_supermethod all_bands[e_bc_supermethod]
|
||||
#define bc_initref all_bands[e_bc_initref]
|
||||
#define bc_escref all_bands[e_bc_escref]
|
||||
#define bc_escrefsize all_bands[e_bc_escrefsize]
|
||||
#define bc_escsize all_bands[e_bc_escsize]
|
||||
#define bc_escbyte all_bands[e_bc_escbyte]
|
||||
#define file_name all_bands[e_file_name]
|
||||
#define file_size_hi all_bands[e_file_size_hi]
|
||||
#define file_size_lo all_bands[e_file_size_lo]
|
||||
#define file_modtime all_bands[e_file_modtime]
|
||||
#define file_options all_bands[e_file_options]
|
@ -1,217 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include "defines.h"
|
||||
#include "bytes.h"
|
||||
#include "utils.h"
|
||||
|
||||
static byte dummy[1 << 10];
|
||||
|
||||
bool bytes::inBounds(const void *p)
|
||||
{
|
||||
return p >= ptr && p < limit();
|
||||
}
|
||||
|
||||
void bytes::malloc(size_t len_)
|
||||
{
|
||||
len = len_;
|
||||
ptr = NEW(byte, add_size(len_, 1)); // add trailing zero byte always
|
||||
if (ptr == nullptr)
|
||||
{
|
||||
// set ptr to some victim memory, to ease escape
|
||||
set(dummy, sizeof(dummy) - 1);
|
||||
unpack_abort(ERROR_ENOMEM);
|
||||
}
|
||||
}
|
||||
|
||||
void bytes::realloc(size_t len_)
|
||||
{
|
||||
if (len == len_)
|
||||
return; // nothing to do
|
||||
if (ptr == dummy)
|
||||
return; // escaping from an error
|
||||
if (ptr == nullptr)
|
||||
{
|
||||
malloc(len_);
|
||||
return;
|
||||
}
|
||||
byte *oldptr = ptr;
|
||||
ptr = (len_ >= PSIZE_MAX) ? nullptr : (byte *)::realloc(ptr, add_size(len_, 1));
|
||||
if (ptr != nullptr)
|
||||
{
|
||||
if (len < len_)
|
||||
memset(ptr + len, 0, len_ - len);
|
||||
ptr[len_] = 0;
|
||||
len = len_;
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr = oldptr; // ease our escape
|
||||
unpack_abort(ERROR_ENOMEM);
|
||||
}
|
||||
}
|
||||
|
||||
void bytes::free()
|
||||
{
|
||||
if (ptr == dummy)
|
||||
return; // escaping from an error
|
||||
if (ptr != nullptr)
|
||||
{
|
||||
::free(ptr);
|
||||
}
|
||||
len = 0;
|
||||
ptr = 0;
|
||||
}
|
||||
|
||||
int bytes::indexOf(byte c)
|
||||
{
|
||||
byte *p = (byte *)memchr(ptr, c, len);
|
||||
return (p == 0) ? -1 : (int)(p - ptr);
|
||||
}
|
||||
|
||||
byte *bytes::writeTo(byte *bp)
|
||||
{
|
||||
memcpy(bp, ptr, len);
|
||||
return bp + len;
|
||||
}
|
||||
|
||||
int bytes::compareTo(bytes &other)
|
||||
{
|
||||
size_t l1 = len;
|
||||
size_t l2 = other.len;
|
||||
int cmp = memcmp(ptr, other.ptr, (l1 < l2) ? l1 : l2);
|
||||
if (cmp != 0)
|
||||
return cmp;
|
||||
return (l1 < l2) ? -1 : (l1 > l2) ? 1 : 0;
|
||||
}
|
||||
|
||||
void bytes::saveFrom(const void *ptr_, size_t len_)
|
||||
{
|
||||
malloc(len_);
|
||||
// Save as much as possible.
|
||||
if (len_ > len)
|
||||
{
|
||||
assert(ptr == dummy); // error recovery
|
||||
len_ = len;
|
||||
}
|
||||
copyFrom(ptr_, len_);
|
||||
}
|
||||
|
||||
//#TODO: Need to fix for exception handling
|
||||
void bytes::copyFrom(const void *ptr_, size_t len_, size_t offset)
|
||||
{
|
||||
assert(len_ == 0 || inBounds(ptr + offset));
|
||||
assert(len_ == 0 || inBounds(ptr + offset + len_ - 1));
|
||||
memcpy(ptr + offset, ptr_, len_);
|
||||
}
|
||||
|
||||
// Make sure there are 'o' bytes beyond the fill pointer,
|
||||
// advance the fill pointer, and return the old fill pointer.
|
||||
byte *fillbytes::grow(size_t s)
|
||||
{
|
||||
size_t nlen = add_size(b.len, s);
|
||||
if (nlen <= allocated)
|
||||
{
|
||||
b.len = nlen;
|
||||
return limit() - s;
|
||||
}
|
||||
size_t maxlen = nlen;
|
||||
if (maxlen < 128)
|
||||
maxlen = 128;
|
||||
if (maxlen < allocated * 2)
|
||||
maxlen = allocated * 2;
|
||||
if (allocated == 0)
|
||||
{
|
||||
// Initial buffer was not malloced. Do not reallocate it.
|
||||
bytes old = b;
|
||||
b.malloc(maxlen);
|
||||
if (b.len == maxlen)
|
||||
old.writeTo(b.ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
b.realloc(maxlen);
|
||||
}
|
||||
allocated = b.len;
|
||||
if (allocated != maxlen)
|
||||
{
|
||||
b.len = nlen - s; // back up
|
||||
return dummy; // scribble during error recov.
|
||||
}
|
||||
// after realloc, recompute pointers
|
||||
b.len = nlen;
|
||||
assert(b.len <= allocated);
|
||||
return limit() - s;
|
||||
}
|
||||
|
||||
void fillbytes::ensureSize(size_t s)
|
||||
{
|
||||
if (allocated >= s)
|
||||
return;
|
||||
size_t len0 = b.len;
|
||||
grow(s - size());
|
||||
b.len = len0; // put it back
|
||||
}
|
||||
|
||||
int ptrlist::indexOf(const void *x)
|
||||
{
|
||||
int len = length();
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
if (get(i) == x)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void ptrlist::freeAll()
|
||||
{
|
||||
int len = length();
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
void *p = (void *)get(i);
|
||||
if (p != nullptr)
|
||||
{
|
||||
::free(p);
|
||||
}
|
||||
}
|
||||
free();
|
||||
}
|
||||
|
||||
int intlist::indexOf(int x)
|
||||
{
|
||||
int len = length();
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
if (get(i) == x)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
@ -1,286 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
struct bytes
|
||||
{
|
||||
int8_t *ptr;
|
||||
size_t len;
|
||||
int8_t *limit()
|
||||
{
|
||||
return ptr + len;
|
||||
}
|
||||
|
||||
void set(int8_t *ptr_, size_t len_)
|
||||
{
|
||||
ptr = ptr_;
|
||||
len = len_;
|
||||
}
|
||||
void set(const char *str)
|
||||
{
|
||||
ptr = (int8_t *)str;
|
||||
len = strlen(str);
|
||||
}
|
||||
bool inBounds(const void *p); // p in [ptr, limit)
|
||||
void malloc(size_t len_);
|
||||
void realloc(size_t len_);
|
||||
void free();
|
||||
void copyFrom(const void *ptr_, size_t len_, size_t offset = 0);
|
||||
void saveFrom(const void *ptr_, size_t len_);
|
||||
void saveFrom(const char *str)
|
||||
{
|
||||
saveFrom(str, strlen(str));
|
||||
}
|
||||
void copyFrom(bytes &other, size_t offset = 0)
|
||||
{
|
||||
copyFrom(other.ptr, other.len, offset);
|
||||
}
|
||||
void saveFrom(bytes &other)
|
||||
{
|
||||
saveFrom(other.ptr, other.len);
|
||||
}
|
||||
void clear(int fill_byte = 0)
|
||||
{
|
||||
memset(ptr, fill_byte, len);
|
||||
}
|
||||
int8_t *writeTo(int8_t *bp);
|
||||
bool equals(bytes &other)
|
||||
{
|
||||
return 0 == compareTo(other);
|
||||
}
|
||||
int compareTo(bytes &other);
|
||||
bool contains(int8_t c)
|
||||
{
|
||||
return indexOf(c) >= 0;
|
||||
}
|
||||
int indexOf(int8_t c);
|
||||
// substrings:
|
||||
static bytes of(int8_t *ptr, size_t len)
|
||||
{
|
||||
bytes res;
|
||||
res.set(ptr, len);
|
||||
return res;
|
||||
}
|
||||
bytes slice(size_t beg, size_t end)
|
||||
{
|
||||
bytes res;
|
||||
res.ptr = ptr + beg;
|
||||
res.len = end - beg;
|
||||
assert(res.len == 0 ||(inBounds(res.ptr) && inBounds(res.limit() - 1)));
|
||||
return res;
|
||||
}
|
||||
// building C strings inside byte buffers:
|
||||
bytes &strcat(const char *str)
|
||||
{
|
||||
::strcat((char *)ptr, str);
|
||||
return *this;
|
||||
}
|
||||
bytes &strcat(bytes &other)
|
||||
{
|
||||
::strncat((char *)ptr, (char *)other.ptr, other.len);
|
||||
return *this;
|
||||
}
|
||||
char *strval()
|
||||
{
|
||||
assert(strlen((char *)ptr) == len);
|
||||
return (char *)ptr;
|
||||
}
|
||||
};
|
||||
#define BYTES_OF(var) (bytes::of((int8_t *)&(var), sizeof(var)))
|
||||
|
||||
struct fillbytes
|
||||
{
|
||||
bytes b;
|
||||
size_t allocated;
|
||||
|
||||
int8_t *base()
|
||||
{
|
||||
return b.ptr;
|
||||
}
|
||||
size_t size()
|
||||
{
|
||||
return b.len;
|
||||
}
|
||||
int8_t *limit()
|
||||
{
|
||||
return b.limit();
|
||||
} // logical limit
|
||||
void setLimit(int8_t *lp)
|
||||
{
|
||||
assert(isAllocated(lp));
|
||||
b.len = lp - b.ptr;
|
||||
}
|
||||
int8_t *end()
|
||||
{
|
||||
return b.ptr + allocated;
|
||||
} // physical limit
|
||||
int8_t *loc(size_t o)
|
||||
{
|
||||
assert(o < b.len);
|
||||
return b.ptr + o;
|
||||
}
|
||||
void init()
|
||||
{
|
||||
allocated = 0;
|
||||
b.set(nullptr, 0);
|
||||
}
|
||||
void init(size_t s)
|
||||
{
|
||||
init();
|
||||
ensureSize(s);
|
||||
}
|
||||
void free()
|
||||
{
|
||||
if (allocated != 0)
|
||||
b.free();
|
||||
allocated = 0;
|
||||
}
|
||||
void empty()
|
||||
{
|
||||
b.len = 0;
|
||||
}
|
||||
int8_t *grow(size_t s); // grow so that limit() += s
|
||||
int getByte(uint32_t i)
|
||||
{
|
||||
return *loc(i) & 0xFF;
|
||||
}
|
||||
void addByte(int8_t x)
|
||||
{
|
||||
*grow(1) = x;
|
||||
}
|
||||
void ensureSize(size_t s); // make sure allocated >= s
|
||||
void trimToSize()
|
||||
{
|
||||
if (allocated > size())
|
||||
b.realloc(allocated = size());
|
||||
}
|
||||
bool canAppend(size_t s)
|
||||
{
|
||||
return allocated > b.len + s;
|
||||
}
|
||||
bool isAllocated(int8_t *p)
|
||||
{
|
||||
return p >= base() && p <= end();
|
||||
} // asserts
|
||||
void set(bytes &src)
|
||||
{
|
||||
set(src.ptr, src.len);
|
||||
}
|
||||
|
||||
void set(int8_t *ptr, size_t len)
|
||||
{
|
||||
b.set(ptr, len);
|
||||
allocated = 0; // mark as not reallocatable
|
||||
}
|
||||
|
||||
// block operations on resizing byte buffer:
|
||||
fillbytes &append(const void *ptr_, size_t len_)
|
||||
{
|
||||
memcpy(grow(len_), ptr_, len_);
|
||||
return (*this);
|
||||
}
|
||||
fillbytes &append(bytes &other)
|
||||
{
|
||||
return append(other.ptr, other.len);
|
||||
}
|
||||
fillbytes &append(const char *str)
|
||||
{
|
||||
return append(str, strlen(str));
|
||||
}
|
||||
};
|
||||
|
||||
struct ptrlist : fillbytes
|
||||
{
|
||||
typedef const void *cvptr;
|
||||
int length()
|
||||
{
|
||||
return (int)(size() / sizeof(cvptr));
|
||||
}
|
||||
cvptr *base()
|
||||
{
|
||||
return (cvptr *)fillbytes::base();
|
||||
}
|
||||
cvptr &get(int i)
|
||||
{
|
||||
return *(cvptr *)loc(i * sizeof(cvptr));
|
||||
}
|
||||
cvptr *limit()
|
||||
{
|
||||
return (cvptr *)fillbytes::limit();
|
||||
}
|
||||
void add(cvptr x)
|
||||
{
|
||||
*(cvptr *)grow(sizeof(x)) = x;
|
||||
}
|
||||
void popTo(int l)
|
||||
{
|
||||
assert(l <= length());
|
||||
b.len = l * sizeof(cvptr);
|
||||
}
|
||||
int indexOf(cvptr x);
|
||||
bool contains(cvptr x)
|
||||
{
|
||||
return indexOf(x) >= 0;
|
||||
}
|
||||
void freeAll(); // frees every ptr on the list, plus the list itself
|
||||
};
|
||||
// Use a macro rather than mess with subtle mismatches
|
||||
// between member and non-member function pointers.
|
||||
#define PTRLIST_QSORT(ptrls, fn) ::qsort((ptrls).base(), (ptrls).length(), sizeof(void *), fn)
|
||||
|
||||
struct intlist : fillbytes
|
||||
{
|
||||
int length()
|
||||
{
|
||||
return (int)(size() / sizeof(int));
|
||||
}
|
||||
int *base()
|
||||
{
|
||||
return (int *)fillbytes::base();
|
||||
}
|
||||
int &get(int i)
|
||||
{
|
||||
return *(int *)loc(i * sizeof(int));
|
||||
}
|
||||
int *limit()
|
||||
{
|
||||
return (int *)fillbytes::limit();
|
||||
}
|
||||
void add(int x)
|
||||
{
|
||||
*(int *)grow(sizeof(x)) = x;
|
||||
}
|
||||
void popTo(int l)
|
||||
{
|
||||
assert(l <= length());
|
||||
b.len = l * sizeof(int);
|
||||
}
|
||||
int indexOf(int x);
|
||||
bool contains(int x)
|
||||
{
|
||||
return indexOf(x) >= 0;
|
||||
}
|
||||
};
|
File diff suppressed because it is too large
Load Diff
@ -1,247 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
struct unpacker;
|
||||
|
||||
#define INT_MAX_VALUE ((int)0x7FFFFFFF)
|
||||
#define INT_MIN_VALUE ((int)0x80000000)
|
||||
|
||||
#define CODING_SPEC(B, H, S, D) ((B) << 20 | (H) << 8 | (S) << 4 | (D) << 0)
|
||||
#define CODING_B(x) ((x) >> 20 & 0xF)
|
||||
#define CODING_H(x) ((x) >> 8 & 0xFFF)
|
||||
#define CODING_S(x) ((x) >> 4 & 0xF)
|
||||
#define CODING_D(x) ((x) >> 0 & 0xF)
|
||||
|
||||
#define CODING_INIT(B, H, S, D) \
|
||||
{ \
|
||||
CODING_SPEC(B, H, S, D), 0, 0, 0, 0, 0, 0, 0, 0 \
|
||||
}
|
||||
|
||||
// For debugging purposes, some compilers do not like this and will complain.
|
||||
// #define long do_not_use_C_long_types_use_jlong_or_int
|
||||
// Use of the type "long" is problematic, do not use it.
|
||||
|
||||
struct coding
|
||||
{
|
||||
int spec; // B,H,S,D
|
||||
|
||||
// Handy values derived from the spec:
|
||||
int B()
|
||||
{
|
||||
return CODING_B(spec);
|
||||
}
|
||||
int H()
|
||||
{
|
||||
return CODING_H(spec);
|
||||
}
|
||||
int S()
|
||||
{
|
||||
return CODING_S(spec);
|
||||
}
|
||||
int D()
|
||||
{
|
||||
return CODING_D(spec);
|
||||
}
|
||||
int L()
|
||||
{
|
||||
return 256 - CODING_H(spec);
|
||||
}
|
||||
int min, max;
|
||||
int umin, umax;
|
||||
char isSigned, isSubrange, isFullRange, isMalloc;
|
||||
|
||||
coding *init(); // returns self or nullptr if error
|
||||
coding *initFrom(int spec_)
|
||||
{
|
||||
assert(this->spec == 0);
|
||||
this->spec = spec_;
|
||||
return init();
|
||||
}
|
||||
|
||||
static coding *findBySpec(int spec);
|
||||
static coding *findBySpec(int B, int H, int S = 0, int D = 0);
|
||||
static coding *findByIndex(int irregularCodingIndex);
|
||||
|
||||
static uint32_t parse(byte *&rp, int B, int H);
|
||||
static uint32_t parse_lgH(byte *&rp, int B, int H, int lgH);
|
||||
static void parseMultiple(byte *&rp, int N, byte *limit, int B, int H);
|
||||
|
||||
uint32_t parse(byte *&rp)
|
||||
{
|
||||
return parse(rp, CODING_B(spec), CODING_H(spec));
|
||||
}
|
||||
void parseMultiple(byte *&rp, int N, byte *limit)
|
||||
{
|
||||
parseMultiple(rp, N, limit, CODING_B(spec), CODING_H(spec));
|
||||
}
|
||||
|
||||
bool canRepresent(int x)
|
||||
{
|
||||
return (x >= min && x <= max);
|
||||
}
|
||||
bool canRepresentUnsigned(int x)
|
||||
{
|
||||
return (x >= umin && x <= umax);
|
||||
}
|
||||
|
||||
int sumInUnsignedRange(int x, int y);
|
||||
|
||||
int readFrom(byte *&rpVar, int *dbase);
|
||||
void readArrayFrom(byte *&rpVar, int *dbase, int length, int *values);
|
||||
void skipArrayFrom(byte *&rpVar, int length)
|
||||
{
|
||||
readArrayFrom(rpVar, (int *)NULL, length, (int *)NULL);
|
||||
}
|
||||
|
||||
void free(); // free self if isMalloc
|
||||
};
|
||||
|
||||
enum coding_method_kind
|
||||
{
|
||||
cmk_ERROR,
|
||||
cmk_BHS,
|
||||
cmk_BHS0,
|
||||
cmk_BHS1,
|
||||
cmk_BHSD1,
|
||||
cmk_BHS1D1full, // isFullRange
|
||||
cmk_BHS1D1sub, // isSubRange
|
||||
|
||||
// special cases hand-optimized (~50% of all decoded values)
|
||||
cmk_BYTE1, //(1,256) 6%
|
||||
cmk_CHAR3, //(3,128) 7%
|
||||
cmk_UNSIGNED5, //(5,64) 13%
|
||||
cmk_DELTA5, //(5,64,1,1) 5%
|
||||
cmk_BCI5, //(5,4) 18%
|
||||
cmk_BRANCH5, //(5,4,2) 4%
|
||||
// cmk_UNSIGNED5H16, //(5,16) 5%
|
||||
// cmk_UNSIGNED2H4, //(2,4) 6%
|
||||
// cmk_DELTA4H8, //(4,8,1,1) 10%
|
||||
// cmk_DELTA3H16, //(3,16,1,1) 9%
|
||||
cmk_BHS_LIMIT,
|
||||
cmk_pop,
|
||||
cmk_pop_BHS0,
|
||||
cmk_pop_BYTE1,
|
||||
cmk_pop_LIMIT,
|
||||
cmk_LIMIT
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
BYTE1_spec = CODING_SPEC(1, 256, 0, 0),
|
||||
CHAR3_spec = CODING_SPEC(3, 128, 0, 0),
|
||||
UNSIGNED4_spec = CODING_SPEC(4, 256, 0, 0),
|
||||
UNSIGNED5_spec = CODING_SPEC(5, 64, 0, 0),
|
||||
SIGNED5_spec = CODING_SPEC(5, 64, 1, 0),
|
||||
DELTA5_spec = CODING_SPEC(5, 64, 1, 1),
|
||||
UDELTA5_spec = CODING_SPEC(5, 64, 0, 1),
|
||||
MDELTA5_spec = CODING_SPEC(5, 64, 2, 1),
|
||||
BCI5_spec = CODING_SPEC(5, 4, 0, 0),
|
||||
BRANCH5_spec = CODING_SPEC(5, 4, 2, 0)
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
B_MAX = 5,
|
||||
C_SLOP = B_MAX * 10
|
||||
};
|
||||
|
||||
struct coding_method;
|
||||
|
||||
// iterator under the control of a meta-coding
|
||||
struct value_stream
|
||||
{
|
||||
// current coding of values or values
|
||||
coding c; // B,H,S,D,etc.
|
||||
coding_method_kind cmk; // type of decoding needed
|
||||
byte *rp; // read pointer
|
||||
byte *rplimit; // final value of read pointer
|
||||
int sum; // partial sum of all values so far (D=1 only)
|
||||
coding_method *cm; // coding method that defines this stream
|
||||
|
||||
void init(byte *band_rp, byte *band_limit, coding *defc);
|
||||
void init(byte *band_rp, byte *band_limit, int spec)
|
||||
{
|
||||
init(band_rp, band_limit, coding::findBySpec(spec));
|
||||
}
|
||||
|
||||
void setCoding(coding *c);
|
||||
void setCoding(int spec)
|
||||
{
|
||||
setCoding(coding::findBySpec(spec));
|
||||
}
|
||||
|
||||
// Parse and decode a single value.
|
||||
int getInt();
|
||||
|
||||
// Parse and decode a single byte, with no error checks.
|
||||
int getByte()
|
||||
{
|
||||
assert(cmk == cmk_BYTE1);
|
||||
assert(rp < rplimit);
|
||||
return *rp++ & 0xFF;
|
||||
}
|
||||
|
||||
// Used only for asserts.
|
||||
bool hasValue();
|
||||
|
||||
void done()
|
||||
{
|
||||
assert(!hasValue());
|
||||
}
|
||||
|
||||
// Sometimes a value stream has an auxiliary (but there are never two).
|
||||
value_stream *helper()
|
||||
{
|
||||
assert(hasHelper());
|
||||
return this + 1;
|
||||
}
|
||||
bool hasHelper();
|
||||
};
|
||||
|
||||
struct coding_method
|
||||
{
|
||||
value_stream vs0; // initial state snapshot (vs.meta==this)
|
||||
|
||||
coding_method *next; // what to do when we run out of bytes
|
||||
|
||||
// these fields are used for pop codes only:
|
||||
int *fValues; // favored value array
|
||||
int fVlength; // maximum favored value token
|
||||
coding_method *uValues; // unfavored value stream
|
||||
|
||||
// pointer to outer unpacker, for error checks etc.
|
||||
unpacker *u;
|
||||
|
||||
// Initialize a value stream.
|
||||
void reset(value_stream *state);
|
||||
|
||||
// Parse a band header, size a band, and initialize for further action.
|
||||
// band_rp advances (but not past band_limit), and meta_rp advances.
|
||||
// The mode gives context, such as "inside a pop".
|
||||
// The defc and N are the incoming parameters to a meta-coding.
|
||||
// The value sink is used to collect output values, when desired.
|
||||
void init(byte *&band_rp, byte *band_limit, byte *&meta_rp, int mode, coding *defc, int N,
|
||||
intlist *valueSink);
|
||||
};
|
@ -1,442 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2005, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
Java Class Version numbers history
|
||||
1.0 to 1.3.X 45,3
|
||||
1.4 to 1.4.X 46,0
|
||||
1.5 to 1.5.X 49,0
|
||||
1.6 to 1.5.x 50,0 NOTE Assumed for now
|
||||
*/
|
||||
|
||||
// classfile constants
|
||||
#define JAVA_MAGIC 0xCAFEBABE
|
||||
#define JAVA_MIN_MAJOR_VERSION 45
|
||||
#define JAVA_MIN_MINOR_VERSION 3
|
||||
#define JAVA5_MAX_MAJOR_VERSION 49
|
||||
#define JAVA5_MAX_MINOR_VERSION 0
|
||||
// NOTE: Assume for now
|
||||
#define JAVA6_MAX_MAJOR_VERSION 50
|
||||
#define JAVA6_MAX_MINOR_VERSION 0
|
||||
|
||||
// package file constants
|
||||
#define JAVA_PACKAGE_MAGIC 0xCAFED00D
|
||||
#define JAVA5_PACKAGE_MAJOR_VERSION 150
|
||||
#define JAVA5_PACKAGE_MINOR_VERSION 7
|
||||
|
||||
#define JAVA6_PACKAGE_MAJOR_VERSION 160
|
||||
#define JAVA6_PACKAGE_MINOR_VERSION 1
|
||||
|
||||
// magic number for gzip streams (for processing pack200-gzip data)
|
||||
#define GZIP_MAGIC 0x1F8B0800
|
||||
#define GZIP_MAGIC_MASK 0xFFFFFF00 // last \bchar\b is variable "flg" field
|
||||
|
||||
enum
|
||||
{
|
||||
CONSTANT_None,
|
||||
CONSTANT_Utf8,
|
||||
CONSTANT_unused2, /* unused, was Unicode */
|
||||
CONSTANT_Integer,
|
||||
CONSTANT_Float,
|
||||
CONSTANT_Long,
|
||||
CONSTANT_Double,
|
||||
CONSTANT_Class,
|
||||
CONSTANT_String,
|
||||
CONSTANT_Fieldref,
|
||||
CONSTANT_Methodref,
|
||||
CONSTANT_InterfaceMethodref,
|
||||
CONSTANT_NameandType,
|
||||
CONSTANT_Signature = 13,
|
||||
CONSTANT_All = 14,
|
||||
CONSTANT_Limit = 15,
|
||||
CONSTANT_NONE = 0,
|
||||
CONSTANT_Literal = 20, // pseudo-tag for debugging
|
||||
CONSTANT_Member = 21, // pseudo-tag for debugging
|
||||
SUBINDEX_BIT = 64, // combined with CONSTANT_xxx for ixTag
|
||||
ACC_STATIC = 0x0008,
|
||||
ACC_IC_LONG_FORM = (1 << 16), // for ic_flags
|
||||
CLASS_ATTR_SourceFile = 17,
|
||||
CLASS_ATTR_EnclosingMethod = 18,
|
||||
CLASS_ATTR_InnerClasses = 23,
|
||||
CLASS_ATTR_ClassFile_version = 24,
|
||||
FIELD_ATTR_ConstantValue = 17,
|
||||
METHOD_ATTR_Code = 17,
|
||||
METHOD_ATTR_Exceptions = 18,
|
||||
METHOD_ATTR_RuntimeVisibleParameterAnnotations = 23,
|
||||
METHOD_ATTR_RuntimeInvisibleParameterAnnotations = 24,
|
||||
METHOD_ATTR_AnnotationDefault = 25,
|
||||
CODE_ATTR_StackMapTable = 0,
|
||||
CODE_ATTR_LineNumberTable = 1,
|
||||
CODE_ATTR_LocalVariableTable = 2,
|
||||
CODE_ATTR_LocalVariableTypeTable = 3,
|
||||
// X_ATTR_Synthetic = 12, // ACC_SYNTHETIC; not predefined
|
||||
X_ATTR_Signature = 19,
|
||||
X_ATTR_Deprecated = 20,
|
||||
X_ATTR_RuntimeVisibleAnnotations = 21,
|
||||
X_ATTR_RuntimeInvisibleAnnotations = 22,
|
||||
X_ATTR_OVERFLOW = 16,
|
||||
X_ATTR_LIMIT_NO_FLAGS_HI = 32,
|
||||
X_ATTR_LIMIT_FLAGS_HI = 63,
|
||||
|
||||
#define O_ATTR_DO(F) \
|
||||
F(X_ATTR_OVERFLOW, 01) \
|
||||
/*(end)*/
|
||||
#define X_ATTR_DO(F) \
|
||||
O_ATTR_DO(F) F(X_ATTR_Signature, Signature) F(X_ATTR_Deprecated, Deprecated) \
|
||||
F(X_ATTR_RuntimeVisibleAnnotations, RuntimeVisibleAnnotations) \
|
||||
F(X_ATTR_RuntimeInvisibleAnnotations, RuntimeInvisibleAnnotations) \
|
||||
/*F(X_ATTR_Synthetic,Synthetic)*/ \
|
||||
/*(end)*/
|
||||
#define CLASS_ATTR_DO(F) \
|
||||
F(CLASS_ATTR_SourceFile, SourceFile) F(CLASS_ATTR_InnerClasses, InnerClasses) \
|
||||
F(CLASS_ATTR_EnclosingMethod, EnclosingMethod) F(CLASS_ATTR_ClassFile_version, 02) \
|
||||
/*(end)*/
|
||||
#define FIELD_ATTR_DO(F) \
|
||||
F(FIELD_ATTR_ConstantValue, ConstantValue) \
|
||||
/*(end)*/
|
||||
#define METHOD_ATTR_DO(F) \
|
||||
F(METHOD_ATTR_Code, Code) F(METHOD_ATTR_Exceptions, Exceptions) \
|
||||
F(METHOD_ATTR_RuntimeVisibleParameterAnnotations, RuntimeVisibleParameterAnnotations) \
|
||||
F(METHOD_ATTR_RuntimeInvisibleParameterAnnotations, \
|
||||
RuntimeInvisibleParameterAnnotations) \
|
||||
F(METHOD_ATTR_AnnotationDefault, AnnotationDefault) \
|
||||
/*(end)*/
|
||||
#define CODE_ATTR_DO(F) \
|
||||
F(CODE_ATTR_StackMapTable, StackMapTable) F(CODE_ATTR_LineNumberTable, LineNumberTable) \
|
||||
F(CODE_ATTR_LocalVariableTable, LocalVariableTable) \
|
||||
F(CODE_ATTR_LocalVariableTypeTable, LocalVariableTypeTable) \
|
||||
/*(end)*/
|
||||
#define ALL_ATTR_DO(F) \
|
||||
X_ATTR_DO(F) CLASS_ATTR_DO(F) FIELD_ATTR_DO(F) METHOD_ATTR_DO(F) CODE_ATTR_DO(F) \
|
||||
/*(end)*/
|
||||
|
||||
// attribute "context types"
|
||||
ATTR_CONTEXT_CLASS = 0,
|
||||
ATTR_CONTEXT_FIELD = 1,
|
||||
ATTR_CONTEXT_METHOD = 2,
|
||||
ATTR_CONTEXT_CODE = 3,
|
||||
ATTR_CONTEXT_LIMIT = 4,
|
||||
|
||||
// constants for parsed layouts (stored in band::le_kind)
|
||||
EK_NONE = 0, // not a layout element
|
||||
EK_INT = 'I', // B H I SH etc., also FH etc.
|
||||
EK_BCI = 'P', // PH etc.
|
||||
EK_BCID = 'Q', // POH etc.
|
||||
EK_BCO = 'O', // OH etc.
|
||||
EK_REPL = 'N', // NH[...] etc.
|
||||
EK_REF = 'R', // RUH, RUNH, KQH, etc.
|
||||
EK_UN = 'T', // TB(...)[...] etc.
|
||||
EK_CASE = 'K', // (...)[...] etc.
|
||||
EK_CALL = '(', // (0), (1), etc.
|
||||
EK_CBLE = '[', // [...][...] etc.
|
||||
NO_BAND_INDEX = -1,
|
||||
|
||||
// File option bits, from LSB in ascending bit position.
|
||||
FO_DEFLATE_HINT = 1 << 0,
|
||||
FO_IS_CLASS_STUB = 1 << 1,
|
||||
|
||||
// Archive option bits, from LSB in ascending bit position:
|
||||
AO_HAVE_SPECIAL_FORMATS = 1 << 0,
|
||||
AO_HAVE_CP_NUMBERS = 1 << 1,
|
||||
AO_HAVE_ALL_CODE_FLAGS = 1 << 2,
|
||||
AO_3_UNUSED_MBZ = 1 << 3,
|
||||
AO_HAVE_FILE_HEADERS = 1 << 4,
|
||||
AO_DEFLATE_HINT = 1 << 5,
|
||||
AO_HAVE_FILE_MODTIME = 1 << 6,
|
||||
AO_HAVE_FILE_OPTIONS = 1 << 7,
|
||||
AO_HAVE_FILE_SIZE_HI = 1 << 8,
|
||||
AO_HAVE_CLASS_FLAGS_HI = 1 << 9,
|
||||
AO_HAVE_FIELD_FLAGS_HI = 1 << 10,
|
||||
AO_HAVE_METHOD_FLAGS_HI = 1 << 11,
|
||||
AO_HAVE_CODE_FLAGS_HI = 1 << 12,
|
||||
#define ARCHIVE_BIT_DO(F) \
|
||||
F(AO_HAVE_SPECIAL_FORMATS) F(AO_HAVE_CP_NUMBERS) F(AO_HAVE_ALL_CODE_FLAGS) \
|
||||
/*F(AO_3_UNUSED_MBZ)*/ \
|
||||
F(AO_HAVE_FILE_HEADERS) F(AO_DEFLATE_HINT) F(AO_HAVE_FILE_MODTIME) \
|
||||
F(AO_HAVE_FILE_OPTIONS) F(AO_HAVE_FILE_SIZE_HI) F(AO_HAVE_CLASS_FLAGS_HI) \
|
||||
F(AO_HAVE_FIELD_FLAGS_HI) F(AO_HAVE_METHOD_FLAGS_HI) F(AO_HAVE_CODE_FLAGS_HI) \
|
||||
/*(end)*/
|
||||
|
||||
// Constants for decoding attribute definition header bytes.
|
||||
ADH_CONTEXT_MASK = 0x3, // (hdr & ADH_CONTEXT_MASK)
|
||||
ADH_BIT_SHIFT = 0x2, // (hdr >> ADH_BIT_SHIFT)
|
||||
ADH_BIT_IS_LSB = 1, // (hdr >> ADH_BIT_SHIFT) - ADH_BIT_IS_LSB
|
||||
#define ADH_BYTE(context, index) ((((index) + ADH_BIT_IS_LSB) << ADH_BIT_SHIFT) + (context))
|
||||
#define ADH_BYTE_CONTEXT(adhb) ((adhb) & ADH_CONTEXT_MASK)
|
||||
#define ADH_BYTE_INDEX(adhb) (((adhb) >> ADH_BIT_SHIFT) - ADH_BIT_IS_LSB)
|
||||
NO_MODTIME = 0, // nullptr modtime value
|
||||
|
||||
// meta-coding
|
||||
_meta_default = 0,
|
||||
_meta_canon_min = 1,
|
||||
_meta_canon_max = 115,
|
||||
_meta_arb = 116,
|
||||
_meta_run = 117,
|
||||
_meta_pop = 141,
|
||||
_meta_limit = 189,
|
||||
_meta_error = 255,
|
||||
_xxx_1_end
|
||||
};
|
||||
|
||||
// Bytecodes.
|
||||
|
||||
enum
|
||||
{
|
||||
bc_nop = 0, // 0x00
|
||||
bc_aconst_null = 1, // 0x01
|
||||
bc_iconst_m1 = 2, // 0x02
|
||||
bc_iconst_0 = 3, // 0x03
|
||||
bc_iconst_1 = 4, // 0x04
|
||||
bc_iconst_2 = 5, // 0x05
|
||||
bc_iconst_3 = 6, // 0x06
|
||||
bc_iconst_4 = 7, // 0x07
|
||||
bc_iconst_5 = 8, // 0x08
|
||||
bc_lconst_0 = 9, // 0x09
|
||||
bc_lconst_1 = 10, // 0x0a
|
||||
bc_fconst_0 = 11, // 0x0b
|
||||
bc_fconst_1 = 12, // 0x0c
|
||||
bc_fconst_2 = 13, // 0x0d
|
||||
bc_dconst_0 = 14, // 0x0e
|
||||
bc_dconst_1 = 15, // 0x0f
|
||||
bc_bipush = 16, // 0x10
|
||||
bc_sipush = 17, // 0x11
|
||||
bc_ldc = 18, // 0x12
|
||||
bc_ldc_w = 19, // 0x13
|
||||
bc_ldc2_w = 20, // 0x14
|
||||
bc_iload = 21, // 0x15
|
||||
bc_lload = 22, // 0x16
|
||||
bc_fload = 23, // 0x17
|
||||
bc_dload = 24, // 0x18
|
||||
bc_aload = 25, // 0x19
|
||||
bc_iload_0 = 26, // 0x1a
|
||||
bc_iload_1 = 27, // 0x1b
|
||||
bc_iload_2 = 28, // 0x1c
|
||||
bc_iload_3 = 29, // 0x1d
|
||||
bc_lload_0 = 30, // 0x1e
|
||||
bc_lload_1 = 31, // 0x1f
|
||||
bc_lload_2 = 32, // 0x20
|
||||
bc_lload_3 = 33, // 0x21
|
||||
bc_fload_0 = 34, // 0x22
|
||||
bc_fload_1 = 35, // 0x23
|
||||
bc_fload_2 = 36, // 0x24
|
||||
bc_fload_3 = 37, // 0x25
|
||||
bc_dload_0 = 38, // 0x26
|
||||
bc_dload_1 = 39, // 0x27
|
||||
bc_dload_2 = 40, // 0x28
|
||||
bc_dload_3 = 41, // 0x29
|
||||
bc_aload_0 = 42, // 0x2a
|
||||
bc_aload_1 = 43, // 0x2b
|
||||
bc_aload_2 = 44, // 0x2c
|
||||
bc_aload_3 = 45, // 0x2d
|
||||
bc_iaload = 46, // 0x2e
|
||||
bc_laload = 47, // 0x2f
|
||||
bc_faload = 48, // 0x30
|
||||
bc_daload = 49, // 0x31
|
||||
bc_aaload = 50, // 0x32
|
||||
bc_baload = 51, // 0x33
|
||||
bc_caload = 52, // 0x34
|
||||
bc_saload = 53, // 0x35
|
||||
bc_istore = 54, // 0x36
|
||||
bc_lstore = 55, // 0x37
|
||||
bc_fstore = 56, // 0x38
|
||||
bc_dstore = 57, // 0x39
|
||||
bc_astore = 58, // 0x3a
|
||||
bc_istore_0 = 59, // 0x3b
|
||||
bc_istore_1 = 60, // 0x3c
|
||||
bc_istore_2 = 61, // 0x3d
|
||||
bc_istore_3 = 62, // 0x3e
|
||||
bc_lstore_0 = 63, // 0x3f
|
||||
bc_lstore_1 = 64, // 0x40
|
||||
bc_lstore_2 = 65, // 0x41
|
||||
bc_lstore_3 = 66, // 0x42
|
||||
bc_fstore_0 = 67, // 0x43
|
||||
bc_fstore_1 = 68, // 0x44
|
||||
bc_fstore_2 = 69, // 0x45
|
||||
bc_fstore_3 = 70, // 0x46
|
||||
bc_dstore_0 = 71, // 0x47
|
||||
bc_dstore_1 = 72, // 0x48
|
||||
bc_dstore_2 = 73, // 0x49
|
||||
bc_dstore_3 = 74, // 0x4a
|
||||
bc_astore_0 = 75, // 0x4b
|
||||
bc_astore_1 = 76, // 0x4c
|
||||
bc_astore_2 = 77, // 0x4d
|
||||
bc_astore_3 = 78, // 0x4e
|
||||
bc_iastore = 79, // 0x4f
|
||||
bc_lastore = 80, // 0x50
|
||||
bc_fastore = 81, // 0x51
|
||||
bc_dastore = 82, // 0x52
|
||||
bc_aastore = 83, // 0x53
|
||||
bc_bastore = 84, // 0x54
|
||||
bc_castore = 85, // 0x55
|
||||
bc_sastore = 86, // 0x56
|
||||
bc_pop = 87, // 0x57
|
||||
bc_pop2 = 88, // 0x58
|
||||
bc_dup = 89, // 0x59
|
||||
bc_dup_x1 = 90, // 0x5a
|
||||
bc_dup_x2 = 91, // 0x5b
|
||||
bc_dup2 = 92, // 0x5c
|
||||
bc_dup2_x1 = 93, // 0x5d
|
||||
bc_dup2_x2 = 94, // 0x5e
|
||||
bc_swap = 95, // 0x5f
|
||||
bc_iadd = 96, // 0x60
|
||||
bc_ladd = 97, // 0x61
|
||||
bc_fadd = 98, // 0x62
|
||||
bc_dadd = 99, // 0x63
|
||||
bc_isub = 100, // 0x64
|
||||
bc_lsub = 101, // 0x65
|
||||
bc_fsub = 102, // 0x66
|
||||
bc_dsub = 103, // 0x67
|
||||
bc_imul = 104, // 0x68
|
||||
bc_lmul = 105, // 0x69
|
||||
bc_fmul = 106, // 0x6a
|
||||
bc_dmul = 107, // 0x6b
|
||||
bc_idiv = 108, // 0x6c
|
||||
bc_ldiv = 109, // 0x6d
|
||||
bc_fdiv = 110, // 0x6e
|
||||
bc_ddiv = 111, // 0x6f
|
||||
bc_irem = 112, // 0x70
|
||||
bc_lrem = 113, // 0x71
|
||||
bc_frem = 114, // 0x72
|
||||
bc_drem = 115, // 0x73
|
||||
bc_ineg = 116, // 0x74
|
||||
bc_lneg = 117, // 0x75
|
||||
bc_fneg = 118, // 0x76
|
||||
bc_dneg = 119, // 0x77
|
||||
bc_ishl = 120, // 0x78
|
||||
bc_lshl = 121, // 0x79
|
||||
bc_ishr = 122, // 0x7a
|
||||
bc_lshr = 123, // 0x7b
|
||||
bc_iushr = 124, // 0x7c
|
||||
bc_lushr = 125, // 0x7d
|
||||
bc_iand = 126, // 0x7e
|
||||
bc_land = 127, // 0x7f
|
||||
bc_ior = 128, // 0x80
|
||||
bc_lor = 129, // 0x81
|
||||
bc_ixor = 130, // 0x82
|
||||
bc_lxor = 131, // 0x83
|
||||
bc_iinc = 132, // 0x84
|
||||
bc_i2l = 133, // 0x85
|
||||
bc_i2f = 134, // 0x86
|
||||
bc_i2d = 135, // 0x87
|
||||
bc_l2i = 136, // 0x88
|
||||
bc_l2f = 137, // 0x89
|
||||
bc_l2d = 138, // 0x8a
|
||||
bc_f2i = 139, // 0x8b
|
||||
bc_f2l = 140, // 0x8c
|
||||
bc_f2d = 141, // 0x8d
|
||||
bc_d2i = 142, // 0x8e
|
||||
bc_d2l = 143, // 0x8f
|
||||
bc_d2f = 144, // 0x90
|
||||
bc_i2b = 145, // 0x91
|
||||
bc_i2c = 146, // 0x92
|
||||
bc_i2s = 147, // 0x93
|
||||
bc_lcmp = 148, // 0x94
|
||||
bc_fcmpl = 149, // 0x95
|
||||
bc_fcmpg = 150, // 0x96
|
||||
bc_dcmpl = 151, // 0x97
|
||||
bc_dcmpg = 152, // 0x98
|
||||
bc_ifeq = 153, // 0x99
|
||||
bc_ifne = 154, // 0x9a
|
||||
bc_iflt = 155, // 0x9b
|
||||
bc_ifge = 156, // 0x9c
|
||||
bc_ifgt = 157, // 0x9d
|
||||
bc_ifle = 158, // 0x9e
|
||||
bc_if_icmpeq = 159, // 0x9f
|
||||
bc_if_icmpne = 160, // 0xa0
|
||||
bc_if_icmplt = 161, // 0xa1
|
||||
bc_if_icmpge = 162, // 0xa2
|
||||
bc_if_icmpgt = 163, // 0xa3
|
||||
bc_if_icmple = 164, // 0xa4
|
||||
bc_if_acmpeq = 165, // 0xa5
|
||||
bc_if_acmpne = 166, // 0xa6
|
||||
bc_goto = 167, // 0xa7
|
||||
bc_jsr = 168, // 0xa8
|
||||
bc_ret = 169, // 0xa9
|
||||
bc_tableswitch = 170, // 0xaa
|
||||
bc_lookupswitch = 171, // 0xab
|
||||
bc_ireturn = 172, // 0xac
|
||||
bc_lreturn = 173, // 0xad
|
||||
bc_freturn = 174, // 0xae
|
||||
bc_dreturn = 175, // 0xaf
|
||||
bc_areturn = 176, // 0xb0
|
||||
bc_return = 177, // 0xb1
|
||||
bc_getstatic = 178, // 0xb2
|
||||
bc_putstatic = 179, // 0xb3
|
||||
bc_getfield = 180, // 0xb4
|
||||
bc_putfield = 181, // 0xb5
|
||||
bc_invokevirtual = 182, // 0xb6
|
||||
bc_invokespecial = 183, // 0xb7
|
||||
bc_invokestatic = 184, // 0xb8
|
||||
bc_invokeinterface = 185, // 0xb9
|
||||
bc_xxxunusedxxx = 186, // 0xba
|
||||
bc_new = 187, // 0xbb
|
||||
bc_newarray = 188, // 0xbc
|
||||
bc_anewarray = 189, // 0xbd
|
||||
bc_arraylength = 190, // 0xbe
|
||||
bc_athrow = 191, // 0xbf
|
||||
bc_checkcast = 192, // 0xc0
|
||||
bc_instanceof = 193, // 0xc1
|
||||
bc_monitorenter = 194, // 0xc2
|
||||
bc_monitorexit = 195, // 0xc3
|
||||
bc_wide = 196, // 0xc4
|
||||
bc_multianewarray = 197, // 0xc5
|
||||
bc_ifnull = 198, // 0xc6
|
||||
bc_ifnonnull = 199, // 0xc7
|
||||
bc_goto_w = 200, // 0xc8
|
||||
bc_jsr_w = 201, // 0xc9
|
||||
bc_bytecode_limit = 202 // 0xca
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
bc_end_marker = 255,
|
||||
bc_byte_escape = 254,
|
||||
bc_ref_escape = 253,
|
||||
_first_linker_op = bc_getstatic,
|
||||
_last_linker_op = bc_invokestatic,
|
||||
_num_linker_ops = (_last_linker_op - _first_linker_op) + 1,
|
||||
_self_linker_op = bc_bytecode_limit,
|
||||
_self_linker_aload_flag = 1 * _num_linker_ops,
|
||||
_self_linker_super_flag = 2 * _num_linker_ops,
|
||||
_self_linker_limit = _self_linker_op + 4 * _num_linker_ops,
|
||||
_invokeinit_op = _self_linker_limit,
|
||||
_invokeinit_self_option = 0,
|
||||
_invokeinit_super_option = 1,
|
||||
_invokeinit_new_option = 2,
|
||||
_invokeinit_limit = _invokeinit_op + 3,
|
||||
_xldc_op = _invokeinit_limit,
|
||||
bc_aldc = bc_ldc,
|
||||
bc_cldc = _xldc_op + 0,
|
||||
bc_ildc = _xldc_op + 1,
|
||||
bc_fldc = _xldc_op + 2,
|
||||
bc_aldc_w = bc_ldc_w,
|
||||
bc_cldc_w = _xldc_op + 3,
|
||||
bc_ildc_w = _xldc_op + 4,
|
||||
bc_fldc_w = _xldc_op + 5,
|
||||
bc_lldc2_w = bc_ldc2_w,
|
||||
bc_dldc2_w = _xldc_op + 6,
|
||||
_xldc_limit = _xldc_op + 7,
|
||||
_xxx_3_end
|
||||
};
|
@ -1,65 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2009, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
// random definitions
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <windows.h>
|
||||
#include <winuser.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
// Error messages that we have
|
||||
#define ERROR_ENOMEM "Memory allocation failed"
|
||||
#define ERROR_FORMAT "Corrupted pack file"
|
||||
#define ERROR_RESOURCE "Cannot extract resource file"
|
||||
#define ERROR_OVERFLOW "Internal buffer overflow"
|
||||
#define ERROR_INTERNAL "Internal error"
|
||||
|
||||
#define lengthof(array) (sizeof(array) / sizeof(array[0]))
|
||||
|
||||
#define NEW(T, n) (T *) must_malloc((int)(scale_size(n, sizeof(T))))
|
||||
#define U_NEW(T, n) (T *) u->alloc(scale_size(n, sizeof(T)))
|
||||
#define T_NEW(T, n) (T *) u->temp_alloc(scale_size(n, sizeof(T)))
|
||||
|
||||
typedef signed char byte;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define MKDIR(dir) mkdir(dir)
|
||||
#define getpid() _getpid()
|
||||
#define PATH_MAX MAX_PATH
|
||||
#define dup2(a, b) _dup2(a, b)
|
||||
#define strcasecmp(s1, s2) _stricmp(s1, s2)
|
||||
#define tempname _tempname
|
||||
#define sleep Sleep
|
||||
#else
|
||||
#define MKDIR(dir) mkdir(dir, 0777);
|
||||
#endif
|
||||
|
||||
/* Must cast to void *, then size_t, then int. */
|
||||
#define ptrlowbits(x) ((int)(size_t)(void *)(x))
|
||||
|
||||
#define DEFAULT_ARCHIVE_MODTIME 1060000000 // Aug 04, 2003 5:26 PM PDT
|
File diff suppressed because it is too large
Load Diff
@ -1,549 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// Global Structures
|
||||
struct jar;
|
||||
struct gunzip;
|
||||
struct band;
|
||||
struct constant_pool;
|
||||
struct entry;
|
||||
struct cpindex;
|
||||
struct inner_class;
|
||||
struct value_stream;
|
||||
|
||||
typedef int64_t (*read_input_fn_t)(unpacker *self, void *buf, int64_t minlen, int64_t maxlen);
|
||||
|
||||
struct cpindex
|
||||
{
|
||||
uint32_t len;
|
||||
entry *base1; // base of primary index
|
||||
entry **base2; // base of secondary index
|
||||
byte ixTag; // type of entries (!= CONSTANT_None), plus 64 if sub-index
|
||||
enum
|
||||
{
|
||||
SUB_TAG = 64
|
||||
};
|
||||
|
||||
entry *get(uint32_t i);
|
||||
|
||||
void init(int len_, entry *base1_, int ixTag_)
|
||||
{
|
||||
len = len_;
|
||||
base1 = base1_;
|
||||
base2 = nullptr;
|
||||
ixTag = ixTag_;
|
||||
}
|
||||
void init(int len_, entry **base2_, int ixTag_)
|
||||
{
|
||||
len = len_;
|
||||
base1 = nullptr;
|
||||
base2 = base2_;
|
||||
ixTag = ixTag_;
|
||||
}
|
||||
};
|
||||
|
||||
struct constant_pool
|
||||
{
|
||||
uint32_t nentries;
|
||||
entry *entries;
|
||||
entry *first_extra_entry;
|
||||
uint32_t maxentries; // total allocated size of entries
|
||||
|
||||
// Position and size of each homogeneous subrange:
|
||||
int tag_count[CONSTANT_Limit];
|
||||
int tag_base[CONSTANT_Limit];
|
||||
cpindex tag_index[CONSTANT_Limit];
|
||||
ptrlist tag_extras[CONSTANT_Limit];
|
||||
|
||||
cpindex *member_indexes; // indexed by 2*CONSTANT_Class.inord
|
||||
cpindex *getFieldIndex(entry *classRef);
|
||||
cpindex *getMethodIndex(entry *classRef);
|
||||
|
||||
inner_class **ic_index;
|
||||
inner_class **ic_child_index;
|
||||
inner_class *getIC(entry *inner);
|
||||
inner_class *getFirstChildIC(entry *outer);
|
||||
inner_class *getNextChildIC(inner_class *child);
|
||||
|
||||
int outputIndexLimit; // index limit after renumbering
|
||||
ptrlist outputEntries; // list of entry* needing output idx assigned
|
||||
|
||||
entry **hashTab;
|
||||
uint32_t hashTabLength;
|
||||
entry *&hashTabRef(byte tag, bytes &b);
|
||||
entry *ensureUtf8(bytes &b);
|
||||
entry *ensureClass(bytes &b);
|
||||
|
||||
// Well-known Utf8 symbols.
|
||||
enum
|
||||
{
|
||||
#define SNAME(n, s) s_##s,
|
||||
ALL_ATTR_DO(SNAME)
|
||||
#undef SNAME
|
||||
s_lt_init_gt, // <init>
|
||||
s_LIMIT
|
||||
};
|
||||
entry *sym[s_LIMIT];
|
||||
|
||||
// read counts from hdr, allocate main arrays
|
||||
enum
|
||||
{
|
||||
NUM_COUNTS = 12
|
||||
};
|
||||
void init(unpacker *u, int counts[NUM_COUNTS]);
|
||||
|
||||
// pointer to outer unpacker, for error checks etc.
|
||||
unpacker *u;
|
||||
|
||||
int getCount(byte tag)
|
||||
{
|
||||
assert((uint32_t)tag < CONSTANT_Limit);
|
||||
return tag_count[tag];
|
||||
}
|
||||
cpindex *getIndex(byte tag)
|
||||
{
|
||||
assert((uint32_t)tag < CONSTANT_Limit);
|
||||
return &tag_index[tag];
|
||||
}
|
||||
cpindex *getKQIndex(); // uses cur_descr
|
||||
|
||||
void expandSignatures();
|
||||
void initMemberIndexes();
|
||||
|
||||
void computeOutputOrder();
|
||||
void computeOutputIndexes();
|
||||
void resetOutputIndexes();
|
||||
};
|
||||
|
||||
/*
|
||||
* The unpacker provides the entry points to the unpack engine,
|
||||
* as well as maintains the state of the engine.
|
||||
*/
|
||||
struct unpacker
|
||||
{
|
||||
// One element of the resulting JAR.
|
||||
struct file
|
||||
{
|
||||
const char *name;
|
||||
uint64_t size;
|
||||
int modtime;
|
||||
int options;
|
||||
bytes data[2];
|
||||
// Note: If Sum(data[*].len) < size,
|
||||
// remaining bytes must be read directly from the input stream.
|
||||
bool deflate_hint()
|
||||
{
|
||||
return ((options & FO_DEFLATE_HINT) != 0);
|
||||
}
|
||||
};
|
||||
|
||||
// if running Unix-style, here are the inputs and outputs
|
||||
FILE *infileptr; // buffered
|
||||
bytes inbytes; // direct
|
||||
gunzip *gzin; // gunzip filter, if any
|
||||
jar *jarout; // output JAR file
|
||||
|
||||
// pointer to self, for U_NEW macro
|
||||
unpacker *u;
|
||||
|
||||
ptrlist mallocs; // list of guys to free when we are all done
|
||||
ptrlist tmallocs; // list of guys to free on next client request
|
||||
fillbytes smallbuf; // supplies small alloc requests
|
||||
fillbytes tsmallbuf; // supplies temporary small alloc requests
|
||||
|
||||
// option management members
|
||||
int verbose; // verbose level, 0 means no output
|
||||
int deflate_hint_or_zero; // ==0 means not set, otherwise -1 or 1
|
||||
int modification_time_or_zero;
|
||||
|
||||
// input stream
|
||||
fillbytes input; // the whole block (size is predicted, has slop too)
|
||||
bool live_input; // is the data in this block live?
|
||||
bool free_input; // must the input buffer be freed?
|
||||
byte *rp; // read pointer (< rplimit <= input.limit())
|
||||
byte *rplimit; // how much of the input block has been read?
|
||||
uint64_t bytes_read;
|
||||
int unsized_bytes_read;
|
||||
|
||||
// callback to read at least one byte, up to available input
|
||||
read_input_fn_t read_input_fn;
|
||||
|
||||
// archive header fields
|
||||
int magic, minver, majver;
|
||||
size_t archive_size;
|
||||
int archive_next_count, archive_options, archive_modtime;
|
||||
int band_headers_size;
|
||||
int file_count, attr_definition_count, ic_count, class_count;
|
||||
int default_class_minver, default_class_majver;
|
||||
int default_file_options, suppress_file_options; // not header fields
|
||||
int default_archive_modtime, default_file_modtime; // not header fields
|
||||
int code_count; // not a header field
|
||||
int files_remaining; // not a header field
|
||||
|
||||
// engine state
|
||||
band *all_bands; // indexed by band_number
|
||||
byte *meta_rp; // read-pointer into (copy of) band_headers
|
||||
constant_pool cp; // all constant pool information
|
||||
inner_class *ics; // InnerClasses
|
||||
|
||||
// output stream
|
||||
bytes output; // output block (either classfile head or tail)
|
||||
byte *wp; // write pointer (< wplimit == output.limit())
|
||||
byte *wpbase; // write pointer starting address (<= wp)
|
||||
byte *wplimit; // how much of the output block has been written?
|
||||
|
||||
// output state
|
||||
file cur_file;
|
||||
entry *cur_class; // CONSTANT_Class entry
|
||||
entry *cur_super; // CONSTANT_Class entry or nullptr
|
||||
entry *cur_descr; // CONSTANT_NameandType entry
|
||||
int cur_descr_flags; // flags corresponding to cur_descr
|
||||
int cur_class_minver, cur_class_majver;
|
||||
bool cur_class_has_local_ics;
|
||||
fillbytes cur_classfile_head;
|
||||
fillbytes cur_classfile_tail;
|
||||
int files_written; // also tells which file we're working on
|
||||
int classes_written; // also tells which class we're working on
|
||||
uint64_t bytes_written;
|
||||
intlist bcimap;
|
||||
fillbytes class_fixup_type;
|
||||
intlist class_fixup_offset;
|
||||
ptrlist class_fixup_ref;
|
||||
fillbytes code_fixup_type; // which format of branch operand?
|
||||
intlist code_fixup_offset; // location of operand needing fixup
|
||||
intlist code_fixup_source; // encoded ID of branch insn
|
||||
ptrlist requested_ics; // which ics need output?
|
||||
|
||||
// stats pertaining to multiple segments (updated on reset)
|
||||
uint64_t bytes_read_before_reset;
|
||||
uint64_t bytes_written_before_reset;
|
||||
int files_written_before_reset;
|
||||
int classes_written_before_reset;
|
||||
int segments_read_before_reset;
|
||||
|
||||
// attribute state
|
||||
struct layout_definition
|
||||
{
|
||||
uint32_t idx; // index (0..31...) which identifies this layout
|
||||
const char *name; // name of layout
|
||||
entry *nameEntry;
|
||||
const char *layout; // string of layout (not yet parsed)
|
||||
band **elems; // array of top-level layout elems (or callables)
|
||||
|
||||
bool hasCallables()
|
||||
{
|
||||
return layout[0] == '[';
|
||||
}
|
||||
band **bands()
|
||||
{
|
||||
assert(elems != nullptr);
|
||||
return elems;
|
||||
}
|
||||
};
|
||||
struct attr_definitions
|
||||
{
|
||||
unpacker *u; // pointer to self, for U_NEW macro
|
||||
int xxx_flags_hi_bn; // locator for flags, count, indexes, calls bands
|
||||
int attrc; // ATTR_CONTEXT_CLASS, etc.
|
||||
uint32_t flag_limit; // 32 or 63, depending on archive_options bit
|
||||
uint64_t predef; // mask of built-in definitions
|
||||
uint64_t redef; // mask of local flag definitions or redefinitions
|
||||
ptrlist layouts; // local (compressor-defined) defs, in index order
|
||||
int flag_count[X_ATTR_LIMIT_FLAGS_HI];
|
||||
intlist overflow_count;
|
||||
ptrlist strip_names; // what attribute names are being stripped?
|
||||
ptrlist band_stack; // Temp., used during layout parsing.
|
||||
ptrlist calls_to_link; // (ditto)
|
||||
int bands_made; // (ditto)
|
||||
|
||||
void free()
|
||||
{
|
||||
layouts.free();
|
||||
overflow_count.free();
|
||||
strip_names.free();
|
||||
band_stack.free();
|
||||
calls_to_link.free();
|
||||
}
|
||||
|
||||
// Locate the five fixed bands.
|
||||
band &xxx_flags_hi();
|
||||
band &xxx_flags_lo();
|
||||
band &xxx_attr_count();
|
||||
band &xxx_attr_indexes();
|
||||
band &xxx_attr_calls();
|
||||
band &fixed_band(int e_class_xxx);
|
||||
|
||||
// Register a new layout, and make bands for it.
|
||||
layout_definition *defineLayout(int idx, const char *name, const char *layout);
|
||||
layout_definition *defineLayout(int idx, entry *nameEntry, const char *layout);
|
||||
band **buildBands(layout_definition *lo);
|
||||
|
||||
// Parse a layout string or part of one, recursively if necessary.
|
||||
const char *parseLayout(const char *lp, band **&res, int curCble);
|
||||
const char *parseNumeral(const char *lp, int &res);
|
||||
const char *parseIntLayout(const char *lp, band *&res, byte le_kind,
|
||||
bool can_be_signed = false);
|
||||
band **popBody(int band_stack_base); // pops a body off band_stack
|
||||
|
||||
// Read data into the bands of the idx-th layout.
|
||||
void readBandData(int idx); // parse layout, make bands, read data
|
||||
void readBandData(band **body, uint32_t count); // recursive helper
|
||||
|
||||
layout_definition *getLayout(uint32_t idx)
|
||||
{
|
||||
if (idx >= (uint32_t)layouts.length())
|
||||
return nullptr;
|
||||
return (layout_definition *)layouts.get(idx);
|
||||
}
|
||||
|
||||
void setHaveLongFlags(bool z)
|
||||
{
|
||||
assert(flag_limit == 0); // not set up yet
|
||||
flag_limit = (z ? X_ATTR_LIMIT_FLAGS_HI : X_ATTR_LIMIT_NO_FLAGS_HI);
|
||||
}
|
||||
bool haveLongFlags()
|
||||
{
|
||||
assert(flag_limit == X_ATTR_LIMIT_NO_FLAGS_HI ||
|
||||
flag_limit == X_ATTR_LIMIT_FLAGS_HI);
|
||||
return flag_limit == X_ATTR_LIMIT_FLAGS_HI;
|
||||
}
|
||||
|
||||
// Return flag_count if idx is predef and not redef, else zero.
|
||||
int predefCount(uint32_t idx);
|
||||
|
||||
bool isRedefined(uint32_t idx)
|
||||
{
|
||||
if (idx >= flag_limit)
|
||||
return false;
|
||||
return (bool)((redef >> idx) & 1);
|
||||
}
|
||||
bool isPredefined(uint32_t idx)
|
||||
{
|
||||
if (idx >= flag_limit)
|
||||
return false;
|
||||
return (bool)(((predef & ~redef) >> idx) & 1);
|
||||
}
|
||||
uint64_t flagIndexMask()
|
||||
{
|
||||
return (predef | redef);
|
||||
}
|
||||
bool isIndex(uint32_t idx)
|
||||
{
|
||||
assert(flag_limit != 0); // must be set up already
|
||||
if (idx < flag_limit)
|
||||
return (bool)(((predef | redef) >> idx) & 1);
|
||||
else
|
||||
return (idx - flag_limit < (uint32_t)overflow_count.length());
|
||||
}
|
||||
int &getCount(uint32_t idx)
|
||||
{
|
||||
assert(isIndex(idx));
|
||||
if (idx < flag_limit)
|
||||
return flag_count[idx];
|
||||
else
|
||||
return overflow_count.get(idx - flag_limit);
|
||||
}
|
||||
};
|
||||
|
||||
attr_definitions attr_defs[ATTR_CONTEXT_LIMIT];
|
||||
|
||||
// Initialization
|
||||
void init(read_input_fn_t input_fn = nullptr);
|
||||
// Resets to a known sane state
|
||||
void reset();
|
||||
// Deallocates all storage.
|
||||
void free();
|
||||
// Deallocates temporary storage (volatile after next client call).
|
||||
void free_temps()
|
||||
{
|
||||
tsmallbuf.init();
|
||||
tmallocs.freeAll();
|
||||
}
|
||||
|
||||
// Option management methods
|
||||
bool set_option(const char *option, const char *value);
|
||||
const char *get_option(const char *option);
|
||||
|
||||
// Fetching input.
|
||||
bool ensure_input(int64_t more);
|
||||
byte *input_scan()
|
||||
{
|
||||
return rp;
|
||||
}
|
||||
size_t input_remaining()
|
||||
{
|
||||
return rplimit - rp;
|
||||
}
|
||||
size_t input_consumed()
|
||||
{
|
||||
return rp - input.base();
|
||||
}
|
||||
|
||||
// Entry points to the unpack engine
|
||||
static int run(int argc, char **argv); // Unix-style entry point.
|
||||
void check_options();
|
||||
void start(void *packptr = nullptr, size_t len = 0);
|
||||
void write_file_to_jar(file *f);
|
||||
void finish();
|
||||
|
||||
// Public post unpack methods
|
||||
int get_files_remaining()
|
||||
{
|
||||
return files_remaining;
|
||||
}
|
||||
int get_segments_remaining()
|
||||
{
|
||||
return archive_next_count;
|
||||
}
|
||||
file *get_next_file(); // returns nullptr on last file
|
||||
|
||||
// General purpose methods
|
||||
void *alloc(size_t size)
|
||||
{
|
||||
return alloc_heap(size, true);
|
||||
}
|
||||
void *temp_alloc(size_t size)
|
||||
{
|
||||
return alloc_heap(size, true, true);
|
||||
}
|
||||
void *alloc_heap(size_t size, bool smallOK = false, bool temp = false);
|
||||
void saveTo(bytes &b, const char *str)
|
||||
{
|
||||
saveTo(b, (byte *)str, strlen(str));
|
||||
}
|
||||
void saveTo(bytes &b, bytes &data)
|
||||
{
|
||||
saveTo(b, data.ptr, data.len);
|
||||
}
|
||||
void saveTo(bytes &b, byte *ptr, size_t len); //{ b.ptr = U_NEW...}
|
||||
const char *saveStr(const char *str)
|
||||
{
|
||||
bytes buf;
|
||||
saveTo(buf, str);
|
||||
return buf.strval();
|
||||
}
|
||||
const char *saveIntStr(int num)
|
||||
{
|
||||
char buf[30];
|
||||
sprintf(buf, "%d", num);
|
||||
return saveStr(buf);
|
||||
}
|
||||
static unpacker *current(); // find current instance
|
||||
|
||||
// Output management
|
||||
void set_output(fillbytes *which)
|
||||
{
|
||||
assert(wp == nullptr);
|
||||
which->ensureSize(1 << 12); // covers the average classfile
|
||||
wpbase = which->base();
|
||||
wp = which->limit();
|
||||
wplimit = which->end();
|
||||
}
|
||||
fillbytes *close_output(fillbytes *which = nullptr); // inverse of set_output
|
||||
|
||||
// These take an implicit parameter of wp/wplimit, and resize as necessary:
|
||||
byte *put_space(size_t len); // allocates space at wp, returns pointer
|
||||
size_t put_empty(size_t s)
|
||||
{
|
||||
byte *p = put_space(s);
|
||||
return p - wpbase;
|
||||
}
|
||||
void ensure_put_space(size_t len);
|
||||
void put_bytes(bytes &b)
|
||||
{
|
||||
b.writeTo(put_space(b.len));
|
||||
}
|
||||
void putu1(int n)
|
||||
{
|
||||
putu1_at(put_space(1), n);
|
||||
}
|
||||
void putu1_fast(int n)
|
||||
{
|
||||
putu1_at(wp++, n);
|
||||
}
|
||||
void putu2(int n); // { putu2_at(put_space(2), n); }
|
||||
void putu4(int n); // { putu4_at(put_space(4), n); }
|
||||
void putu8(int64_t n); // { putu8_at(put_space(8), n); }
|
||||
void putref(entry *e); // { putu2_at(put_space(2), putref_index(e, 2)); }
|
||||
void putu1ref(entry *e); // { putu1_at(put_space(1), putref_index(e, 1)); }
|
||||
int putref_index(entry *e, int size); // size in [1..2]
|
||||
void put_label(int curIP, int size); // size in {2,4}
|
||||
void putlayout(band **body);
|
||||
void put_stackmap_type();
|
||||
|
||||
size_t wpoffset()
|
||||
{
|
||||
return (size_t)(wp - wpbase);
|
||||
} // (unvariant across overflow)
|
||||
byte *wp_at(size_t offset)
|
||||
{
|
||||
return wpbase + offset;
|
||||
}
|
||||
uint32_t to_bci(uint32_t bii);
|
||||
void get_code_header(int &max_stack, int &max_na_locals, int &handler_count, int &cflags);
|
||||
band *ref_band_for_self_op(int bc, bool &isAloadVar, int &origBCVar);
|
||||
band *ref_band_for_op(int bc);
|
||||
|
||||
// Definitions of standard classfile int formats:
|
||||
static void putu1_at(byte *wp, int n)
|
||||
{
|
||||
assert(n == (n & 0xFF));
|
||||
wp[0] = n;
|
||||
}
|
||||
static void putu2_at(byte *wp, int n);
|
||||
static void putu4_at(byte *wp, int n);
|
||||
static void putu8_at(byte *wp, int64_t n);
|
||||
|
||||
// Private stuff
|
||||
void reset_cur_classfile();
|
||||
void write_classfile_tail();
|
||||
void write_classfile_head();
|
||||
void write_code();
|
||||
void write_bc_ops();
|
||||
void write_members(int num, int attrc); // attrc=ATTR_CONTEXT_FIELD/METHOD
|
||||
int write_attrs(int attrc, uint64_t indexBits);
|
||||
|
||||
// The readers
|
||||
void read_bands();
|
||||
void read_file_header();
|
||||
void read_cp();
|
||||
void read_cp_counts(value_stream &hdr);
|
||||
void read_attr_defs();
|
||||
void read_ics();
|
||||
void read_attrs(int attrc, int obj_count);
|
||||
void read_classes();
|
||||
void read_code_headers();
|
||||
void read_bcs();
|
||||
void read_bc_ops();
|
||||
void read_files();
|
||||
void read_Utf8_values(entry *cpMap, int len);
|
||||
void read_single_words(band &cp_band, entry *cpMap, int len);
|
||||
void read_double_words(band &cp_bands, entry *cpMap, int len);
|
||||
void read_single_refs(band &cp_band, byte refTag, entry *cpMap, int len);
|
||||
void read_double_refs(band &cp_band, byte ref1Tag, byte ref2Tag, entry *cpMap, int len);
|
||||
void read_signature_values(entry *cpMap, int len);
|
||||
};
|
@ -1,162 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <time.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "constants.h"
|
||||
#include "utils.h"
|
||||
#include "defines.h"
|
||||
#include "bytes.h"
|
||||
#include "coding.h"
|
||||
#include "unpack200.h"
|
||||
#include "unpack.h"
|
||||
#include "zip.h"
|
||||
|
||||
// Callback for fetching data, Unix style.
|
||||
static int64_t read_input_via_stdio(unpacker *u, void *buf, int64_t minlen, int64_t maxlen)
|
||||
{
|
||||
assert(u->infileptr != nullptr);
|
||||
assert(minlen <= maxlen); // don't talk nonsense
|
||||
int64_t numread = 0;
|
||||
char *bufptr = (char *)buf;
|
||||
while (numread < minlen)
|
||||
{
|
||||
// read available input, up to buf.length or maxlen
|
||||
int readlen = (1 << 16);
|
||||
if (readlen > (maxlen - numread))
|
||||
readlen = (int)(maxlen - numread);
|
||||
int nr = 0;
|
||||
|
||||
nr = (int)fread(bufptr, 1, readlen, u->infileptr);
|
||||
if (nr <= 0)
|
||||
{
|
||||
if (errno != EINTR)
|
||||
break;
|
||||
nr = 0;
|
||||
}
|
||||
numread += nr;
|
||||
bufptr += nr;
|
||||
assert(numread <= maxlen);
|
||||
}
|
||||
return numread;
|
||||
}
|
||||
|
||||
enum
|
||||
{
|
||||
EOF_MAGIC = 0,
|
||||
BAD_MAGIC = -1
|
||||
};
|
||||
|
||||
static int read_magic(unpacker *u, char peek[], int peeklen)
|
||||
{
|
||||
assert(peeklen == 4); // magic numbers are always 4 bytes
|
||||
int64_t nr = (u->read_input_fn)(u, peek, peeklen, peeklen);
|
||||
if (nr != peeklen)
|
||||
{
|
||||
return (nr == 0) ? EOF_MAGIC : BAD_MAGIC;
|
||||
}
|
||||
int magic = 0;
|
||||
for (int i = 0; i < peeklen; i++)
|
||||
{
|
||||
magic <<= 8;
|
||||
magic += peek[i] & 0xFF;
|
||||
}
|
||||
return magic;
|
||||
}
|
||||
|
||||
void unpack_200(FILE *input, FILE *output)
|
||||
{
|
||||
unpacker u;
|
||||
u.init(read_input_via_stdio);
|
||||
|
||||
// initialize jar output
|
||||
// the output takes ownership of the file handle
|
||||
jar jarout;
|
||||
jarout.init(&u);
|
||||
jarout.jarfp = output;
|
||||
|
||||
// the input doesn't
|
||||
u.infileptr = input;
|
||||
|
||||
// read the magic!
|
||||
char peek[4];
|
||||
int magic;
|
||||
magic = read_magic(&u, peek, (int)sizeof(peek));
|
||||
|
||||
// if it is a gzip encoded file, we need an extra gzip input filter
|
||||
if ((magic & GZIP_MAGIC_MASK) == GZIP_MAGIC)
|
||||
{
|
||||
gunzip *gzin = NEW(gunzip, 1);
|
||||
gzin->init(&u);
|
||||
// FIXME: why the side effects? WHY?
|
||||
u.gzin->start(magic);
|
||||
u.start();
|
||||
}
|
||||
else
|
||||
{
|
||||
// otherwise, feed the bytes to the unpacker directly
|
||||
u.start(peek, sizeof(peek));
|
||||
}
|
||||
|
||||
// Note: The checks to u.aborting() are necessary to gracefully
|
||||
// terminate processing when the first segment throws an error.
|
||||
for (;;)
|
||||
{
|
||||
// Each trip through this loop unpacks one segment
|
||||
// and then resets the unpacker.
|
||||
for (unpacker::file *filep; (filep = u.get_next_file()) != nullptr;)
|
||||
{
|
||||
u.write_file_to_jar(filep);
|
||||
}
|
||||
|
||||
// Peek ahead for more data.
|
||||
magic = read_magic(&u, peek, (int)sizeof(peek));
|
||||
if (magic != (int)JAVA_PACKAGE_MAGIC)
|
||||
{
|
||||
// we do not feel strongly about this kind of thing...
|
||||
/*
|
||||
if (magic != EOF_MAGIC)
|
||||
unpack_abort("garbage after end of pack archive");
|
||||
*/
|
||||
break; // all done
|
||||
}
|
||||
|
||||
// Release all storage from parsing the old segment.
|
||||
u.reset();
|
||||
// Restart, beginning with the peek-ahead.
|
||||
u.start(peek, sizeof(peek));
|
||||
}
|
||||
u.finish();
|
||||
u.free(); // tidy up malloc blocks
|
||||
fclose(input);
|
||||
}
|
@ -1,71 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <direct.h>
|
||||
#include <io.h>
|
||||
#include <process.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "constants.h"
|
||||
#include "defines.h"
|
||||
#include "bytes.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include "unpack.h"
|
||||
|
||||
void *must_malloc(size_t size)
|
||||
{
|
||||
size_t msize = size;
|
||||
void *ptr = (msize > PSIZE_MAX) ? nullptr : malloc(msize);
|
||||
if (ptr != nullptr)
|
||||
{
|
||||
memset(ptr, 0, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error(ERROR_ENOMEM);
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void unpack_abort(const char *msg)
|
||||
{
|
||||
if (msg == nullptr)
|
||||
msg = "corrupt pack file or internal error";
|
||||
throw std::runtime_error(msg);
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
// Definitions of our util functions
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
void *must_malloc(size_t size);
|
||||
|
||||
// overflow management
|
||||
#define OVERFLOW ((size_t) - 1)
|
||||
#define PSIZE_MAX (OVERFLOW / 2) /* normal size limit */
|
||||
|
||||
inline size_t scale_size(size_t size, size_t scale)
|
||||
{
|
||||
return (size > PSIZE_MAX / scale) ? OVERFLOW : size * scale;
|
||||
}
|
||||
|
||||
inline size_t add_size(size_t size1, size_t size2)
|
||||
{
|
||||
return ((size1 | size2 | (size1 + size2)) > PSIZE_MAX) ? OVERFLOW : size1 + size2;
|
||||
}
|
||||
|
||||
inline size_t add_size(size_t size1, size_t size2, int size3)
|
||||
{
|
||||
return add_size(add_size(size1, size2), size3);
|
||||
}
|
||||
|
||||
struct unpacker;
|
||||
/// This throws an exception!
|
||||
extern void unpack_abort(const char *msg = nullptr);
|
@ -1,589 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Note: Lifted from uncrunch.c from jdk sources
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#include <strings.h>
|
||||
#endif
|
||||
|
||||
#include "defines.h"
|
||||
#include "bytes.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include "constants.h"
|
||||
#include "unpack.h"
|
||||
|
||||
#include "zip.h"
|
||||
|
||||
#include "zlib.h"
|
||||
|
||||
inline uint32_t jar::get_crc32(uint32_t c, uchar *ptr, uint32_t len)
|
||||
{
|
||||
return crc32(c, ptr, len);
|
||||
}
|
||||
|
||||
// FIXME: this is bullshit. Do real endianness detection.
|
||||
#ifdef sparc
|
||||
#define SWAP_BYTES(a) ((((a) << 8) & 0xff00) | 0x00ff) & (((a) >> 8) | 0xff00)
|
||||
#else
|
||||
#define SWAP_BYTES(a) (a)
|
||||
#endif
|
||||
|
||||
#define GET_INT_LO(a) SWAP_BYTES(a & 0xFFFF)
|
||||
|
||||
#define GET_INT_HI(a) SWAP_BYTES((a >> 16) & 0xFFFF);
|
||||
|
||||
void jar::init(unpacker *u_)
|
||||
{
|
||||
BYTES_OF(*this).clear();
|
||||
u = u_;
|
||||
u->jarout = this;
|
||||
}
|
||||
|
||||
// Write data to the ZIP output stream.
|
||||
void jar::write_data(void *buff, int len)
|
||||
{
|
||||
while (len > 0)
|
||||
{
|
||||
int rc = (int)fwrite(buff, 1, len, jarfp);
|
||||
if (rc <= 0)
|
||||
{
|
||||
fprintf(stderr, "Error: write on output file failed err=%d\n", errno);
|
||||
exit(1); // Called only from the native standalone unpacker
|
||||
}
|
||||
output_file_offset += rc;
|
||||
buff = ((char *)buff) + rc;
|
||||
len -= rc;
|
||||
}
|
||||
}
|
||||
|
||||
void jar::add_to_jar_directory(const char *fname, bool store, int modtime, int len, int clen,
|
||||
uint32_t crc)
|
||||
{
|
||||
uint32_t fname_length = (uint32_t)strlen(fname);
|
||||
ushort header[23];
|
||||
if (modtime == 0)
|
||||
modtime = default_modtime;
|
||||
uint32_t dostime = get_dostime(modtime);
|
||||
|
||||
header[0] = (ushort)SWAP_BYTES(0x4B50);
|
||||
header[1] = (ushort)SWAP_BYTES(0x0201);
|
||||
header[2] = (ushort)SWAP_BYTES(0xA);
|
||||
|
||||
// required version
|
||||
header[3] = (ushort)SWAP_BYTES(0xA);
|
||||
|
||||
// flags 02 = maximum sub-compression flag
|
||||
header[4] = (store) ? 0x0 : SWAP_BYTES(0x2);
|
||||
|
||||
// Compression method 8=deflate.
|
||||
header[5] = (store) ? 0x0 : SWAP_BYTES(0x08);
|
||||
|
||||
// Last modified date and time.
|
||||
header[6] = (ushort)GET_INT_LO(dostime);
|
||||
header[7] = (ushort)GET_INT_HI(dostime);
|
||||
|
||||
// CRC
|
||||
header[8] = (ushort)GET_INT_LO(crc);
|
||||
header[9] = (ushort)GET_INT_HI(crc);
|
||||
|
||||
// Compressed length:
|
||||
header[10] = (ushort)GET_INT_LO(clen);
|
||||
header[11] = (ushort)GET_INT_HI(clen);
|
||||
|
||||
// Uncompressed length.
|
||||
header[12] = (ushort)GET_INT_LO(len);
|
||||
header[13] = (ushort)GET_INT_HI(len);
|
||||
|
||||
// Filename length
|
||||
header[14] = (ushort)SWAP_BYTES(fname_length);
|
||||
// So called "extra field" length.
|
||||
header[15] = 0;
|
||||
// So called "comment" length.
|
||||
header[16] = 0;
|
||||
// Disk number start
|
||||
header[17] = 0;
|
||||
// File flags => binary
|
||||
header[18] = 0;
|
||||
// More file flags
|
||||
header[19] = 0;
|
||||
header[20] = 0;
|
||||
// Offset within ZIP file.
|
||||
header[21] = (ushort)GET_INT_LO(output_file_offset);
|
||||
header[22] = (ushort)GET_INT_HI(output_file_offset);
|
||||
|
||||
// Copy the whole thing into the central directory.
|
||||
central_directory.append(header, sizeof(header));
|
||||
|
||||
// Copy the fname to the header.
|
||||
central_directory.append(fname, fname_length);
|
||||
|
||||
central_directory_count++;
|
||||
}
|
||||
|
||||
void jar::write_jar_header(const char *fname, bool store, int modtime, int len, int clen,
|
||||
uint32_t crc)
|
||||
{
|
||||
uint32_t fname_length = (uint32_t)strlen(fname);
|
||||
ushort header[15];
|
||||
if (modtime == 0)
|
||||
modtime = default_modtime;
|
||||
uint32_t dostime = get_dostime(modtime);
|
||||
|
||||
// ZIP LOC magic.
|
||||
header[0] = (ushort)SWAP_BYTES(0x4B50);
|
||||
header[1] = (ushort)SWAP_BYTES(0x0403);
|
||||
|
||||
// Version
|
||||
header[2] = (ushort)SWAP_BYTES(0xA);
|
||||
|
||||
// flags 02 = maximum sub-compression flag
|
||||
header[3] = (store) ? 0x0 : SWAP_BYTES(0x2);
|
||||
|
||||
// Compression method = deflate
|
||||
header[4] = (store) ? 0x0 : SWAP_BYTES(0x08);
|
||||
|
||||
// Last modified date and time.
|
||||
header[5] = (ushort)GET_INT_LO(dostime);
|
||||
header[6] = (ushort)GET_INT_HI(dostime);
|
||||
|
||||
// CRC
|
||||
header[7] = (ushort)GET_INT_LO(crc);
|
||||
header[8] = (ushort)GET_INT_HI(crc);
|
||||
|
||||
// Compressed length:
|
||||
header[9] = (ushort)GET_INT_LO(clen);
|
||||
header[10] = (ushort)GET_INT_HI(clen);
|
||||
|
||||
// Uncompressed length.
|
||||
header[11] = (ushort)GET_INT_LO(len);
|
||||
header[12] = (ushort)GET_INT_HI(len);
|
||||
|
||||
// Filename length
|
||||
header[13] = (ushort)SWAP_BYTES(fname_length);
|
||||
// So called "extra field" length.
|
||||
header[14] = 0;
|
||||
|
||||
// Write the LOC header to the output file.
|
||||
write_data(header, (int)sizeof(header));
|
||||
|
||||
// Copy the fname to the header.
|
||||
write_data((char *)fname, (int)fname_length);
|
||||
}
|
||||
|
||||
void jar::write_central_directory()
|
||||
{
|
||||
bytes mc;
|
||||
mc.set("PACK200");
|
||||
|
||||
ushort header[11];
|
||||
|
||||
// Create the End of Central Directory structure.
|
||||
header[0] = (ushort)SWAP_BYTES(0x4B50);
|
||||
header[1] = (ushort)SWAP_BYTES(0x0605);
|
||||
// disk numbers
|
||||
header[2] = 0;
|
||||
header[3] = 0;
|
||||
// Number of entries in central directory.
|
||||
header[4] = (ushort)SWAP_BYTES(central_directory_count);
|
||||
header[5] = (ushort)SWAP_BYTES(central_directory_count);
|
||||
// Size of the central directory}
|
||||
header[6] = (ushort)GET_INT_LO((int)central_directory.size());
|
||||
header[7] = (ushort)GET_INT_HI((int)central_directory.size());
|
||||
// Offset of central directory within disk.
|
||||
header[8] = (ushort)GET_INT_LO(output_file_offset);
|
||||
header[9] = (ushort)GET_INT_HI(output_file_offset);
|
||||
// zipfile comment length;
|
||||
header[10] = (ushort)SWAP_BYTES((int)mc.len);
|
||||
|
||||
// Write the central directory.
|
||||
write_data(central_directory.b);
|
||||
|
||||
// Write the End of Central Directory structure.
|
||||
write_data(header, (int)sizeof(header));
|
||||
|
||||
// Write the comment.
|
||||
write_data(mc);
|
||||
}
|
||||
|
||||
// Public API
|
||||
|
||||
// Open a Jar file and initialize.
|
||||
void jar::openJarFile(const char *fname)
|
||||
{
|
||||
if (!jarfp)
|
||||
{
|
||||
jarfp = fopen(fname, "wb");
|
||||
if (!jarfp)
|
||||
{
|
||||
fprintf(stderr, "Error: Could not open jar file: %s\n", fname);
|
||||
exit(3); // Called only from the native standalone unpacker
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add a ZIP entry and copy the file data
|
||||
void jar::addJarEntry(const char *fname, bool deflate_hint, int modtime, bytes &head,
|
||||
bytes &tail)
|
||||
{
|
||||
int len = (int)(head.len + tail.len);
|
||||
int clen = 0;
|
||||
|
||||
uint32_t crc = get_crc32(0, Z_NULL, 0);
|
||||
if (head.len != 0)
|
||||
crc = get_crc32(crc, (uchar *)head.ptr, (uint32_t)head.len);
|
||||
if (tail.len != 0)
|
||||
crc = get_crc32(crc, (uchar *)tail.ptr, (uint32_t)tail.len);
|
||||
|
||||
bool deflate = (deflate_hint && len > 0);
|
||||
|
||||
if (deflate)
|
||||
{
|
||||
if (deflate_bytes(head, tail) == false)
|
||||
{
|
||||
deflate = false;
|
||||
}
|
||||
}
|
||||
clen = (int)((deflate) ? deflated.size() : len);
|
||||
add_to_jar_directory(fname, !deflate, modtime, len, clen, crc);
|
||||
write_jar_header(fname, !deflate, modtime, len, clen, crc);
|
||||
|
||||
if (deflate)
|
||||
{
|
||||
write_data(deflated.b);
|
||||
}
|
||||
else
|
||||
{
|
||||
write_data(head);
|
||||
write_data(tail);
|
||||
}
|
||||
}
|
||||
|
||||
// Add a ZIP entry for a directory name no data
|
||||
void jar::addDirectoryToJarFile(const char *dir_name)
|
||||
{
|
||||
bool store = true;
|
||||
add_to_jar_directory((const char *)dir_name, store, default_modtime, 0, 0, 0);
|
||||
write_jar_header((const char *)dir_name, store, default_modtime, 0, 0, 0);
|
||||
}
|
||||
|
||||
// Write out the central directory and close the jar file.
|
||||
void jar::closeJarFile(bool central)
|
||||
{
|
||||
if (jarfp)
|
||||
{
|
||||
fflush(jarfp);
|
||||
if (central)
|
||||
write_central_directory();
|
||||
fflush(jarfp);
|
||||
fclose(jarfp);
|
||||
}
|
||||
reset();
|
||||
}
|
||||
|
||||
/* Convert the date y/n/d and time h:m:s to a four byte DOS date and
|
||||
* time (date in high two bytes, time in low two bytes allowing magnitude
|
||||
* comparison).
|
||||
*/
|
||||
inline uint32_t jar::dostime(int y, int n, int d, int h, int m, int s)
|
||||
{
|
||||
return y < 1980 ? dostime(1980, 1, 1, 0, 0, 0)
|
||||
: (((uint32_t)y - 1980) << 25) | ((uint32_t)n << 21) | ((uint32_t)d << 16) |
|
||||
((uint32_t)h << 11) | ((uint32_t)m << 5) | ((uint32_t)s >> 1);
|
||||
}
|
||||
/*
|
||||
#ifdef _REENTRANT // solaris
|
||||
extern "C" struct tm *gmtime_r(const time_t *, struct tm *);
|
||||
#else
|
||||
#define gmtime_r(t, s) gmtime(t)
|
||||
#endif
|
||||
*/
|
||||
/*
|
||||
* Return the Unix time in DOS format
|
||||
*/
|
||||
uint32_t jar::get_dostime(int modtime)
|
||||
{
|
||||
// see defines.h
|
||||
if (modtime != 0 && modtime == modtime_cache)
|
||||
return dostime_cache;
|
||||
if (modtime != 0 && default_modtime == 0)
|
||||
default_modtime = modtime; // catch a reasonable default
|
||||
time_t t = modtime;
|
||||
struct tm sbuf;
|
||||
(void)memset((void *)&sbuf, 0, sizeof(sbuf));
|
||||
struct tm *s = gmtime_r(&t, &sbuf);
|
||||
modtime_cache = modtime;
|
||||
dostime_cache =
|
||||
dostime(s->tm_year + 1900, s->tm_mon + 1, s->tm_mday, s->tm_hour, s->tm_min, s->tm_sec);
|
||||
// printf("modtime %d => %d\n", modtime_cache, dostime_cache);
|
||||
return dostime_cache;
|
||||
}
|
||||
|
||||
/* Returns true on success, and will set the clen to the compressed
|
||||
length, the caller should verify if true and clen less than the
|
||||
input data
|
||||
*/
|
||||
bool jar::deflate_bytes(bytes &head, bytes &tail)
|
||||
{
|
||||
int len = (int)(head.len + tail.len);
|
||||
|
||||
z_stream zs;
|
||||
BYTES_OF(zs).clear();
|
||||
|
||||
// NOTE: the window size should always be -MAX_WBITS normally -15.
|
||||
// unzip/zipup.c and java/Deflater.c
|
||||
|
||||
int error =
|
||||
deflateInit2(&zs, Z_BEST_COMPRESSION, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY);
|
||||
if (error != Z_OK)
|
||||
{
|
||||
/*
|
||||
switch (error)
|
||||
{
|
||||
case Z_MEM_ERROR:
|
||||
PRINTCR((2, "Error: deflate error : Out of memory \n"));
|
||||
break;
|
||||
case Z_STREAM_ERROR:
|
||||
PRINTCR((2, "Error: deflate error : Invalid compression level \n"));
|
||||
break;
|
||||
case Z_VERSION_ERROR:
|
||||
PRINTCR((2, "Error: deflate error : Invalid version\n"));
|
||||
break;
|
||||
default:
|
||||
PRINTCR((2, "Error: Internal deflate error error = %d\n", error));
|
||||
}
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
||||
deflated.empty();
|
||||
zs.next_out = (uchar *)deflated.grow(len + (len / 2));
|
||||
zs.avail_out = (int)deflated.size();
|
||||
|
||||
zs.next_in = (uchar *)head.ptr;
|
||||
zs.avail_in = (int)head.len;
|
||||
|
||||
bytes *first = &head;
|
||||
bytes *last = &tail;
|
||||
if (last->len == 0)
|
||||
{
|
||||
first = nullptr;
|
||||
last = &head;
|
||||
}
|
||||
else if (first->len == 0)
|
||||
{
|
||||
first = nullptr;
|
||||
}
|
||||
|
||||
if (first != nullptr && error == Z_OK)
|
||||
{
|
||||
zs.next_in = (uchar *)first->ptr;
|
||||
zs.avail_in = (int)first->len;
|
||||
error = deflate(&zs, Z_NO_FLUSH);
|
||||
}
|
||||
if (error == Z_OK)
|
||||
{
|
||||
zs.next_in = (uchar *)last->ptr;
|
||||
zs.avail_in = (int)last->len;
|
||||
error = deflate(&zs, Z_FINISH);
|
||||
}
|
||||
if (error == Z_STREAM_END)
|
||||
{
|
||||
if (len > (int)zs.total_out)
|
||||
{
|
||||
deflated.b.len = zs.total_out;
|
||||
deflateEnd(&zs);
|
||||
return true;
|
||||
}
|
||||
deflateEnd(&zs);
|
||||
return false;
|
||||
}
|
||||
|
||||
deflateEnd(&zs);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Callback for fetching data from a GZIP input stream
|
||||
static int64_t read_input_via_gzip(unpacker *u, void *buf, int64_t minlen, int64_t maxlen)
|
||||
{
|
||||
assert(minlen <= maxlen); // don't talk nonsense
|
||||
int64_t numread = 0;
|
||||
char *bufptr = (char *)buf;
|
||||
char *inbuf = u->gzin->inbuf;
|
||||
size_t inbuflen = sizeof(u->gzin->inbuf);
|
||||
read_input_fn_t read_gzin_fn = u->gzin->read_input_fn;
|
||||
z_stream &zs = *(z_stream *)u->gzin->zstream;
|
||||
while (numread < minlen)
|
||||
{
|
||||
int readlen = (1 << 16); // pretty arbitrary
|
||||
if (readlen > (maxlen - numread))
|
||||
readlen = (int)(maxlen - numread);
|
||||
zs.next_out = (uchar *)bufptr;
|
||||
zs.avail_out = readlen;
|
||||
if (zs.avail_in == 0)
|
||||
{
|
||||
zs.avail_in = (int)read_gzin_fn(u, inbuf, 1, inbuflen);
|
||||
zs.next_in = (uchar *)inbuf;
|
||||
}
|
||||
int error = inflate(&zs, Z_NO_FLUSH);
|
||||
if (error != Z_OK && error != Z_STREAM_END)
|
||||
{
|
||||
unpack_abort("error inflating input");
|
||||
break;
|
||||
}
|
||||
int nr = readlen - zs.avail_out;
|
||||
numread += nr;
|
||||
bufptr += nr;
|
||||
assert(numread <= maxlen);
|
||||
if (error == Z_STREAM_END)
|
||||
{
|
||||
enum
|
||||
{
|
||||
TRAILER_LEN = 8
|
||||
};
|
||||
// skip 8-byte trailer
|
||||
if (zs.avail_in >= TRAILER_LEN)
|
||||
{
|
||||
zs.avail_in -= TRAILER_LEN;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Bug: 5023768,we read past the TRAILER_LEN to see if there is
|
||||
// any extraneous data, as we dont support concatenated .gz
|
||||
// files just yet.
|
||||
int extra = (int)read_gzin_fn(u, inbuf, 1, inbuflen);
|
||||
zs.avail_in += extra - TRAILER_LEN;
|
||||
}
|
||||
// %%% should check final CRC and length here
|
||||
// %%% should check for concatenated *.gz files here
|
||||
if (zs.avail_in > 0)
|
||||
unpack_abort("garbage after end of deflated input stream");
|
||||
// pop this filter off:
|
||||
u->gzin->free();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// fprintf(u->errstrm, "readInputFn(%d,%d) => %d (gunzip)\n",
|
||||
// (int)minlen, (int)maxlen, (int)numread);
|
||||
return numread;
|
||||
}
|
||||
|
||||
void gunzip::init(unpacker *u_)
|
||||
{
|
||||
BYTES_OF(*this).clear();
|
||||
u = u_;
|
||||
assert(u->gzin == nullptr); // once only, please
|
||||
read_input_fn = u->read_input_fn;
|
||||
zstream = NEW(z_stream, 1);
|
||||
u->gzin = this;
|
||||
u->read_input_fn = read_input_via_gzip;
|
||||
}
|
||||
|
||||
void gunzip::start(int magic)
|
||||
{
|
||||
assert((magic & GZIP_MAGIC_MASK) == GZIP_MAGIC);
|
||||
int gz_flg = (magic & 0xFF); // keep "flg", discard other 3 bytes
|
||||
enum
|
||||
{
|
||||
FHCRC = (1 << 1),
|
||||
FEXTRA = (1 << 2),
|
||||
FNAME = (1 << 3),
|
||||
FCOMMENT = (1 << 4)
|
||||
};
|
||||
char gz_mtime[4];
|
||||
char gz_xfl[1];
|
||||
char gz_os[1];
|
||||
char gz_extra_len[2];
|
||||
char gz_hcrc[2];
|
||||
char gz_ignore;
|
||||
// do not save extra, name, comment
|
||||
read_fixed_field(gz_mtime, sizeof(gz_mtime));
|
||||
read_fixed_field(gz_xfl, sizeof(gz_xfl));
|
||||
read_fixed_field(gz_os, sizeof(gz_os));
|
||||
if (gz_flg & FEXTRA)
|
||||
{
|
||||
read_fixed_field(gz_extra_len, sizeof(gz_extra_len));
|
||||
int extra_len = gz_extra_len[0] & 0xFF;
|
||||
extra_len += (gz_extra_len[1] & 0xFF) << 8;
|
||||
for (; extra_len > 0; extra_len--)
|
||||
{
|
||||
read_fixed_field(&gz_ignore, 1);
|
||||
}
|
||||
}
|
||||
int null_terms = 0;
|
||||
if (gz_flg & FNAME)
|
||||
null_terms++;
|
||||
if (gz_flg & FCOMMENT)
|
||||
null_terms++;
|
||||
for (; null_terms; null_terms--)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
gz_ignore = 0;
|
||||
read_fixed_field(&gz_ignore, 1);
|
||||
if (gz_ignore == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (gz_flg & FHCRC)
|
||||
read_fixed_field(gz_hcrc, sizeof(gz_hcrc));
|
||||
|
||||
// now the input stream is ready to read into the inflater
|
||||
int error = inflateInit2((z_stream *)zstream, -MAX_WBITS);
|
||||
if (error != Z_OK)
|
||||
{
|
||||
unpack_abort("cannot create input");
|
||||
}
|
||||
}
|
||||
|
||||
void gunzip::free()
|
||||
{
|
||||
assert(u->gzin == this);
|
||||
u->gzin = nullptr;
|
||||
u->read_input_fn = this->read_input_fn;
|
||||
inflateEnd((z_stream *)zstream);
|
||||
::free(zstream);
|
||||
zstream = nullptr;
|
||||
::free(this);
|
||||
}
|
||||
|
||||
void gunzip::read_fixed_field(char *buf, size_t buflen)
|
||||
{
|
||||
int64_t nr = read_input_fn(u, buf, buflen, buflen);
|
||||
if ((size_t)nr != buflen)
|
||||
unpack_abort("short stream header");
|
||||
}
|
@ -1,112 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
typedef unsigned short ushort;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef unsigned char uchar;
|
||||
|
||||
#include "unpack.h"
|
||||
|
||||
struct jar
|
||||
{
|
||||
// JAR file writer
|
||||
FILE *jarfp;
|
||||
int default_modtime;
|
||||
|
||||
// Used by unix2dostime:
|
||||
int modtime_cache;
|
||||
uint32_t dostime_cache;
|
||||
|
||||
// Private members
|
||||
fillbytes central_directory;
|
||||
ushort central_directory_count;
|
||||
uint32_t output_file_offset;
|
||||
fillbytes deflated; // temporary buffer
|
||||
|
||||
// pointer to outer unpacker, for error checks etc.
|
||||
unpacker *u;
|
||||
|
||||
// Public Methods
|
||||
void openJarFile(const char *fname);
|
||||
void addJarEntry(const char *fname, bool deflate_hint, int modtime, bytes &head,
|
||||
bytes &tail);
|
||||
void addDirectoryToJarFile(const char *dir_name);
|
||||
void closeJarFile(bool central);
|
||||
|
||||
void init(unpacker *u_);
|
||||
|
||||
void free()
|
||||
{
|
||||
central_directory.free();
|
||||
deflated.free();
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
free();
|
||||
init(u);
|
||||
}
|
||||
|
||||
// Private Methods
|
||||
void write_data(void *ptr, int len);
|
||||
void write_data(bytes &b)
|
||||
{
|
||||
write_data(b.ptr, (int)b.len);
|
||||
}
|
||||
void add_to_jar_directory(const char *fname, bool store, int modtime, int len, int clen,
|
||||
uint32_t crc);
|
||||
void write_jar_header(const char *fname, bool store, int modtime, int len, int clen,
|
||||
unsigned int crc);
|
||||
void write_central_directory();
|
||||
uint32_t dostime(int y, int n, int d, int h, int m, int s);
|
||||
uint32_t get_dostime(int modtime);
|
||||
|
||||
// The definitions of these depend on the NO_ZLIB option:
|
||||
bool deflate_bytes(bytes &head, bytes &tail);
|
||||
static uint32_t get_crc32(uint32_t c, unsigned char *ptr, uint32_t len);
|
||||
};
|
||||
|
||||
struct gunzip
|
||||
{
|
||||
// optional gzip input stream control block
|
||||
|
||||
// pointer to outer unpacker, for error checks etc.
|
||||
unpacker *u;
|
||||
|
||||
read_input_fn_t read_input_fn; // underlying \bchar\b stream
|
||||
void *zstream; // inflater state
|
||||
char inbuf[1 << 14]; // input buffer
|
||||
|
||||
void init(unpacker *u_); // pushes new value on u->read_input_fn
|
||||
|
||||
void free();
|
||||
|
||||
void start(int magic);
|
||||
|
||||
// private stuff
|
||||
void read_fixed_field(char *buf, size_t buflen);
|
||||
};
|
Loading…
Reference in New Issue
Block a user