Merge "Remove ijar"
am: 1dcffadbc7
Change-Id: I55b0892905cf67655661f5a15ef3574e9e27db97
This commit is contained in:
commit
dee143988e
|
@ -556,7 +556,6 @@ ACP := $(prebuilt_build_tools_bin)/acp
|
||||||
CKATI := $(prebuilt_build_tools_bin)/ckati
|
CKATI := $(prebuilt_build_tools_bin)/ckati
|
||||||
DEPMOD := $(HOST_OUT_EXECUTABLES)/depmod
|
DEPMOD := $(HOST_OUT_EXECUTABLES)/depmod
|
||||||
FILESLIST := $(SOONG_HOST_OUT_EXECUTABLES)/fileslist
|
FILESLIST := $(SOONG_HOST_OUT_EXECUTABLES)/fileslist
|
||||||
IJAR := $(prebuilt_build_tools_bin)/ijar
|
|
||||||
MAKEPARALLEL := $(prebuilt_build_tools_bin)/makeparallel
|
MAKEPARALLEL := $(prebuilt_build_tools_bin)/makeparallel
|
||||||
SOONG_JAVAC_WRAPPER := $(SOONG_HOST_OUT_EXECUTABLES)/soong_javac_wrapper
|
SOONG_JAVAC_WRAPPER := $(SOONG_HOST_OUT_EXECUTABLES)/soong_javac_wrapper
|
||||||
SOONG_ZIP := $(SOONG_HOST_OUT_EXECUTABLES)/soong_zip
|
SOONG_ZIP := $(SOONG_HOST_OUT_EXECUTABLES)/soong_zip
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
// Copyright 2015 The Android Open Source Project
|
|
||||||
//
|
|
||||||
// The rest of files in this directory comes from
|
|
||||||
// https://github.com/bazelbuild/bazel/tree/master/third_party/ijar
|
|
||||||
|
|
||||||
cc_binary_host {
|
|
||||||
srcs: [
|
|
||||||
"classfile.cc",
|
|
||||||
"ijar.cc",
|
|
||||||
"zip.cc",
|
|
||||||
],
|
|
||||||
cflags: [
|
|
||||||
"-Wall",
|
|
||||||
"-Werror",
|
|
||||||
],
|
|
||||||
host_ldlibs: ["-lz"],
|
|
||||||
name: "ijar",
|
|
||||||
}
|
|
|
@ -1,203 +0,0 @@
|
||||||
|
|
||||||
Apache License
|
|
||||||
Version 2.0, January 2004
|
|
||||||
http://www.apache.org/licenses/
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
||||||
|
|
||||||
1. Definitions.
|
|
||||||
|
|
||||||
"License" shall mean the terms and conditions for use, reproduction,
|
|
||||||
and distribution as defined by Sections 1 through 9 of this document.
|
|
||||||
|
|
||||||
"Licensor" shall mean the copyright owner or entity authorized by
|
|
||||||
the copyright owner that is granting the License.
|
|
||||||
|
|
||||||
"Legal Entity" shall mean the union of the acting entity and all
|
|
||||||
other entities that control, are controlled by, or are under common
|
|
||||||
control with that entity. For the purposes of this definition,
|
|
||||||
"control" means (i) the power, direct or indirect, to cause the
|
|
||||||
direction or management of such entity, whether by contract or
|
|
||||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
||||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
||||||
|
|
||||||
"You" (or "Your") shall mean an individual or Legal Entity
|
|
||||||
exercising permissions granted by this License.
|
|
||||||
|
|
||||||
"Source" form shall mean the preferred form for making modifications,
|
|
||||||
including but not limited to software source code, documentation
|
|
||||||
source, and configuration files.
|
|
||||||
|
|
||||||
"Object" form shall mean any form resulting from mechanical
|
|
||||||
transformation or translation of a Source form, including but
|
|
||||||
not limited to compiled object code, generated documentation,
|
|
||||||
and conversions to other media types.
|
|
||||||
|
|
||||||
"Work" shall mean the work of authorship, whether in Source or
|
|
||||||
Object form, made available under the License, as indicated by a
|
|
||||||
copyright notice that is included in or attached to the work
|
|
||||||
(an example is provided in the Appendix below).
|
|
||||||
|
|
||||||
"Derivative Works" shall mean any work, whether in Source or Object
|
|
||||||
form, that is based on (or derived from) the Work and for which the
|
|
||||||
editorial revisions, annotations, elaborations, or other modifications
|
|
||||||
represent, as a whole, an original work of authorship. For the purposes
|
|
||||||
of this License, Derivative Works shall not include works that remain
|
|
||||||
separable from, or merely link (or bind by name) to the interfaces of,
|
|
||||||
the Work and Derivative Works thereof.
|
|
||||||
|
|
||||||
"Contribution" shall mean any work of authorship, including
|
|
||||||
the original version of the Work and any modifications or additions
|
|
||||||
to that Work or Derivative Works thereof, that is intentionally
|
|
||||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
||||||
or by an individual or Legal Entity authorized to submit on behalf of
|
|
||||||
the copyright owner. For the purposes of this definition, "submitted"
|
|
||||||
means any form of electronic, verbal, or written communication sent
|
|
||||||
to the Licensor or its representatives, including but not limited to
|
|
||||||
communication on electronic mailing lists, source code control systems,
|
|
||||||
and issue tracking systems that are managed by, or on behalf of, the
|
|
||||||
Licensor for the purpose of discussing and improving the Work, but
|
|
||||||
excluding communication that is conspicuously marked or otherwise
|
|
||||||
designated in writing by the copyright owner as "Not a Contribution."
|
|
||||||
|
|
||||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
||||||
on behalf of whom a Contribution has been received by Licensor and
|
|
||||||
subsequently incorporated within the Work.
|
|
||||||
|
|
||||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
copyright license to reproduce, prepare Derivative Works of,
|
|
||||||
publicly display, publicly perform, sublicense, and distribute the
|
|
||||||
Work and such Derivative Works in Source or Object form.
|
|
||||||
|
|
||||||
3. Grant of Patent License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
(except as stated in this section) patent license to make, have made,
|
|
||||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
||||||
where such license applies only to those patent claims licensable
|
|
||||||
by such Contributor that are necessarily infringed by their
|
|
||||||
Contribution(s) alone or by combination of their Contribution(s)
|
|
||||||
with the Work to which such Contribution(s) was submitted. If You
|
|
||||||
institute patent litigation against any entity (including a
|
|
||||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
||||||
or a Contribution incorporated within the Work constitutes direct
|
|
||||||
or contributory patent infringement, then any patent licenses
|
|
||||||
granted to You under this License for that Work shall terminate
|
|
||||||
as of the date such litigation is filed.
|
|
||||||
|
|
||||||
4. Redistribution. You may reproduce and distribute copies of the
|
|
||||||
Work or Derivative Works thereof in any medium, with or without
|
|
||||||
modifications, and in Source or Object form, provided that You
|
|
||||||
meet the following conditions:
|
|
||||||
|
|
||||||
(a) You must give any other recipients of the Work or
|
|
||||||
Derivative Works a copy of this License; and
|
|
||||||
|
|
||||||
(b) You must cause any modified files to carry prominent notices
|
|
||||||
stating that You changed the files; and
|
|
||||||
|
|
||||||
(c) You must retain, in the Source form of any Derivative Works
|
|
||||||
that You distribute, all copyright, patent, trademark, and
|
|
||||||
attribution notices from the Source form of the Work,
|
|
||||||
excluding those notices that do not pertain to any part of
|
|
||||||
the Derivative Works; and
|
|
||||||
|
|
||||||
(d) If the Work includes a "NOTICE" text file as part of its
|
|
||||||
distribution, then any Derivative Works that You distribute must
|
|
||||||
include a readable copy of the attribution notices contained
|
|
||||||
within such NOTICE file, excluding those notices that do not
|
|
||||||
pertain to any part of the Derivative Works, in at least one
|
|
||||||
of the following places: within a NOTICE text file distributed
|
|
||||||
as part of the Derivative Works; within the Source form or
|
|
||||||
documentation, if provided along with the Derivative Works; or,
|
|
||||||
within a display generated by the Derivative Works, if and
|
|
||||||
wherever such third-party notices normally appear. The contents
|
|
||||||
of the NOTICE file are for informational purposes only and
|
|
||||||
do not modify the License. You may add Your own attribution
|
|
||||||
notices within Derivative Works that You distribute, alongside
|
|
||||||
or as an addendum to the NOTICE text from the Work, provided
|
|
||||||
that such additional attribution notices cannot be construed
|
|
||||||
as modifying the License.
|
|
||||||
|
|
||||||
You may add Your own copyright statement to Your modifications and
|
|
||||||
may provide additional or different license terms and conditions
|
|
||||||
for use, reproduction, or distribution of Your modifications, or
|
|
||||||
for any such Derivative Works as a whole, provided Your use,
|
|
||||||
reproduction, and distribution of the Work otherwise complies with
|
|
||||||
the conditions stated in this License.
|
|
||||||
|
|
||||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
||||||
any Contribution intentionally submitted for inclusion in the Work
|
|
||||||
by You to the Licensor shall be under the terms and conditions of
|
|
||||||
this License, without any additional terms or conditions.
|
|
||||||
Notwithstanding the above, nothing herein shall supersede or modify
|
|
||||||
the terms of any separate license agreement you may have executed
|
|
||||||
with Licensor regarding such Contributions.
|
|
||||||
|
|
||||||
6. Trademarks. This License does not grant permission to use the trade
|
|
||||||
names, trademarks, service marks, or product names of the Licensor,
|
|
||||||
except as required for reasonable and customary use in describing the
|
|
||||||
origin of the Work and reproducing the content of the NOTICE file.
|
|
||||||
|
|
||||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
||||||
agreed to in writing, Licensor provides the Work (and each
|
|
||||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
implied, including, without limitation, any warranties or conditions
|
|
||||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
||||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
||||||
appropriateness of using or redistributing the Work and assume any
|
|
||||||
risks associated with Your exercise of permissions under this License.
|
|
||||||
|
|
||||||
8. Limitation of Liability. In no event and under no legal theory,
|
|
||||||
whether in tort (including negligence), contract, or otherwise,
|
|
||||||
unless required by applicable law (such as deliberate and grossly
|
|
||||||
negligent acts) or agreed to in writing, shall any Contributor be
|
|
||||||
liable to You for damages, including any direct, indirect, special,
|
|
||||||
incidental, or consequential damages of any character arising as a
|
|
||||||
result of this License or out of the use or inability to use the
|
|
||||||
Work (including but not limited to damages for loss of goodwill,
|
|
||||||
work stoppage, computer failure or malfunction, or any and all
|
|
||||||
other commercial damages or losses), even if such Contributor
|
|
||||||
has been advised of the possibility of such damages.
|
|
||||||
|
|
||||||
9. Accepting Warranty or Additional Liability. While redistributing
|
|
||||||
the Work or Derivative Works thereof, You may choose to offer,
|
|
||||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
||||||
or other liability obligations and/or rights consistent with this
|
|
||||||
License. However, in accepting such obligations, You may act only
|
|
||||||
on Your own behalf and on Your sole responsibility, not on behalf
|
|
||||||
of any other Contributor, and only if You agree to indemnify,
|
|
||||||
defend, and hold each Contributor harmless for any liability
|
|
||||||
incurred by, or claims asserted against, such Contributor by reason
|
|
||||||
of your accepting any such warranty or additional liability.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
APPENDIX: How to apply the Apache License to your work.
|
|
||||||
|
|
||||||
To apply the Apache License to your work, attach the following
|
|
||||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
||||||
replaced with your own identifying information. (Don't include
|
|
||||||
the brackets!) The text should be enclosed in the appropriate
|
|
||||||
comment syntax for the file format. We also recommend that a
|
|
||||||
file or class name and description of purpose be included on the
|
|
||||||
same "printed page" as the copyright notice for easier
|
|
||||||
identification within third-party archives.
|
|
||||||
|
|
||||||
Copyright [yyyy] [name of copyright owner]
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
|
@ -1,120 +0,0 @@
|
||||||
|
|
||||||
ijar: A tool for generating interface .jars from normal .jars
|
|
||||||
=============================================================
|
|
||||||
|
|
||||||
Alan Donovan, 26 May 2007.
|
|
||||||
|
|
||||||
Rationale:
|
|
||||||
|
|
||||||
In order to improve the speed of compilation of Java programs in
|
|
||||||
Bazel, the output of build steps is cached.
|
|
||||||
|
|
||||||
This works very nicely for C++ compilation: a compilation unit
|
|
||||||
includes a .cc source file and typically dozens of header files.
|
|
||||||
Header files change relatively infrequently, so the need for a
|
|
||||||
rebuild is usually driven by a change in the .cc file. Even after
|
|
||||||
syncing a slightly newer version of the tree and doing a rebuild,
|
|
||||||
many hits in the cache are still observed.
|
|
||||||
|
|
||||||
In Java, by contrast, a compilation unit involves a set of .java
|
|
||||||
source files, plus a set of .jar files containing already-compiled
|
|
||||||
JVM .class files. Class files serve a dual purpose: from the JVM's
|
|
||||||
perspective, they are containers of executable code, but from the
|
|
||||||
compiler's perspective, they are interface definitions. The problem
|
|
||||||
here is that .jar files are very much more sensitive to change than
|
|
||||||
C++ header files, so even a change that is insignificant to the
|
|
||||||
compiler (such as the addition of a print statement to a method in a
|
|
||||||
prerequisite class) will cause the jar to change, and any code that
|
|
||||||
depends on this jar's interface will be recompiled unnecessarily.
|
|
||||||
|
|
||||||
The purpose of ijar is to produce, from a .jar file, a much smaller,
|
|
||||||
simpler .jar file containing only the parts that are significant for
|
|
||||||
the purposes of compilation. In other words, an interface .jar
|
|
||||||
file. By changing ones compilation dependencies to be the interface
|
|
||||||
jar files, unnecessary recompilation is avoided when upstream
|
|
||||||
changes don't affect the interface.
|
|
||||||
|
|
||||||
Details:
|
|
||||||
|
|
||||||
ijar is a tool that reads a .jar file and emits a .jar file
|
|
||||||
containing only the parts that are relevant to Java compilation.
|
|
||||||
For example, it throws away:
|
|
||||||
|
|
||||||
- Files whose name does not end in ".class".
|
|
||||||
- All executable method code.
|
|
||||||
- All private methods and fields.
|
|
||||||
- All constants and attributes except the minimal set necessary to
|
|
||||||
describe the class interface.
|
|
||||||
- All debugging information
|
|
||||||
(LineNumberTable, SourceFile, LocalVariableTables attributes).
|
|
||||||
|
|
||||||
It also sets to zero the file modification times in the index of the
|
|
||||||
.jar file.
|
|
||||||
|
|
||||||
Implementation:
|
|
||||||
|
|
||||||
ijar is implemented in C++, and runs very quickly. For example
|
|
||||||
(when optimized) it takes only 530ms to process a 42MB
|
|
||||||
.jar file containing 5878 classe, resulting in an interface .jar
|
|
||||||
file of only 11.4MB in size. For more usual .jar sizes of a few
|
|
||||||
megabytes, a runtime of 50ms is typical.
|
|
||||||
|
|
||||||
The implementation strategy is to mmap both the input jar and the
|
|
||||||
newly-created _interface.jar, and to scan through the former and
|
|
||||||
emit the latter in a single pass. There are a couple of locations
|
|
||||||
where some kind of "backpatching" is required:
|
|
||||||
|
|
||||||
- in the .zip file format, for each file, the size field precedes
|
|
||||||
the data. We emit a zero but note its location, generate and emit
|
|
||||||
the stripped classfile, then poke the correct size into the
|
|
||||||
location.
|
|
||||||
|
|
||||||
- for JVM .class files, the header (including the constant table)
|
|
||||||
precedes the body, but cannot be emitted before it because it's
|
|
||||||
not until we emit the body that we know which constants are
|
|
||||||
referenced and which are garbage. So we emit the body into a
|
|
||||||
temporary buffer, then emit the header to the output jar, followed
|
|
||||||
by the contents of the temp buffer.
|
|
||||||
|
|
||||||
Also note that the zip file format has unnecessary duplication of
|
|
||||||
the index metadata: it has header+data for each file, then another
|
|
||||||
set of (similar) headers at the end. Rather than save the metadata
|
|
||||||
explicitly in some datastructure, we just record the addresses of
|
|
||||||
the already-emitted zip metadata entries in the output file, and
|
|
||||||
then read from there as necessary.
|
|
||||||
|
|
||||||
Notes:
|
|
||||||
|
|
||||||
This code has no dependency except on the STL and on zlib.
|
|
||||||
|
|
||||||
Almost all of the getX/putX/ReadX/WriteX functions in the code
|
|
||||||
advance their first argument pointer, which is passed by reference.
|
|
||||||
|
|
||||||
It's tempting to discard package-private classes and class members.
|
|
||||||
However, this would be incorrect because they are a necessary part
|
|
||||||
of the package interface, as a Java package is often compiled in
|
|
||||||
multiple stages. For example: in Bazel, both java tests and java
|
|
||||||
code inhabit the same Java package but are compiled separately.
|
|
||||||
|
|
||||||
Assumptions:
|
|
||||||
|
|
||||||
We assume that jar files are uncompressed v1.0 zip files (created
|
|
||||||
with 'jar c0f') with a zero general_purpose_bit_flag.
|
|
||||||
|
|
||||||
We assume that javap/javac don't need the correct CRC checksums in
|
|
||||||
the .jar file.
|
|
||||||
|
|
||||||
We assume that it's better simply to abort in the face of unknown
|
|
||||||
input than to risk leaving out something important from the output
|
|
||||||
(although in the case of annotations, it should be safe to ignore
|
|
||||||
ones we don't understand).
|
|
||||||
|
|
||||||
TODO:
|
|
||||||
Maybe: ensure a canonical sort order is used for every list (jar
|
|
||||||
entries, class members, attributes, etc.) This isn't essential
|
|
||||||
because we can assume the compiler is deterministic and the order in
|
|
||||||
the source files changes little. Also, it would require two passes. :(
|
|
||||||
|
|
||||||
Maybe: delete dynamically-allocated memory.
|
|
||||||
|
|
||||||
Add (a lot) more tests. Include a test of idempotency.
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,102 +0,0 @@
|
||||||
// Copyright 2001,2007 Alan Donovan. All rights reserved.
|
|
||||||
//
|
|
||||||
// Author: Alan Donovan <adonovan@google.com>
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
// common.h -- common definitions.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef INCLUDED_DEVTOOLS_IJAR_COMMON_H
|
|
||||||
#define INCLUDED_DEVTOOLS_IJAR_COMMON_H
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
namespace devtools_ijar {
|
|
||||||
|
|
||||||
typedef unsigned long long u8;
|
|
||||||
typedef uint32_t u4;
|
|
||||||
typedef uint16_t u2;
|
|
||||||
typedef uint8_t u1;
|
|
||||||
|
|
||||||
// be = big endian, le = little endian
|
|
||||||
|
|
||||||
inline u1 get_u1(const u1 *&p) {
|
|
||||||
return *p++;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline u2 get_u2be(const u1 *&p) {
|
|
||||||
u4 x = (p[0] << 8) | p[1];
|
|
||||||
p += 2;
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline u2 get_u2le(const u1 *&p) {
|
|
||||||
u4 x = (p[1] << 8) | p[0];
|
|
||||||
p += 2;
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline u4 get_u4be(const u1 *&p) {
|
|
||||||
u4 x = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
|
|
||||||
p += 4;
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline u4 get_u4le(const u1 *&p) {
|
|
||||||
u4 x = (p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0];
|
|
||||||
p += 4;
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void put_u1(u1 *&p, u1 x) {
|
|
||||||
*p++ = x;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void put_u2be(u1 *&p, u2 x) {
|
|
||||||
*p++ = x >> 8;
|
|
||||||
*p++ = x & 0xff;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void put_u2le(u1 *&p, u2 x) {
|
|
||||||
*p++ = x & 0xff;
|
|
||||||
*p++ = x >> 8;;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void put_u4be(u1 *&p, u4 x) {
|
|
||||||
*p++ = x >> 24;
|
|
||||||
*p++ = (x >> 16) & 0xff;
|
|
||||||
*p++ = (x >> 8) & 0xff;
|
|
||||||
*p++ = x & 0xff;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void put_u4le(u1 *&p, u4 x) {
|
|
||||||
*p++ = x & 0xff;
|
|
||||||
*p++ = (x >> 8) & 0xff;
|
|
||||||
*p++ = (x >> 16) & 0xff;
|
|
||||||
*p++ = x >> 24;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy n bytes from src to p, and advance p.
|
|
||||||
inline void put_n(u1 *&p, const u1 *src, size_t n) {
|
|
||||||
memcpy(p, src, n);
|
|
||||||
p += n;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern bool verbose;
|
|
||||||
|
|
||||||
} // namespace devtools_ijar
|
|
||||||
|
|
||||||
#endif // INCLUDED_DEVTOOLS_IJAR_COMMON_H
|
|
|
@ -1,182 +0,0 @@
|
||||||
// Copyright 2001,2007 Alan Donovan. All rights reserved.
|
|
||||||
//
|
|
||||||
// Author: Alan Donovan <adonovan@google.com>
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
// ijar.cpp -- .jar -> _interface.jar tool.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#include "zip.h"
|
|
||||||
|
|
||||||
namespace devtools_ijar {
|
|
||||||
|
|
||||||
bool verbose = false;
|
|
||||||
|
|
||||||
// Reads a JVM class from classdata_in (of the specified length), and
|
|
||||||
// writes out a simplified class to classdata_out, advancing the
|
|
||||||
// pointer.
|
|
||||||
void StripClass(u1 *&classdata_out, const u1 *classdata_in, size_t in_length);
|
|
||||||
|
|
||||||
const char* CLASS_EXTENSION = ".class";
|
|
||||||
const size_t CLASS_EXTENSION_LENGTH = strlen(CLASS_EXTENSION);
|
|
||||||
|
|
||||||
// ZipExtractorProcessor that select only .class file and use
|
|
||||||
// StripClass to generate an interface class, storing as a new file
|
|
||||||
// in the specified ZipBuilder.
|
|
||||||
class JarStripperProcessor : public ZipExtractorProcessor {
|
|
||||||
public:
|
|
||||||
JarStripperProcessor() {}
|
|
||||||
virtual ~JarStripperProcessor() {}
|
|
||||||
|
|
||||||
virtual void Process(const char* filename, const u4 attr,
|
|
||||||
const u1* data, const size_t size);
|
|
||||||
virtual bool Accept(const char* filename, const u4 attr);
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Not owned by JarStripperProcessor, see SetZipBuilder().
|
|
||||||
ZipBuilder* builder;
|
|
||||||
|
|
||||||
public:
|
|
||||||
// Set the ZipBuilder to add the ijar class to the output zip file.
|
|
||||||
// This pointer should not be deleted while this class is still in use and
|
|
||||||
// it should be set before any call to the Process() method.
|
|
||||||
void SetZipBuilder(ZipBuilder* builder) {
|
|
||||||
this->builder = builder;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
bool JarStripperProcessor::Accept(const char* filename, const u4) {
|
|
||||||
ssize_t offset = strlen(filename) - CLASS_EXTENSION_LENGTH;
|
|
||||||
if (offset >= 0) {
|
|
||||||
return strcmp(filename + offset, CLASS_EXTENSION) == 0;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void JarStripperProcessor::Process(const char* filename, const u4,
|
|
||||||
const u1* data, const size_t size) {
|
|
||||||
if (verbose) {
|
|
||||||
fprintf(stderr, "INFO: StripClass: %s\n", filename);
|
|
||||||
}
|
|
||||||
u1 *q = builder->NewFile(filename, 0);
|
|
||||||
u1 *classdata_out = q;
|
|
||||||
StripClass(q, data, size); // actually process it
|
|
||||||
size_t out_length = q - classdata_out;
|
|
||||||
builder->FinishFile(out_length);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Opens "file_in" (a .jar file) for reading, and writes an interface
|
|
||||||
// .jar to "file_out".
|
|
||||||
void OpenFilesAndProcessJar(const char *file_out, const char *file_in) {
|
|
||||||
JarStripperProcessor processor;
|
|
||||||
std::unique_ptr<ZipExtractor> in(ZipExtractor::Create(file_in, &processor));
|
|
||||||
if (in.get() == NULL) {
|
|
||||||
fprintf(stderr, "Unable to open Zip file %s: %s\n", file_in,
|
|
||||||
strerror(errno));
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
u8 output_length = in->CalculateOutputLength();
|
|
||||||
std::unique_ptr<ZipBuilder> out(ZipBuilder::Create(file_out, output_length));
|
|
||||||
if (out.get() == NULL) {
|
|
||||||
fprintf(stderr, "Unable to open output file %s: %s\n", file_out,
|
|
||||||
strerror(errno));
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
processor.SetZipBuilder(out.get());
|
|
||||||
|
|
||||||
// Process all files in the zip
|
|
||||||
if (in->ProcessAll() < 0) {
|
|
||||||
fprintf(stderr, "%s\n", in->GetError());
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add dummy file, since javac doesn't like truly empty jars.
|
|
||||||
if (out->GetNumberFiles() == 0) {
|
|
||||||
out->WriteEmptyFile("dummy");
|
|
||||||
}
|
|
||||||
// Finish writing the output file
|
|
||||||
if (out->Finish() < 0) {
|
|
||||||
fprintf(stderr, "%s\n", out->GetError());
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
// Get all file size
|
|
||||||
size_t in_length = in->GetSize();
|
|
||||||
size_t out_length = out->GetSize();
|
|
||||||
if (verbose) {
|
|
||||||
fprintf(stderr, "INFO: produced interface jar: %s -> %s (%d%%).\n",
|
|
||||||
file_in, file_out,
|
|
||||||
static_cast<int>(100.0 * out_length / in_length));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace devtools_ijar
|
|
||||||
|
|
||||||
//
|
|
||||||
// main method
|
|
||||||
//
|
|
||||||
static void usage() {
|
|
||||||
fprintf(stderr, "Usage: ijar [-v] x.jar [x_interface.jar>]\n");
|
|
||||||
fprintf(stderr, "Creates an interface jar from the specified jar file.\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
|
||||||
const char *filename_in = NULL;
|
|
||||||
const char *filename_out = NULL;
|
|
||||||
|
|
||||||
for (int ii = 1; ii < argc; ++ii) {
|
|
||||||
if (strcmp(argv[ii], "-v") == 0) {
|
|
||||||
devtools_ijar::verbose = true;
|
|
||||||
} else if (filename_in == NULL) {
|
|
||||||
filename_in = argv[ii];
|
|
||||||
} else if (filename_out == NULL) {
|
|
||||||
filename_out = argv[ii];
|
|
||||||
} else {
|
|
||||||
usage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filename_in == NULL) {
|
|
||||||
usage();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Guess output filename from input:
|
|
||||||
char filename_out_buf[PATH_MAX];
|
|
||||||
if (filename_out == NULL) {
|
|
||||||
size_t len = strlen(filename_in);
|
|
||||||
if (len > 4 && strncmp(filename_in + len - 4, ".jar", 4) == 0) {
|
|
||||||
strcpy(filename_out_buf, filename_in);
|
|
||||||
strcpy(filename_out_buf + len - 4, "-interface.jar");
|
|
||||||
filename_out = filename_out_buf;
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "Can't determine output filename since input filename "
|
|
||||||
"doesn't end with '.jar'.\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (devtools_ijar::verbose) {
|
|
||||||
fprintf(stderr, "INFO: writing to '%s'.\n", filename_out);
|
|
||||||
}
|
|
||||||
|
|
||||||
devtools_ijar::OpenFilesAndProcessJar(filename_out, filename_in);
|
|
||||||
return 0;
|
|
||||||
}
|
|
1032
tools/ijar/zip.cc
1032
tools/ijar/zip.cc
File diff suppressed because it is too large
Load Diff
173
tools/ijar/zip.h
173
tools/ijar/zip.h
|
@ -1,173 +0,0 @@
|
||||||
// Copyright 2015 Google Inc. All rights reserved.
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
// zip.h -- .zip (.jar) file reading/writing routines.
|
|
||||||
//
|
|
||||||
// This file specifies the interface to use the ZIP implementation of ijar.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef INCLUDED_THIRD_PARTY_IJAR_ZIP_H
|
|
||||||
#define INCLUDED_THIRD_PARTY_IJAR_ZIP_H
|
|
||||||
|
|
||||||
#include <sys/stat.h>
|
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
namespace devtools_ijar {
|
|
||||||
|
|
||||||
// Tells if this is a directory entry from the mode. This method
|
|
||||||
// is safer than zipattr_to_mode(attr) & S_IFDIR because the unix
|
|
||||||
// mode might not be set in DOS zip files.
|
|
||||||
inline bool zipattr_is_dir(u4 attr) { return (attr & 0x10) != 0; }
|
|
||||||
|
|
||||||
// Convert a Unix file mode to a ZIP file attribute
|
|
||||||
inline u4 mode_to_zipattr(mode_t m) {
|
|
||||||
return (((u4) m) << 16) + ((m & S_IFDIR) != 0 ? 0x10 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert a ZIP file attribute to a Unix file mode
|
|
||||||
inline mode_t zipattr_to_mode(u4 attr) {
|
|
||||||
return ((mode_t) ((attr >> 16) & 0xffff));
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Class interface for building ZIP files
|
|
||||||
//
|
|
||||||
class ZipBuilder {
|
|
||||||
public:
|
|
||||||
virtual ~ZipBuilder() {}
|
|
||||||
|
|
||||||
// Returns the text for the last error, or null on no last error.
|
|
||||||
virtual const char* GetError() = 0;
|
|
||||||
|
|
||||||
// Add a new file to the ZIP, the file will have path "filename"
|
|
||||||
// and external attributes "attr". This function returns a pointer
|
|
||||||
// to a memory buffer to write the data of the file into. This buffer
|
|
||||||
// is owned by ZipBuilder and should not be free'd by the caller. The
|
|
||||||
// file length is then specified when the files is finished written
|
|
||||||
// using the FinishFile(size_t) function.
|
|
||||||
// On failure, returns NULL and GetError() will return an non-empty message.
|
|
||||||
virtual u1* NewFile(const char* filename, const u4 attr) = 0;
|
|
||||||
|
|
||||||
// Finish writing a file and specify its length. After calling this method
|
|
||||||
// one should not reuse the pointer given by NewFile. The file can be
|
|
||||||
// compressed using the deflate algorithm by setting `compress` to true.
|
|
||||||
// By default, CRC32 are not computed as java tooling doesn't care, but
|
|
||||||
// computing it can be activated by setting `compute_crc` to true.
|
|
||||||
// On failure, returns -1 and GetError() will return an non-empty message.
|
|
||||||
virtual int FinishFile(size_t filelength,
|
|
||||||
bool compress = false,
|
|
||||||
bool compute_crc = false) = 0;
|
|
||||||
|
|
||||||
// Write an empty file, it is equivalent to:
|
|
||||||
// NewFile(filename, 0);
|
|
||||||
// FinishFile(0);
|
|
||||||
// On failure, returns -1 and GetError() will return an non-empty message.
|
|
||||||
virtual int WriteEmptyFile(const char* filename) = 0;
|
|
||||||
|
|
||||||
// Finish writing the ZIP file. This method can be called only once
|
|
||||||
// (subsequent calls will do nothing) and none of
|
|
||||||
// NewFile/FinishFile/WriteEmptyFile should be called after calling Finish. If
|
|
||||||
// this method was not called when the object is destroyed, it will be called.
|
|
||||||
// It is here as a convenience to get information on the final generated ZIP
|
|
||||||
// file.
|
|
||||||
// On failure, returns -1 and GetError() will return an non-empty message.
|
|
||||||
virtual int Finish() = 0;
|
|
||||||
|
|
||||||
// Get the current size of the ZIP file. This size will not be matching the
|
|
||||||
// final ZIP file until Finish() has been called because Finish() is actually
|
|
||||||
// writing the central directory of the ZIP File.
|
|
||||||
virtual size_t GetSize() = 0;
|
|
||||||
|
|
||||||
// Returns the current number of files stored in the ZIP.
|
|
||||||
virtual int GetNumberFiles() = 0;
|
|
||||||
|
|
||||||
// Create a new ZipBuilder writing the file zip_file and the size of the
|
|
||||||
// output will be at most estimated_size. Use ZipBuilder::EstimateSize() or
|
|
||||||
// ZipExtractor::CalculateOuputLength() to have an estimated_size depending on
|
|
||||||
// a list of file to store.
|
|
||||||
// On failure, returns NULL. Refer to errno for error code.
|
|
||||||
static ZipBuilder* Create(const char* zip_file, u8 estimated_size);
|
|
||||||
|
|
||||||
// Estimate the maximum size of the ZIP files containing files in the "files"
|
|
||||||
// null-terminated array.
|
|
||||||
// Returns 0 on error.
|
|
||||||
static u8 EstimateSize(char **files);
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// An abstract class to process data from a ZipExtractor.
|
|
||||||
// Derive from this class if you wish to process data from a ZipExtractor.
|
|
||||||
//
|
|
||||||
class ZipExtractorProcessor {
|
|
||||||
public:
|
|
||||||
virtual ~ZipExtractorProcessor() {}
|
|
||||||
|
|
||||||
// Tells whether to skip or process the file "filename". "attr" is the
|
|
||||||
// external file attributes and can be converted to unix mode using the
|
|
||||||
// zipattr_to_mode() function. This method is suppoed to returns true
|
|
||||||
// if the file should be processed and false if it should be skipped.
|
|
||||||
virtual bool Accept(const char* filename, const u4 attr) = 0;
|
|
||||||
|
|
||||||
// Process a file accepted by Accept. The file "filename" has external
|
|
||||||
// attributes "attr" and length "size". The file content is accessible
|
|
||||||
// in the buffer pointed by "data".
|
|
||||||
virtual void Process(const char* filename, const u4 attr,
|
|
||||||
const u1* data, const size_t size) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// Class interface for reading ZIP files
|
|
||||||
//
|
|
||||||
class ZipExtractor {
|
|
||||||
public:
|
|
||||||
virtual ~ZipExtractor() {}
|
|
||||||
|
|
||||||
// Returns the text for the last error, or null on no last error.
|
|
||||||
virtual const char* GetError() = 0;
|
|
||||||
|
|
||||||
// Process the next files, returns false if the end of ZIP file has been
|
|
||||||
// reached. The processor provided by the Create method will be called
|
|
||||||
// if a file is encountered. If false is returned, check the return value
|
|
||||||
// of GetError() for potential errors.
|
|
||||||
virtual bool ProcessNext() = 0;
|
|
||||||
|
|
||||||
// Process the all files, returns -1 on error (GetError() will be populated
|
|
||||||
// on error).
|
|
||||||
virtual int ProcessAll();
|
|
||||||
|
|
||||||
// Reset the file pointer to the beginning.
|
|
||||||
virtual void Reset() = 0;
|
|
||||||
|
|
||||||
// Return the size of the ZIP file.
|
|
||||||
virtual size_t GetSize() = 0;
|
|
||||||
|
|
||||||
// Return the size of the resulting zip file by keeping only file
|
|
||||||
// accepted by the processor and storing them uncompressed. This
|
|
||||||
// method can be used to create a ZipBuilder for storing a subset
|
|
||||||
// of the input files.
|
|
||||||
// On error, 0 is returned and GetError() returns a non-empty message.
|
|
||||||
virtual u8 CalculateOutputLength() = 0;
|
|
||||||
|
|
||||||
// Create a ZipExtractor that extract the zip file "filename" and process
|
|
||||||
// it with "processor".
|
|
||||||
// On error, a null pointer is returned and the value of errno should be
|
|
||||||
// checked.
|
|
||||||
static ZipExtractor* Create(const char* filename,
|
|
||||||
ZipExtractorProcessor *processor);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace devtools_ijar
|
|
||||||
|
|
||||||
#endif // INCLUDED_THIRD_PARTY_IJAR_ZIP_H
|
|
|
@ -1,312 +0,0 @@
|
||||||
// Copyright 2015 Google Inc. All rights reserved.
|
|
||||||
//
|
|
||||||
// Author: Alan Donovan <adonovan@google.com>
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
|
|
||||||
//
|
|
||||||
// Zip / Unzip file using ijar zip implementation.
|
|
||||||
//
|
|
||||||
// Note that this Zip implementation intentionally don't compute CRC-32
|
|
||||||
// because it is useless computation for jar because Java doesn't care.
|
|
||||||
// CRC-32 of all files in the zip file will be set to 0.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/mman.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#include "zip.h"
|
|
||||||
|
|
||||||
namespace devtools_ijar {
|
|
||||||
|
|
||||||
#define SYSCALL(expr) do { \
|
|
||||||
if ((expr) < 0) { \
|
|
||||||
perror(#expr); \
|
|
||||||
abort(); \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
//
|
|
||||||
// A ZipExtractorProcessor that extract all files in the ZIP file.
|
|
||||||
//
|
|
||||||
class UnzipProcessor : public ZipExtractorProcessor {
|
|
||||||
public:
|
|
||||||
// Create a processor who will extract the files into output_root
|
|
||||||
// if "extract" is set to true and will print the list of files and
|
|
||||||
// their unix modes if "verbose" is set to true.
|
|
||||||
UnzipProcessor(const char *output_root, bool verbose, bool extract)
|
|
||||||
: output_root_(output_root), verbose_(verbose), extract_(extract) {}
|
|
||||||
virtual ~UnzipProcessor() {}
|
|
||||||
|
|
||||||
virtual void Process(const char* filename, const u4 attr,
|
|
||||||
const u1* data, const size_t size);
|
|
||||||
virtual bool Accept(const char* filename, const u4 attr) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
const char *output_root_;
|
|
||||||
const bool verbose_;
|
|
||||||
const bool extract_;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Concatene 2 path, path1 and path2, using / as a directory separator and
|
|
||||||
// puting the result in "out". "size" specify the size of the output buffer
|
|
||||||
void concat_path(char* out, const size_t size,
|
|
||||||
const char *path1, const char *path2) {
|
|
||||||
int len1 = strlen(path1);
|
|
||||||
size_t l = len1;
|
|
||||||
strncpy(out, path1, size - 1);
|
|
||||||
out[size-1] = 0;
|
|
||||||
if (l < size - 1 && path1[len1] != '/' && path2[0] != '/') {
|
|
||||||
out[l] = '/';
|
|
||||||
l++;
|
|
||||||
out[l] = 0;
|
|
||||||
}
|
|
||||||
if (l < size - 1) {
|
|
||||||
strncat(out, path2, size - 1 - l);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do a recursive mkdir of all folders of path except the last path
|
|
||||||
// segment (if path ends with a / then the last path segment is empty).
|
|
||||||
// All folders are created using "mode" for creation mode.
|
|
||||||
void mkdirs(const char *path, mode_t mode) {
|
|
||||||
char path_[PATH_MAX];
|
|
||||||
struct stat statst;
|
|
||||||
strncpy(path_, path, PATH_MAX);
|
|
||||||
path_[PATH_MAX-1] = 0;
|
|
||||||
char *pointer = path_;
|
|
||||||
while ((pointer = strchr(pointer, '/')) != NULL) {
|
|
||||||
if (path_ != pointer) { // skip leading slash
|
|
||||||
*pointer = 0;
|
|
||||||
if (stat(path_, &statst) != 0) {
|
|
||||||
if (mkdir(path_, mode) < 0) {
|
|
||||||
fprintf(stderr, "Cannot create folder %s: %s\n",
|
|
||||||
path_, strerror(errno));
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*pointer = '/';
|
|
||||||
}
|
|
||||||
pointer++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void UnzipProcessor::Process(const char* filename, const u4 attr,
|
|
||||||
const u1* data, const size_t size) {
|
|
||||||
mode_t mode = zipattr_to_mode(attr);
|
|
||||||
mode_t perm = mode & 0777;
|
|
||||||
bool isdir = (mode & S_IFDIR) != 0;
|
|
||||||
if (attr == 0) {
|
|
||||||
// Fallback when the external attribute is not set.
|
|
||||||
isdir = filename[strlen(filename)-1] == '/';
|
|
||||||
perm = 0777;
|
|
||||||
}
|
|
||||||
if (verbose_) {
|
|
||||||
printf("%c %o %s\n", isdir ? 'd' : 'f', perm, filename);
|
|
||||||
}
|
|
||||||
if (extract_) {
|
|
||||||
char path[PATH_MAX];
|
|
||||||
int fd;
|
|
||||||
concat_path(path, PATH_MAX, output_root_, filename);
|
|
||||||
mkdirs(path, perm);
|
|
||||||
if (!isdir) {
|
|
||||||
fd = open(path, O_CREAT | O_WRONLY, perm);
|
|
||||||
if (fd < 0) {
|
|
||||||
fprintf(stderr, "Cannot open file %s for writing: %s\n",
|
|
||||||
path, strerror(errno));
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
SYSCALL(write(fd, data, size));
|
|
||||||
SYSCALL(close(fd));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the basename of path and store it in output. output_size
|
|
||||||
// is the size of the output buffer.
|
|
||||||
void basename(const char *path, char *output, size_t output_size) {
|
|
||||||
const char *pointer = strrchr(path, '/');
|
|
||||||
if (pointer == NULL) {
|
|
||||||
pointer = path;
|
|
||||||
} else {
|
|
||||||
pointer++; // Skip the leading slash.
|
|
||||||
}
|
|
||||||
strncpy(output, pointer, output_size);
|
|
||||||
output[output_size-1] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Execute the extraction (or just listing if just v is provided)
|
|
||||||
int extract(char *zipfile, bool verbose, bool extract) {
|
|
||||||
char output_root[PATH_MAX];
|
|
||||||
getcwd(output_root, PATH_MAX);
|
|
||||||
|
|
||||||
UnzipProcessor processor(output_root, verbose, extract);
|
|
||||||
std::unique_ptr<ZipExtractor> extractor(ZipExtractor::Create(zipfile,
|
|
||||||
&processor));
|
|
||||||
if (extractor.get() == NULL) {
|
|
||||||
fprintf(stderr, "Unable to open zip file %s: %s.\n", zipfile,
|
|
||||||
strerror(errno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (extractor->ProcessAll() < 0) {
|
|
||||||
fprintf(stderr, "%s.\n", extractor->GetError());
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Execute the create operation
|
|
||||||
int create(char *zipfile, char **files, bool flatten, bool verbose,
|
|
||||||
bool compress) {
|
|
||||||
struct stat statst;
|
|
||||||
u8 size = ZipBuilder::EstimateSize(files);
|
|
||||||
if (size == 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
std::unique_ptr<ZipBuilder> builder(ZipBuilder::Create(zipfile, size));
|
|
||||||
if (builder.get() == NULL) {
|
|
||||||
fprintf(stderr, "Unable to create zip file %s: %s.\n",
|
|
||||||
zipfile, strerror(errno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
for (int i = 0; files[i] != NULL; i++) {
|
|
||||||
stat(files[i], &statst);
|
|
||||||
char path[PATH_MAX];
|
|
||||||
bool isdir = (statst.st_mode & S_IFDIR) != 0;
|
|
||||||
|
|
||||||
if (flatten && isdir) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compute the path, flattening it if requested
|
|
||||||
if (flatten) {
|
|
||||||
basename(files[i], path, PATH_MAX);
|
|
||||||
} else {
|
|
||||||
strncpy(path, files[i], PATH_MAX);
|
|
||||||
path[PATH_MAX-1] = 0;
|
|
||||||
size_t len = strlen(path);
|
|
||||||
if (isdir && len < PATH_MAX - 1) {
|
|
||||||
// Add the trailing slash for folders
|
|
||||||
path[len] = '/';
|
|
||||||
path[len+1] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (verbose) {
|
|
||||||
mode_t perm = statst.st_mode & 0777;
|
|
||||||
printf("%c %o %s\n", isdir ? 'd' : 'f', perm, path);
|
|
||||||
}
|
|
||||||
|
|
||||||
u1 *buffer = builder->NewFile(path, mode_to_zipattr(statst.st_mode));
|
|
||||||
if (isdir || statst.st_size == 0) {
|
|
||||||
builder->FinishFile(0);
|
|
||||||
} else {
|
|
||||||
// mmap the input file and memcpy
|
|
||||||
int fd = open(files[i], O_RDONLY);
|
|
||||||
if (fd < 0) {
|
|
||||||
fprintf(stderr, "Can't open file %s for reading: %s.\n",
|
|
||||||
files[i], strerror(errno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
void *data = mmap(NULL, statst.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
|
|
||||||
if (data == MAP_FAILED) {
|
|
||||||
fprintf(stderr, "Can't mmap file %s for reading: %s.\n",
|
|
||||||
files[i], strerror(errno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
memcpy(buffer, data, statst.st_size);
|
|
||||||
munmap(data, statst.st_size);
|
|
||||||
builder->FinishFile(statst.st_size, compress, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (builder->Finish() < 0) {
|
|
||||||
fprintf(stderr, "%s\n", builder->GetError());
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace devtools_ijar
|
|
||||||
|
|
||||||
//
|
|
||||||
// main method
|
|
||||||
//
|
|
||||||
static void usage(char *progname) {
|
|
||||||
fprintf(stderr, "Usage: %s [vxc[fC]] x.zip [file1...filen]\n", progname);
|
|
||||||
fprintf(stderr, " v verbose - list all file in x.zip\n");
|
|
||||||
fprintf(stderr, " x extract - extract file in x.zip in current directory\n");
|
|
||||||
fprintf(stderr, " c create - add files to x.zip\n");
|
|
||||||
fprintf(stderr, " f flatten - flatten files to use with create operation\n");
|
|
||||||
fprintf(stderr,
|
|
||||||
" C compress - compress files when using the create operation\n");
|
|
||||||
fprintf(stderr, "x and c cannot be used in the same command-line.\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
|
||||||
bool extract = false;
|
|
||||||
bool verbose = false;
|
|
||||||
bool create = false;
|
|
||||||
bool compress = false;
|
|
||||||
bool flatten = false;
|
|
||||||
|
|
||||||
if (argc < 3) {
|
|
||||||
usage(argv[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; argv[1][i] != 0; i++) {
|
|
||||||
switch (argv[1][i]) {
|
|
||||||
case 'x':
|
|
||||||
extract = true;
|
|
||||||
break;
|
|
||||||
case 'v':
|
|
||||||
verbose = true;
|
|
||||||
break;
|
|
||||||
case 'c':
|
|
||||||
create = true;
|
|
||||||
break;
|
|
||||||
case 'f':
|
|
||||||
flatten = true;
|
|
||||||
break;
|
|
||||||
case 'C':
|
|
||||||
compress = true;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
usage(argv[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (create) {
|
|
||||||
if (extract) {
|
|
||||||
usage(argv[0]);
|
|
||||||
}
|
|
||||||
// Create a zip
|
|
||||||
return devtools_ijar::create(argv[2], argv + 3, flatten, verbose, compress);
|
|
||||||
} else {
|
|
||||||
if (flatten) {
|
|
||||||
usage(argv[0]);
|
|
||||||
}
|
|
||||||
// Extraction / list mode
|
|
||||||
return devtools_ijar::extract(argv[2], verbose, extract);
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue